summaryrefslogtreecommitdiff
path: root/chromium/services
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/services')
-rw-r--r--chromium/services/BUILD.gn4
-rw-r--r--chromium/services/OWNERS3
-rw-r--r--chromium/services/audio/BUILD.gn51
-rw-r--r--chromium/services/audio/audio_processor.cc100
-rw-r--r--chromium/services/audio/audio_processor.h56
-rw-r--r--chromium/services/audio/debug_recording.h3
-rw-r--r--chromium/services/audio/debug_recording_unittest.cc5
-rw-r--r--chromium/services/audio/delay_buffer.h7
-rw-r--r--chromium/services/audio/device_listener_output_stream.cc114
-rw-r--r--chromium/services/audio/device_listener_output_stream.h81
-rw-r--r--chromium/services/audio/device_listener_output_stream_unittest.cc323
-rw-r--r--chromium/services/audio/device_notifier.cc2
-rw-r--r--chromium/services/audio/device_notifier_unittest.cc11
-rw-r--r--chromium/services/audio/device_output_listener.h39
-rw-r--r--chromium/services/audio/group_coordinator.h15
-rw-r--r--chromium/services/audio/in_process_audio_manager_accessor.cc3
-rw-r--r--chromium/services/audio/in_process_audio_manager_accessor.h4
-rw-r--r--chromium/services/audio/input_controller.cc38
-rw-r--r--chromium/services/audio/input_controller.h23
-rw-r--r--chromium/services/audio/input_controller_unittest.cc103
-rw-r--r--chromium/services/audio/input_stream.cc3
-rw-r--r--chromium/services/audio/input_stream.h2
-rw-r--r--chromium/services/audio/input_stream_unittest.cc16
-rw-r--r--chromium/services/audio/input_sync_writer.cc54
-rw-r--r--chromium/services/audio/input_sync_writer.h19
-rw-r--r--chromium/services/audio/input_sync_writer_unittest.cc9
-rw-r--r--chromium/services/audio/local_muter.h4
-rw-r--r--chromium/services/audio/log_factory_manager_unittest.cc11
-rw-r--r--chromium/services/audio/loopback_stream.h13
-rw-r--r--chromium/services/audio/loopback_stream_unittest.cc3
-rw-r--r--chromium/services/audio/mixing_graph.cc18
-rw-r--r--chromium/services/audio/mixing_graph.h94
-rw-r--r--chromium/services/audio/mixing_graph_impl.cc215
-rw-r--r--chromium/services/audio/mixing_graph_impl.h115
-rw-r--r--chromium/services/audio/mixing_graph_impl_unittest.cc396
-rw-r--r--chromium/services/audio/mixing_graph_input_unittest.cc406
-rw-r--r--chromium/services/audio/output_controller.cc81
-rw-r--r--chromium/services/audio/output_controller.h43
-rw-r--r--chromium/services/audio/output_controller_unittest.cc228
-rw-r--r--chromium/services/audio/output_device_mixer.cc26
-rw-r--r--chromium/services/audio/output_device_mixer.h83
-rw-r--r--chromium/services/audio/output_device_mixer_impl.cc867
-rw-r--r--chromium/services/audio/output_device_mixer_impl.h184
-rw-r--r--chromium/services/audio/output_device_mixer_impl_unittest.cc1260
-rw-r--r--chromium/services/audio/output_device_mixer_manager.cc316
-rw-r--r--chromium/services/audio/output_device_mixer_manager.h117
-rw-r--r--chromium/services/audio/output_device_mixer_manager_unittest.cc1201
-rw-r--r--chromium/services/audio/output_stream.cc5
-rw-r--r--chromium/services/audio/output_stream.h8
-rw-r--r--chromium/services/audio/output_stream_unittest.cc17
-rw-r--r--chromium/services/audio/owning_audio_manager_accessor.cc10
-rw-r--r--chromium/services/audio/owning_audio_manager_accessor.h4
-rw-r--r--chromium/services/audio/public/cpp/BUILD.gn5
-rw-r--r--chromium/services/audio/public/cpp/debug_recording_session.h6
-rw-r--r--chromium/services/audio/public/cpp/fake_system_info.h1
-rw-r--r--chromium/services/audio/public/cpp/input_ipc.h4
-rw-r--r--chromium/services/audio/public/cpp/output_device.h3
-rw-r--r--chromium/services/audio/public/cpp/sounds/audio_stream_handler.cc3
-rw-r--r--chromium/services/audio/public/cpp/sounds/audio_stream_handler.h1
-rw-r--r--chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc2
-rw-r--r--chromium/services/audio/public/cpp/sounds/sounds_manager.h7
-rw-r--r--chromium/services/audio/public/cpp/sounds/test_data.h5
-rw-r--r--chromium/services/audio/public/mojom/BUILD.gn1
-rw-r--r--chromium/services/audio/public/mojom/audio_service.mojom6
-rw-r--r--chromium/services/audio/reference_output.h39
-rw-r--r--chromium/services/audio/service.cc5
-rw-r--r--chromium/services/audio/service.h1
-rw-r--r--chromium/services/audio/service_metrics.h4
-rw-r--r--chromium/services/audio/snooper_node.h1
-rw-r--r--chromium/services/audio/stream_factory.cc56
-rw-r--r--chromium/services/audio/stream_factory.h9
-rw-r--r--chromium/services/audio/sync_mixing_graph_input.cc95
-rw-r--r--chromium/services/audio/sync_mixing_graph_input.h77
-rw-r--r--chromium/services/audio/sync_reader.cc92
-rw-r--r--chromium/services/audio/sync_reader.h4
-rw-r--r--chromium/services/audio/system_info.h1
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc24
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader_unittest.cc3
-rw-r--r--chromium/services/cert_verifier/cert_verifier_service_unittest.cc9
-rw-r--r--chromium/services/cert_verifier/integration_tests/network_service_unittest.cc2
-rw-r--r--chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc2
-rw-r--r--chromium/services/cert_verifier/public/mojom/trial_comparison_cert_verifier.mojom2
-rw-r--r--chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.cc4
-rw-r--r--chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.h1
-rw-r--r--chromium/services/data_decoder/BUILD.gn24
-rw-r--r--chromium/services/data_decoder/ble_scan_parser_impl.h1
-rw-r--r--chromium/services/data_decoder/data_decoder_service.cc1
-rw-r--r--chromium/services/data_decoder/data_decoder_service.h1
-rw-r--r--chromium/services/data_decoder/image_decoder_impl.h1
-rw-r--r--chromium/services/data_decoder/image_decoder_impl_unittest.cc15
-rw-r--r--chromium/services/data_decoder/json_parser_impl.h1
-rw-r--r--chromium/services/data_decoder/public/cpp/data_decoder.cc5
-rw-r--r--chromium/services/data_decoder/public/cpp/data_decoder.h1
-rw-r--r--chromium/services/data_decoder/public/cpp/decode_image.cc10
-rw-r--r--chromium/services/data_decoder/public/cpp/decode_image.h12
-rw-r--r--chromium/services/data_decoder/public/cpp/json_sanitizer.h7
-rw-r--r--chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc21
-rw-r--r--chromium/services/data_decoder/public/cpp/safe_xml_parser.cc1
-rw-r--r--chromium/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h3
-rw-r--r--chromium/services/data_decoder/public/mojom/BUILD.gn2
-rw-r--r--chromium/services/data_decoder/web_bundle_builder.cc153
-rw-r--r--chromium/services/data_decoder/web_bundle_builder.h56
-rw-r--r--chromium/services/data_decoder/web_bundle_builder_unittest.cc80
-rw-r--r--chromium/services/data_decoder/web_bundler.cc27
-rw-r--r--chromium/services/data_decoder/xml_parser.h1
-rw-r--r--chromium/services/device/BUILD.gn4
-rw-r--r--chromium/services/device/battery/OWNERS2
-rw-r--r--chromium/services/device/battery/battery_monitor_impl.h1
-rw-r--r--chromium/services/device/battery/battery_monitor_impl_unittest.cc4
-rw-r--r--chromium/services/device/battery/battery_status_manager_chromeos.cc6
-rw-r--r--chromium/services/device/battery/battery_status_manager_default.cc1
-rw-r--r--chromium/services/device/battery/battery_status_manager_linux.cc3
-rw-r--r--chromium/services/device/battery/battery_status_manager_linux_unittest.cc22
-rw-r--r--chromium/services/device/battery/battery_status_manager_mac.cc1
-rw-r--r--chromium/services/device/battery/battery_status_manager_win.cc1
-rw-r--r--chromium/services/device/battery/battery_status_service.cc2
-rw-r--r--chromium/services/device/battery/battery_status_service.h1
-rw-r--r--chromium/services/device/battery/battery_status_service_unittest.cc4
-rw-r--r--chromium/services/device/binder_overrides.cc7
-rw-r--r--chromium/services/device/binder_overrides.h12
-rw-r--r--chromium/services/device/bluetooth/bluetooth_system.cc21
-rw-r--r--chromium/services/device/bluetooth/bluetooth_system.h1
-rw-r--r--chromium/services/device/bluetooth/bluetooth_system_factory.h1
-rw-r--r--chromium/services/device/bluetooth/bluetooth_system_unittest.cc101
-rw-r--r--chromium/services/device/device_posture/device_posture_platform_provider.h3
-rw-r--r--chromium/services/device/device_posture/device_posture_provider_impl.h2
-rw-r--r--chromium/services/device/device_service.cc43
-rw-r--r--chromium/services/device/device_service.h20
-rw-r--r--chromium/services/device/device_service_test_base.cc3
-rw-r--r--chromium/services/device/device_service_test_base.h1
-rw-r--r--chromium/services/device/fingerprint/fingerprint_chromeos.h1
-rw-r--r--chromium/services/device/fingerprint/fingerprint_chromeos_unittest.cc1
-rw-r--r--chromium/services/device/generic_sensor/OWNERS2
-rw-r--r--chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h14
-rw-r--r--chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer_unittest.cc4
-rw-r--r--chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.cc6
-rw-r--r--chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.h12
-rw-r--r--chromium/services/device/generic_sensor/fake_platform_sensor_fusion.h6
-rw-r--r--chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc63
-rw-r--r--chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h1
-rw-r--r--chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer_unittest.cc3
-rw-r--r--chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h1
-rw-r--r--chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer_unittest.cc4
-rw-r--r--chromium/services/device/generic_sensor/linux/sensor_device_manager.h9
-rw-r--r--chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h11
-rw-r--r--chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion_unittest.cc4
-rw-r--r--chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h11
-rw-r--r--chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc4
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor.cc60
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor.h33
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_accelerometer_mac.h9
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_ambient_light_mac.h6
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc105
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc43
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_android.h4
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_chromeos.h5
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_fusion.cc16
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_fusion.h13
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_fusion_algorithm.h4
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc52
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_linux.cc5
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_linux.h10
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_base.h10
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc54
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_linux.h15
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_unittest_android.cc1
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_win.cc2
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_winrt.cc2
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_linux.cc2
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_win.cc8
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_win.h3
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h3
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_util.cc27
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_util.h13
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_util_unittest.cc112
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_win.cc13
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_win.h8
-rw-r--r--chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h13
-rw-r--r--chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h13
-rw-r--r--chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope_unittest.cc4
-rw-r--r--chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc3
-rw-r--r--chromium/services/device/generic_sensor/sensor_fusion_algorithm_using_accelerometer_unittest.cc5
-rw-r--r--chromium/services/device/generic_sensor/sensor_impl.h1
-rw-r--r--chromium/services/device/generic_sensor/sensor_provider_impl.h3
-rw-r--r--chromium/services/device/geolocation/OWNERS5
-rw-r--r--chromium/services/device/geolocation/empty_wifi_data_provider.h6
-rw-r--r--chromium/services/device/geolocation/fake_location_provider.h3
-rw-r--r--chromium/services/device/geolocation/fake_position_cache.h1
-rw-r--r--chromium/services/device/geolocation/geolocation_context.h1
-rw-r--r--chromium/services/device/geolocation/geolocation_impl.h4
-rw-r--r--chromium/services/device/geolocation/geolocation_provider_impl.cc2
-rw-r--r--chromium/services/device/geolocation/geolocation_provider_impl.h6
-rw-r--r--chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc18
-rw-r--r--chromium/services/device/geolocation/location_arbitrator.h5
-rw-r--r--chromium/services/device/geolocation/location_arbitrator_unittest.cc9
-rw-r--r--chromium/services/device/geolocation/network_location_provider.cc4
-rw-r--r--chromium/services/device/geolocation/network_location_provider.h6
-rw-r--r--chromium/services/device/geolocation/network_location_provider_unittest.cc33
-rw-r--r--chromium/services/device/geolocation/network_location_request.cc2
-rw-r--r--chromium/services/device/geolocation/network_location_request.h1
-rw-r--r--chromium/services/device/geolocation/position_cache_impl.h4
-rw-r--r--chromium/services/device/geolocation/public_ip_address_geolocation_provider.h1
-rw-r--r--chromium/services/device/geolocation/public_ip_address_geolocator.h4
-rw-r--r--chromium/services/device/geolocation/public_ip_address_location_notifier.h4
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider.h8
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_chromeos.h6
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_common.cc2
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_common.h6
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc17
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_linux.cc1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_linux.h6
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_mac.h6
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_mac.mm1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_manager.h6
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_win.h6
-rw-r--r--chromium/services/device/geolocation/wifi_polling_policy.h1
-rw-r--r--chromium/services/device/geolocation/wifi_polling_policy_unittest.cc3
-rw-r--r--chromium/services/device/geolocation/win/fake_geocoordinate_winrt.h1
-rw-r--r--chromium/services/device/geolocation/win/fake_geoposition_winrt.h2
-rw-r--r--chromium/services/device/geolocation/win/fake_position_changed_event_args_winrt.h2
-rw-r--r--chromium/services/device/geolocation/win/fake_status_changed_event_args_winrt.h2
-rw-r--r--chromium/services/device/hid/hid_connection.h3
-rw-r--r--chromium/services/device/hid/hid_connection_impl.h5
-rw-r--r--chromium/services/device/hid/hid_connection_impl_unittest.cc4
-rw-r--r--chromium/services/device/hid/hid_connection_linux.cc1
-rw-r--r--chromium/services/device/hid/hid_connection_linux.h2
-rw-r--r--chromium/services/device/hid/hid_connection_mac.cc2
-rw-r--r--chromium/services/device/hid/hid_manager_unittest.cc4
-rw-r--r--chromium/services/device/hid/hid_service_linux.cc3
-rw-r--r--chromium/services/device/hid/hid_service_linux.h2
-rw-r--r--chromium/services/device/hid/hid_service_mac.cc3
-rw-r--r--chromium/services/device/hid/hid_service_win.cc2
-rw-r--r--chromium/services/device/hid/input_service_linux.cc6
-rw-r--r--chromium/services/device/hid/input_service_linux.h1
-rw-r--r--chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc8
-rw-r--r--chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h1
-rw-r--r--chromium/services/device/media_transfer_protocol/mtp_device_manager.h2
-rw-r--r--chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java60
-rw-r--r--chromium/services/device/power_monitor/power_monitor_message_broadcaster.h1
-rw-r--r--chromium/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc10
-rw-r--r--chromium/services/device/public/cpp/BUILD.gn7
-rw-r--r--chromium/services/device/public/cpp/device_feature_list.cc1
-rw-r--r--chromium/services/device/public/cpp/device_features.cc4
-rw-r--r--chromium/services/device/public/cpp/device_features.h1
-rw-r--r--chromium/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h1
-rw-r--r--chromium/services/device/public/cpp/hid/hid_collection.cc4
-rw-r--r--chromium/services/device/public/cpp/hid/hid_collection.h3
-rw-r--r--chromium/services/device/public/cpp/hid/hid_item_state_table.h3
-rw-r--r--chromium/services/device/public/cpp/hid/hid_report_descriptor_item.h7
-rw-r--r--chromium/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc1
-rw-r--r--chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc3
-rw-r--r--chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h1
-rw-r--r--chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc12
-rw-r--r--chromium/services/device/public/cpp/usb/usb_ids.h7
-rw-r--r--chromium/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java2
-rw-r--r--chromium/services/device/public/mojom/BUILD.gn3
-rw-r--r--chromium/services/device/screen_orientation/OWNERS1
-rw-r--r--chromium/services/device/screen_orientation/screen_orientation_listener_android.h1
-rw-r--r--chromium/services/device/serial/bluetooth_serial_device_enumerator.cc165
-rw-r--r--chromium/services/device/serial/bluetooth_serial_device_enumerator.h44
-rw-r--r--chromium/services/device/serial/bluetooth_serial_port_impl.cc222
-rw-r--r--chromium/services/device/serial/bluetooth_serial_port_impl.h32
-rw-r--r--chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc470
-rw-r--r--chromium/services/device/serial/fake_serial_device_enumerator.h1
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_linux.h1
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_mac.h1
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_win.cc140
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_win.h5
-rw-r--r--chromium/services/device/serial/serial_io_handler.cc32
-rw-r--r--chromium/services/device/serial/serial_io_handler.h34
-rw-r--r--chromium/services/device/serial/serial_io_handler_posix.cc57
-rw-r--r--chromium/services/device/serial/serial_io_handler_posix.h14
-rw-r--r--chromium/services/device/serial/serial_io_handler_posix_unittest.cc7
-rw-r--r--chromium/services/device/serial/serial_io_handler_win.cc12
-rw-r--r--chromium/services/device/serial/serial_io_handler_win.h12
-rw-r--r--chromium/services/device/serial/serial_port_impl.cc2
-rw-r--r--chromium/services/device/serial/serial_port_impl.h5
-rw-r--r--chromium/services/device/serial/serial_port_impl_unittest.cc4
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl.cc36
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl.h24
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl_unittest.cc86
-rw-r--r--chromium/services/device/time_zone_monitor/BUILD.gn2
-rw-r--r--chromium/services/device/time_zone_monitor/DEPS2
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc2
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_android.h1
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_chromeos.cc14
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc7
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_mac.mm1
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc1
-rw-r--r--chromium/services/device/usb/mock_usb_device_handle.cc2
-rw-r--r--chromium/services/device/usb/mock_usb_device_handle.h3
-rw-r--r--chromium/services/device/usb/mojo/device_impl.h1
-rw-r--r--chromium/services/device/usb/mojo/device_impl_unittest.cc6
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl.h1
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl_unittest.cc4
-rw-r--r--chromium/services/device/usb/mojo/device_manager_test.cc6
-rw-r--r--chromium/services/device/usb/mojo/device_manager_test.h4
-rw-r--r--chromium/services/device/usb/scoped_libusb_device_handle.h1
-rw-r--r--chromium/services/device/usb/scoped_libusb_device_ref.h1
-rw-r--r--chromium/services/device/usb/scoped_winusb_handle.h7
-rw-r--r--chromium/services/device/usb/usb_context.cc1
-rw-r--r--chromium/services/device/usb/usb_context.h6
-rw-r--r--chromium/services/device/usb/usb_context_unittest.cc5
-rw-r--r--chromium/services/device/usb/usb_descriptors.cc6
-rw-r--r--chromium/services/device/usb/usb_device.h6
-rw-r--r--chromium/services/device/usb/usb_device_android.h4
-rw-r--r--chromium/services/device/usb/usb_device_handle.h7
-rw-r--r--chromium/services/device/usb/usb_device_handle_android.cc6
-rw-r--r--chromium/services/device/usb/usb_device_handle_android.h2
-rw-r--r--chromium/services/device/usb/usb_device_handle_impl.cc8
-rw-r--r--chromium/services/device/usb/usb_device_handle_impl.h6
-rw-r--r--chromium/services/device/usb/usb_device_handle_usbfs.cc286
-rw-r--r--chromium/services/device/usb/usb_device_handle_usbfs.h32
-rw-r--r--chromium/services/device/usb/usb_device_handle_win.cc9
-rw-r--r--chromium/services/device/usb/usb_device_handle_win.h27
-rw-r--r--chromium/services/device/usb/usb_device_impl.cc4
-rw-r--r--chromium/services/device/usb/usb_device_impl.h6
-rw-r--r--chromium/services/device/usb/usb_device_linux.cc2
-rw-r--r--chromium/services/device/usb/usb_device_linux.h6
-rw-r--r--chromium/services/device/usb/usb_device_win.cc11
-rw-r--r--chromium/services/device/usb/usb_device_win.h10
-rw-r--r--chromium/services/device/usb/usb_service.h5
-rw-r--r--chromium/services/device/usb/usb_service_android.cc2
-rw-r--r--chromium/services/device/usb/usb_service_impl.cc4
-rw-r--r--chromium/services/device/usb/usb_service_impl.h1
-rw-r--r--chromium/services/device/usb/usb_service_linux.cc46
-rw-r--r--chromium/services/device/usb/usb_service_linux.h6
-rw-r--r--chromium/services/device/usb/usb_service_win.cc42
-rw-r--r--chromium/services/device/usb/usb_service_win.h6
-rw-r--r--chromium/services/device/vibration/OWNERS2
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/BUILD.gn22
-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.h4
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_android.cc8
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_ash.cc2
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc16
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc37
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc2
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_stub.cc6
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc8
-rw-r--r--chromium/services/device/wake_lock/wake_lock.h6
-rw-r--r--chromium/services/device/wake_lock/wake_lock_context.h2
-rw-r--r--chromium/services/device/wake_lock/wake_lock_provider.cc6
-rw-r--r--chromium/services/device/wake_lock/wake_lock_provider.h4
-rw-r--r--chromium/services/image_annotation/annotator.cc90
-rw-r--r--chromium/services/image_annotation/annotator.h19
-rw-r--r--chromium/services/image_annotation/annotator_unittest.cc41
-rw-r--r--chromium/services/image_annotation/image_annotation_metrics.cc5
-rw-r--r--chromium/services/image_annotation/image_annotation_metrics.h7
-rw-r--r--chromium/services/image_annotation/image_annotation_service.h1
-rw-r--r--chromium/services/image_annotation/public/cpp/image_processor.cc2
-rw-r--r--chromium/services/image_annotation/public/cpp/image_processor.h3
-rw-r--r--chromium/services/image_annotation/public/mojom/image_annotation.mojom3
-rw-r--r--chromium/services/media_session/audio_focus_manager_unittest.cc5
-rw-r--r--chromium/services/media_session/audio_focus_request.h1
-rw-r--r--chromium/services/media_session/media_controller.cc3
-rw-r--r--chromium/services/media_session/media_controller.h3
-rw-r--r--chromium/services/media_session/media_controller_unittest.cc5
-rw-r--r--chromium/services/media_session/media_session_service_impl.h1
-rw-r--r--chromium/services/media_session/media_session_service_impl_unittest.cc1
-rw-r--r--chromium/services/media_session/public/cpp/media_image_manager.h1
-rw-r--r--chromium/services/media_session/public/cpp/media_image_manager_unittest.cc6
-rw-r--r--chromium/services/media_session/public/cpp/test/BUILD.gn7
-rw-r--r--chromium/services/metrics/public/cpp/delegating_ukm_recorder.h2
-rw-r--r--chromium/services/metrics/public/cpp/metrics_utils.cc2
-rw-r--r--chromium/services/metrics/public/cpp/ukm_entry_builder.h1
-rw-r--r--chromium/services/metrics/public/cpp/ukm_entry_builder_base.h1
-rw-r--r--chromium/services/metrics/public/cpp/ukm_recorder.h6
-rw-r--r--chromium/services/metrics/public/cpp/ukm_source.h1
-rw-r--r--chromium/services/metrics/ukm_api.md6
-rw-r--r--chromium/services/metrics/ukm_recorder_interface.h3
-rw-r--r--chromium/services/network/BUILD.gn55
-rw-r--r--chromium/services/network/OWNERS2
-rw-r--r--chromium/services/network/cert_verifier_with_trust_anchors.h1
-rw-r--r--chromium/services/network/chunked_data_pipe_upload_data_stream.h1
-rw-r--r--chromium/services/network/chunked_data_pipe_upload_data_stream_unittest.cc1
-rw-r--r--chromium/services/network/conditional_cache_deletion_helper.cc4
-rw-r--r--chromium/services/network/conditional_cache_deletion_helper.h5
-rw-r--r--chromium/services/network/cookie_access_delegate_impl.cc8
-rw-r--r--chromium/services/network/cookie_access_delegate_impl.h7
-rw-r--r--chromium/services/network/cookie_manager.cc49
-rw-r--r--chromium/services/network/cookie_manager.h12
-rw-r--r--chromium/services/network/cookie_manager_unittest.cc230
-rw-r--r--chromium/services/network/cookie_settings.h4
-rw-r--r--chromium/services/network/cors/cors_url_loader.cc291
-rw-r--r--chromium/services/network/cors/cors_url_loader.h94
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory.cc165
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory.h62
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory_unittest.cc130
-rw-r--r--chromium/services/network/cors/cors_url_loader_unittest.cc1598
-rw-r--r--chromium/services/network/cors/preflight_cache.cc6
-rw-r--r--chromium/services/network/cors/preflight_cache.h7
-rw-r--r--chromium/services/network/cors/preflight_cache_unittest.cc8
-rw-r--r--chromium/services/network/cors/preflight_controller.cc202
-rw-r--r--chromium/services/network/cors/preflight_controller.h32
-rw-r--r--chromium/services/network/cors/preflight_controller_unittest.cc82
-rw-r--r--chromium/services/network/cors/preflight_result.cc19
-rw-r--r--chromium/services/network/cors/preflight_result.h21
-rw-r--r--chromium/services/network/cors/preflight_result_unittest.cc23
-rw-r--r--chromium/services/network/crl_set_distributor.h1
-rw-r--r--chromium/services/network/data_pipe_element_reader.h1
-rw-r--r--chromium/services/network/data_pipe_element_reader_unittest.cc7
-rw-r--r--chromium/services/network/dhcp_pac_file_fetcher_mojo.h1
-rw-r--r--chromium/services/network/dns_config_change_manager.h1
-rw-r--r--chromium/services/network/dns_config_change_manager_unittest.cc13
-rw-r--r--chromium/services/network/expect_ct_reporter.cc5
-rw-r--r--chromium/services/network/expect_ct_reporter.h4
-rw-r--r--chromium/services/network/expect_ct_reporter_unittest.cc83
-rw-r--r--chromium/services/network/first_party_sets/first_party_set_parser.cc16
-rw-r--r--chromium/services/network/first_party_sets/first_party_set_parser.h12
-rw-r--r--chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc43
-rw-r--r--chromium/services/network/first_party_sets/first_party_sets.cc99
-rw-r--r--chromium/services/network/first_party_sets/first_party_sets.h110
-rw-r--r--chromium/services/network/first_party_sets/first_party_sets_unittest.cc1295
-rw-r--r--chromium/services/network/host_resolver.cc7
-rw-r--r--chromium/services/network/host_resolver.h6
-rw-r--r--chromium/services/network/host_resolver_mdns_listener.h1
-rw-r--r--chromium/services/network/host_resolver_unittest.cc92
-rw-r--r--chromium/services/network/http_auth_cache_copier.h1
-rw-r--r--chromium/services/network/http_cache_data_counter.h1
-rw-r--r--chromium/services/network/http_cache_data_remover.h1
-rw-r--r--chromium/services/network/http_cache_data_remover_unittest.cc39
-rw-r--r--chromium/services/network/http_server_properties_pref_delegate.h4
-rw-r--r--chromium/services/network/ignore_errors_cert_verifier_unittest.cc5
-rw-r--r--chromium/services/network/keepalive_statistics_recorder.h1
-rw-r--r--chromium/services/network/mdns_responder.cc7
-rw-r--r--chromium/services/network/mdns_responder.h10
-rw-r--r--chromium/services/network/mock_mojo_dhcp_wpad_url_client.h1
-rw-r--r--chromium/services/network/mojo_host_resolver_impl.cc3
-rw-r--r--chromium/services/network/mojo_host_resolver_impl.h4
-rw-r--r--chromium/services/network/mojo_host_resolver_impl_unittest.cc16
-rw-r--r--chromium/services/network/mojo_socket_test_util.h1
-rw-r--r--chromium/services/network/net_log_exporter.h4
-rw-r--r--chromium/services/network/network_change_manager.h1
-rw-r--r--chromium/services/network/network_change_manager_unittest.cc1
-rw-r--r--chromium/services/network/network_context.cc113
-rw-r--r--chromium/services/network/network_context.h50
-rw-r--r--chromium/services/network/network_context_unittest.cc336
-rw-r--r--chromium/services/network/network_qualities_pref_delegate.cc3
-rw-r--r--chromium/services/network/network_qualities_pref_delegate.h4
-rw-r--r--chromium/services/network/network_qualities_pref_delegate_unittest.cc1
-rw-r--r--chromium/services/network/network_quality_estimator_manager.h1
-rw-r--r--chromium/services/network/network_quality_estimator_manager_unittest.cc12
-rw-r--r--chromium/services/network/network_service.cc11
-rw-r--r--chromium/services/network/network_service.h18
-rw-r--r--chromium/services/network/network_service_network_delegate.h4
-rw-r--r--chromium/services/network/network_service_proxy_delegate.cc4
-rw-r--r--chromium/services/network/network_service_proxy_delegate.h7
-rw-r--r--chromium/services/network/network_service_proxy_delegate_unittest.cc8
-rw-r--r--chromium/services/network/network_service_unittest.cc8
-rw-r--r--chromium/services/network/nss_temp_certs_cache_chromeos.h1
-rw-r--r--chromium/services/network/nss_temp_certs_cache_chromeos_unittest.cc1
-rw-r--r--chromium/services/network/origin_policy/origin_policy_fetcher.h3
-rw-r--r--chromium/services/network/origin_policy/origin_policy_manager.h4
-rw-r--r--chromium/services/network/origin_policy/origin_policy_manager_unittest.cc5
-rw-r--r--chromium/services/network/origin_policy/origin_policy_parser.h6
-rw-r--r--chromium/services/network/p2p/socket.h9
-rw-r--r--chromium/services/network/p2p/socket_manager.cc3
-rw-r--r--chromium/services/network/p2p/socket_manager.h6
-rw-r--r--chromium/services/network/p2p/socket_tcp.h4
-rw-r--r--chromium/services/network/p2p/socket_tcp_unittest.cc3
-rw-r--r--chromium/services/network/p2p/socket_test_utils.h5
-rw-r--r--chromium/services/network/p2p/socket_throttler.h1
-rw-r--r--chromium/services/network/p2p/socket_udp.cc5
-rw-r--r--chromium/services/network/p2p/socket_udp.h6
-rw-r--r--chromium/services/network/p2p/socket_udp_unittest.cc11
-rw-r--r--chromium/services/network/proxy_auto_config_library.cc12
-rw-r--r--chromium/services/network/proxy_config_service_mojo.h1
-rw-r--r--chromium/services/network/proxy_config_service_mojo_unittest.cc4
-rw-r--r--chromium/services/network/proxy_lookup_request.h4
-rw-r--r--chromium/services/network/proxy_resolver_factory_mojo.cc18
-rw-r--r--chromium/services/network/proxy_resolver_factory_mojo.h6
-rw-r--r--chromium/services/network/proxy_resolver_factory_mojo_unittest.cc28
-rw-r--r--chromium/services/network/proxy_resolving_client_socket.h8
-rw-r--r--chromium/services/network/proxy_resolving_client_socket_factory.h4
-rw-r--r--chromium/services/network/proxy_resolving_client_socket_unittest.cc44
-rw-r--r--chromium/services/network/proxy_resolving_socket_factory_mojo.h1
-rw-r--r--chromium/services/network/proxy_resolving_socket_mojo.h4
-rw-r--r--chromium/services/network/proxy_resolving_socket_mojo_unittest.cc6
-rw-r--r--chromium/services/network/proxy_service_mojo_unittest.cc25
-rw-r--r--chromium/services/network/public/cpp/BUILD.gn43
-rw-r--r--chromium/services/network/public/cpp/OWNERS3
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc4
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc3
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc4
-rw-r--r--chromium/services/network/public/cpp/client_hints.cc42
-rw-r--r--chromium/services/network/public/cpp/client_hints.h18
-rw-r--r--chromium/services/network/public/cpp/client_hints_unittest.cc108
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc14
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc28
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc3
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc41
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.h26
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc50
-rw-r--r--chromium/services/network/public/cpp/corb/corb_impl.cc14
-rw-r--r--chromium/services/network/public/cpp/corb/corb_impl.h5
-rw-r--r--chromium/services/network/public/cpp/corb/corb_impl_unittest.cc34
-rw-r--r--chromium/services/network/public/cpp/cors/cors.cc54
-rw-r--r--chromium/services/network/public/cpp/cors/cors.h6
-rw-r--r--chromium/services/network/public/cpp/cors/cors_unittest.cc35
-rw-r--r--chromium/services/network/public/cpp/cors/origin_access_entry.cc23
-rw-r--r--chromium/services/network/public/cpp/cors/origin_access_entry.h13
-rw-r--r--chromium/services/network/public/cpp/cors/origin_access_entry_unittest.cc26
-rw-r--r--chromium/services/network/public/cpp/cors/origin_access_list.h1
-rw-r--r--chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc2
-rw-r--r--chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h1
-rw-r--r--chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc2
-rw-r--r--chromium/services/network/public/cpp/devtools_observer_util.cc3
-rw-r--r--chromium/services/network/public/cpp/empty_url_loader_client.h1
-rw-r--r--chromium/services/network/public/cpp/features.cc51
-rw-r--r--chromium/services/network/public/cpp/features.gni6
-rw-r--r--chromium/services/network/public/cpp/features.h21
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util.cc14
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util.h20
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util_unittest.cc37
-rw-r--r--chromium/services/network/public/cpp/is_potentially_trustworthy.cc5
-rw-r--r--chromium/services/network/public/cpp/is_potentially_trustworthy.h6
-rw-r--r--chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h3
-rw-r--r--chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc1
-rw-r--r--chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h3
-rw-r--r--chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc1
-rw-r--r--chromium/services/network/public/cpp/net_adapters.h23
-rw-r--r--chromium/services/network/public/cpp/network_connection_tracker.cc2
-rw-r--r--chromium/services/network/public/cpp/network_connection_tracker.h6
-rw-r--r--chromium/services/network/public/cpp/network_connection_tracker_unittest.cc14
-rw-r--r--chromium/services/network/public/cpp/network_mojom_traits_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/network_quality_tracker.cc4
-rw-r--r--chromium/services/network/public/cpp/network_quality_tracker.h14
-rw-r--r--chromium/services/network/public/cpp/network_quality_tracker_unittest.cc6
-rw-r--r--chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc1
-rw-r--r--chromium/services/network/public/cpp/origin_agent_cluster_parser.cc9
-rw-r--r--chromium/services/network/public/cpp/origin_agent_cluster_parser.h3
-rw-r--r--chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc36
-rw-r--r--chromium/services/network/public/cpp/parsed_headers.cc14
-rw-r--r--chromium/services/network/public/cpp/proxy_config_mojom_traits.cc1
-rw-r--r--chromium/services/network/public/cpp/proxy_config_mojom_traits.h17
-rw-r--r--chromium/services/network/public/cpp/proxy_config_with_annotation_mojom_traits.h4
-rw-r--r--chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.cc34
-rw-r--r--chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.h73
-rw-r--r--chromium/services/network/public/cpp/reporting_api_report_mojom_traits.h2
-rw-r--r--chromium/services/network/public/cpp/request_destination.cc9
-rw-r--r--chromium/services/network/public/cpp/request_destination.h4
-rw-r--r--chromium/services/network/public/cpp/resource_request.cc17
-rw-r--r--chromium/services/network/public/cpp/resource_request.h21
-rw-r--r--chromium/services/network/public/cpp/resource_request_body.h6
-rw-r--r--chromium/services/network/public/cpp/self_deleting_url_loader_factory.h8
-rw-r--r--chromium/services/network/public/cpp/server/http_connection.h1
-rw-r--r--chromium/services/network/public/cpp/server/http_server.cc5
-rw-r--r--chromium/services/network/public/cpp/server/http_server.h4
-rw-r--r--chromium/services/network/public/cpp/server/http_server_unittest.cc149
-rw-r--r--chromium/services/network/public/cpp/server/web_socket.cc12
-rw-r--r--chromium/services/network/public/cpp/server/web_socket.h6
-rw-r--r--chromium/services/network/public/cpp/server/web_socket_encoder.cc4
-rw-r--r--chromium/services/network/public/cpp/server/web_socket_encoder.h1
-rw-r--r--chromium/services/network/public/cpp/shared_url_loader_factory.h1
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader.cc10
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader_stream_consumer.h8
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader_unittest.cc8
-rw-r--r--chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc3
-rw-r--r--chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc1
-rw-r--r--chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc10
-rw-r--r--chromium/services/network/public/cpp/url_loader_completion_status.h1
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.cc27
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.h39
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc10
-rw-r--r--chromium/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h3
-rw-r--r--chromium/services/network/public/mojom/BUILD.gn140
-rw-r--r--chromium/services/network/public/mojom/cookie_manager.mojom14
-rw-r--r--chromium/services/network/public/mojom/cors.mojom30
-rw-r--r--chromium/services/network/public/mojom/ct_log_info.mojom14
-rw-r--r--chromium/services/network/public/mojom/devtools_observer.mojom8
-rw-r--r--chromium/services/network/public/mojom/fetch_api.mojom9
-rw-r--r--chromium/services/network/public/mojom/network_context.mojom28
-rw-r--r--chromium/services/network/public/mojom/network_service.mojom24
-rw-r--r--chromium/services/network/public/mojom/network_service_test.mojom9
-rw-r--r--chromium/services/network/public/mojom/parsed_headers.mojom11
-rw-r--r--chromium/services/network/public/mojom/proxy_config_with_annotation.mojom2
-rw-r--r--chromium/services/network/public/mojom/reporting_report.mojom51
-rw-r--r--chromium/services/network/public/mojom/reporting_service.mojom86
-rw-r--r--chromium/services/network/public/mojom/ssl_config.mojom13
-rw-r--r--chromium/services/network/public/mojom/supports_loading_mode.mojom4
-rw-r--r--chromium/services/network/public/mojom/tls_socket.mojom2
-rw-r--r--chromium/services/network/public/mojom/url_loader_factory.mojom9
-rw-r--r--chromium/services/network/public/mojom/url_request.mojom53
-rw-r--r--chromium/services/network/public/mojom/url_response_head.mojom16
-rw-r--r--chromium/services/network/public/mojom/web_bundle_handle.mojom1
-rw-r--r--chromium/services/network/public/mojom/web_client_hints_types.mojom4
-rw-r--r--chromium/services/network/radio_monitor_android.cc74
-rw-r--r--chromium/services/network/radio_monitor_android.h85
-rw-r--r--chromium/services/network/resolve_host_request.h1
-rw-r--r--chromium/services/network/resource_scheduler/resource_scheduler.cc140
-rw-r--r--chromium/services/network/resource_scheduler/resource_scheduler.h22
-rw-r--r--chromium/services/network/resource_scheduler/resource_scheduler_client.h8
-rw-r--r--chromium/services/network/resource_scheduler/resource_scheduler_unittest.cc138
-rw-r--r--chromium/services/network/restricted_cookie_manager.cc56
-rw-r--r--chromium/services/network/restricted_cookie_manager.h17
-rw-r--r--chromium/services/network/restricted_cookie_manager_unittest.cc270
-rw-r--r--chromium/services/network/sct_auditing/README.md24
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_cache.cc273
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_cache.h128
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_cache_unittest.cc181
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_handler.cc87
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_handler.h81
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_reporter.cc231
-rw-r--r--chromium/services/network/sct_auditing/sct_auditing_reporter.h103
-rw-r--r--chromium/services/network/session_cleanup_cookie_store.cc10
-rw-r--r--chromium/services/network/session_cleanup_cookie_store.h7
-rw-r--r--chromium/services/network/session_cleanup_cookie_store_unittest.cc12
-rw-r--r--chromium/services/network/socket_data_pump.h6
-rw-r--r--chromium/services/network/socket_data_pump_unittest.cc1
-rw-r--r--chromium/services/network/socket_factory.h6
-rw-r--r--chromium/services/network/ssl_config_service_mojo.h5
-rw-r--r--chromium/services/network/ssl_config_service_mojo_unittest.cc3
-rw-r--r--chromium/services/network/ssl_config_type_converter.cc3
-rw-r--r--chromium/services/network/tcp_bound_socket.h4
-rw-r--r--chromium/services/network/tcp_connected_socket.h8
-rw-r--r--chromium/services/network/tcp_server_socket.h4
-rw-r--r--chromium/services/network/tcp_socket_unittest.cc9
-rw-r--r--chromium/services/network/test_chunked_data_pipe_getter.h1
-rw-r--r--chromium/services/network/test_mojo_proxy_resolver_factory.h1
-rw-r--r--chromium/services/network/throttling/network_conditions.h1
-rw-r--r--chromium/services/network/throttling/scoped_throttling_token.h1
-rw-r--r--chromium/services/network/throttling/throttling_controller.cc9
-rw-r--r--chromium/services/network/throttling/throttling_controller.h11
-rw-r--r--chromium/services/network/throttling/throttling_controller_unittest.cc36
-rw-r--r--chromium/services/network/throttling/throttling_network_interceptor.h1
-rw-r--r--chromium/services/network/throttling/throttling_network_transaction.cc5
-rw-r--r--chromium/services/network/throttling/throttling_network_transaction.h6
-rw-r--r--chromium/services/network/throttling/throttling_network_transaction_factory.h1
-rw-r--r--chromium/services/network/throttling/throttling_upload_data_stream.h4
-rw-r--r--chromium/services/network/tls_client_socket.h1
-rw-r--r--chromium/services/network/tls_client_socket_unittest.cc9
-rw-r--r--chromium/services/network/tls_socket_factory.h6
-rw-r--r--chromium/services/network/transitional_url_loader_factory_owner.h3
-rw-r--r--chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h4
-rw-r--r--chromium/services/network/trust_tokens/has_trust_tokens_answerer.h3
-rw-r--r--chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc2
-rw-r--r--chromium/services/network/trust_tokens/trust_token_client_data_canonicalization.cc2
-rw-r--r--chromium/services/network/trust_tokens/trust_token_database_owner.cc2
-rw-r--r--chromium/services/network/trust_tokens/trust_token_database_owner.h2
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_helper_factory.h5
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc1
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h7
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h5
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc1
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper.h3
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc7
-rw-r--r--chromium/services/network/trust_tokens/trust_token_store.cc4
-rw-r--r--chromium/services/network/trust_tokens/trust_token_store.h2
-rw-r--r--chromium/services/network/udp_socket.h4
-rw-r--r--chromium/services/network/udp_socket_unittest.cc1
-rw-r--r--chromium/services/network/upload_progress_tracker.h6
-rw-r--r--chromium/services/network/upload_progress_tracker_unittest.cc15
-rw-r--r--chromium/services/network/url_loader.cc270
-rw-r--r--chromium/services/network/url_loader.h49
-rw-r--r--chromium/services/network/url_loader_factory.cc56
-rw-r--r--chromium/services/network/url_loader_factory.h6
-rw-r--r--chromium/services/network/url_loader_unittest.cc155
-rw-r--r--chromium/services/network/url_request_context_builder_mojo.h1
-rw-r--r--chromium/services/network/web_bundle/web_bundle_manager_unittest.cc8
-rw-r--r--chromium/services/network/web_bundle/web_bundle_url_loader_factory.cc16
-rw-r--r--chromium/services/network/web_bundle/web_bundle_url_loader_factory.h3
-rw-r--r--chromium/services/network/web_bundle/web_bundle_url_loader_factory_unittest.cc82
-rw-r--r--chromium/services/network/web_transport.cc11
-rw-r--r--chromium/services/network/web_transport.h4
-rw-r--r--chromium/services/network/web_transport_unittest.cc11
-rw-r--r--chromium/services/network/websocket.cc95
-rw-r--r--chromium/services/network/websocket.h30
-rw-r--r--chromium/services/network/websocket_factory.h3
-rw-r--r--chromium/services/network/websocket_interceptor.cc8
-rw-r--r--chromium/services/network/websocket_interceptor.h6
-rw-r--r--chromium/services/network/websocket_interceptor_unittest.cc10
-rw-r--r--chromium/services/network/websocket_throttler.h7
-rw-r--r--chromium/services/preferences/public/cpp/dictionary_value_update.cc15
-rw-r--r--chromium/services/preferences/public/cpp/dictionary_value_update.h3
-rw-r--r--chromium/services/preferences/public/cpp/scoped_pref_update.h4
-rw-r--r--chromium/services/preferences/public/cpp/tracked/mock_validation_delegate.h7
-rw-r--r--chromium/services/preferences/tracked/dictionary_hash_store_contents.cc1
-rw-r--r--chromium/services/preferences/tracked/dictionary_hash_store_contents.h10
-rw-r--r--chromium/services/preferences/tracked/pref_hash_calculator.h2
-rw-r--r--chromium/services/preferences/tracked/pref_hash_calculator_unittest.cc1
-rw-r--r--chromium/services/preferences/tracked/pref_hash_filter.h1
-rw-r--r--chromium/services/preferences/tracked/pref_hash_filter_unittest.cc21
-rw-r--r--chromium/services/preferences/tracked/pref_hash_store_impl.cc6
-rw-r--r--chromium/services/preferences/tracked/pref_hash_store_impl.h1
-rw-r--r--chromium/services/preferences/tracked/pref_hash_store_impl_unittest.cc6
-rw-r--r--chromium/services/preferences/tracked/registry_hash_store_contents_win.h1
-rw-r--r--chromium/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc8
-rw-r--r--chromium/services/preferences/tracked/tracked_atomic_preference.h9
-rw-r--r--chromium/services/preferences/tracked/tracked_persistent_pref_store_factory.h2
-rw-r--r--chromium/services/preferences/tracked/tracked_preference_helper.h6
-rw-r--r--chromium/services/preferences/tracked/tracked_preferences_migration.cc7
-rw-r--r--chromium/services/preferences/tracked/tracked_preferences_migration_unittest.cc8
-rw-r--r--chromium/services/preferences/tracked/tracked_split_preference.h9
-rw-r--r--chromium/services/proxy_resolver/BUILD.gn9
-rw-r--r--chromium/services/proxy_resolver/host_resolver_mojo.cc3
-rw-r--r--chromium/services/proxy_resolver/host_resolver_mojo.h4
-rw-r--r--chromium/services/proxy_resolver/mock_proxy_host_resolver.cc3
-rw-r--r--chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h3
-rw-r--r--chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc9
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_factory_impl.cc6
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_factory_impl.h1
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc7
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_impl.cc4
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_impl.h1
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_impl_unittest.cc11
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_v8.cc25
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_v8.h6
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_v8_tracing.cc21
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_v8_tracing.h1
-rw-r--r--chromium/services/proxy_resolver/proxy_resolver_v8_tracing_unittest.cc5
-rw-r--r--chromium/services/proxy_resolver_win/BUILD.gn29
-rw-r--r--chromium/services/proxy_resolver_win/public/cpp/OWNERS2
-rw-r--r--chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.cc100
-rw-r--r--chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.h26
-rw-r--r--chromium/services/proxy_resolver_win/public/mojom/BUILD.gn33
-rw-r--r--chromium/services/proxy_resolver_win/public/mojom/OWNERS2
-rw-r--r--chromium/services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom43
-rw-r--r--chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.cc454
-rw-r--r--chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.h135
-rw-r--r--chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl_unittest.cc641
-rw-r--r--chromium/services/proxy_resolver_win/winhttp_api_wrapper.h55
-rw-r--r--chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.cc (renamed from chromium/services/proxy_resolver_win/winhttp_api_wrapper.cc)34
-rw-r--r--chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.h74
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/graph.h18
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h3
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc2
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h7
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h5
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h5
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc5
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h6
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h1
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h1
-rw-r--r--chromium/services/service_manager/BUILD.gn3
-rw-r--r--chromium/services/service_manager/background_service_manager.cc4
-rw-r--r--chromium/services/service_manager/background_service_manager.h1
-rw-r--r--chromium/services/service_manager/catalog.h1
-rw-r--r--chromium/services/service_manager/public/cpp/connector.h9
-rw-r--r--chromium/services/service_manager/public/cpp/interface_provider.cc20
-rw-r--r--chromium/services/service_manager/public/cpp/interface_provider.h23
-rw-r--r--chromium/services/service_manager/public/cpp/local_interface_provider.h1
-rw-r--r--chromium/services/service_manager/public/cpp/manifest.h6
-rw-r--r--chromium/services/service_manager/public/cpp/service.h1
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/main.cc1
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.cc1
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.h1
-rw-r--r--chromium/services/service_manager/public/cpp/service_filter.h1
-rw-r--r--chromium/services/service_manager/public/cpp/service_keepalive.h4
-rw-r--r--chromium/services/service_manager/public/cpp/service_receiver.h1
-rw-r--r--chromium/services/service_manager/public/cpp/standalone_connector_impl.h4
-rw-r--r--chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc1
-rw-r--r--chromium/services/service_manager/public/java/src/org/chromium/services/service_manager/Connector.java4
-rw-r--r--chromium/services/service_manager/service_instance.cc3
-rw-r--r--chromium/services/service_manager/service_instance.h13
-rw-r--r--chromium/services/service_manager/service_instance_registry.h4
-rw-r--r--chromium/services/service_manager/service_manager.cc9
-rw-r--r--chromium/services/service_manager/service_manager.h4
-rw-r--r--chromium/services/service_manager/service_process_host.h5
-rw-r--r--chromium/services/service_manager/service_process_launcher.cc23
-rw-r--r--chromium/services/service_manager/service_process_launcher.h7
-rw-r--r--chromium/services/services_strings.grd3
-rw-r--r--chromium/services/services_strings_grd/IDS_WINDOWS_SYSTEM_PROXY_RESOLVER_DISPLAY_NAME.png.sha11
-rw-r--r--chromium/services/shape_detection/BUILD.gn68
-rw-r--r--chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java4
-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/barcode_detection_impl_barhopper_unittest.cc39
-rw-r--r--chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm4
-rw-r--r--chromium/services/shape_detection/barcode_detection_impl_mac_vision.h1
-rw-r--r--chromium/services/shape_detection/barcode_detection_provider_mac.h1
-rw-r--r--chromium/services/shape_detection/detection_utils_mac.h1
-rw-r--r--chromium/services/shape_detection/detection_utils_mac.mm2
-rw-r--r--chromium/services/shape_detection/face_detection_impl_mac_vision.h1
-rw-r--r--chromium/services/shape_detection/face_detection_impl_win.h1
-rw-r--r--chromium/services/shape_detection/face_detection_impl_win_unittest.cc7
-rw-r--r--chromium/services/shape_detection/face_detection_provider_mac.h1
-rw-r--r--chromium/services/shape_detection/face_detection_provider_win.h1
-rw-r--r--chromium/services/shape_detection/public/mojom/BUILD.gn4
-rw-r--r--chromium/services/shape_detection/shape_detection_service.cc36
-rw-r--r--chromium/services/shape_detection/shape_detection_service.h1
-rw-r--r--chromium/services/shape_detection/text_detection_impl.h5
-rw-r--r--chromium/services/shape_detection/text_detection_impl_win.h1
-rw-r--r--chromium/services/shape_detection/text_detection_impl_win_unittest.cc7
-rw-r--r--chromium/services/strings/services_strings_af.xtb1
-rw-r--r--chromium/services/strings/services_strings_am.xtb1
-rw-r--r--chromium/services/strings/services_strings_ar.xtb1
-rw-r--r--chromium/services/strings/services_strings_as.xtb1
-rw-r--r--chromium/services/strings/services_strings_az.xtb1
-rw-r--r--chromium/services/strings/services_strings_be.xtb1
-rw-r--r--chromium/services/strings/services_strings_bg.xtb1
-rw-r--r--chromium/services/strings/services_strings_bn.xtb1
-rw-r--r--chromium/services/strings/services_strings_bs.xtb1
-rw-r--r--chromium/services/strings/services_strings_ca.xtb1
-rw-r--r--chromium/services/strings/services_strings_cs.xtb1
-rw-r--r--chromium/services/strings/services_strings_da.xtb1
-rw-r--r--chromium/services/strings/services_strings_de.xtb1
-rw-r--r--chromium/services/strings/services_strings_el.xtb1
-rw-r--r--chromium/services/strings/services_strings_en-GB.xtb1
-rw-r--r--chromium/services/strings/services_strings_es-419.xtb1
-rw-r--r--chromium/services/strings/services_strings_es.xtb1
-rw-r--r--chromium/services/strings/services_strings_et.xtb1
-rw-r--r--chromium/services/strings/services_strings_eu.xtb1
-rw-r--r--chromium/services/strings/services_strings_fa.xtb1
-rw-r--r--chromium/services/strings/services_strings_fi.xtb1
-rw-r--r--chromium/services/strings/services_strings_fil.xtb1
-rw-r--r--chromium/services/strings/services_strings_fr-CA.xtb1
-rw-r--r--chromium/services/strings/services_strings_fr.xtb1
-rw-r--r--chromium/services/strings/services_strings_gl.xtb1
-rw-r--r--chromium/services/strings/services_strings_gu.xtb1
-rw-r--r--chromium/services/strings/services_strings_hi.xtb1
-rw-r--r--chromium/services/strings/services_strings_hr.xtb1
-rw-r--r--chromium/services/strings/services_strings_hu.xtb1
-rw-r--r--chromium/services/strings/services_strings_hy.xtb1
-rw-r--r--chromium/services/strings/services_strings_id.xtb1
-rw-r--r--chromium/services/strings/services_strings_is.xtb1
-rw-r--r--chromium/services/strings/services_strings_it.xtb1
-rw-r--r--chromium/services/strings/services_strings_iw.xtb1
-rw-r--r--chromium/services/strings/services_strings_ja.xtb1
-rw-r--r--chromium/services/strings/services_strings_ka.xtb1
-rw-r--r--chromium/services/strings/services_strings_kk.xtb1
-rw-r--r--chromium/services/strings/services_strings_km.xtb1
-rw-r--r--chromium/services/strings/services_strings_kn.xtb1
-rw-r--r--chromium/services/strings/services_strings_ko.xtb1
-rw-r--r--chromium/services/strings/services_strings_ky.xtb1
-rw-r--r--chromium/services/strings/services_strings_lo.xtb1
-rw-r--r--chromium/services/strings/services_strings_lt.xtb1
-rw-r--r--chromium/services/strings/services_strings_lv.xtb1
-rw-r--r--chromium/services/strings/services_strings_mk.xtb1
-rw-r--r--chromium/services/strings/services_strings_ml.xtb1
-rw-r--r--chromium/services/strings/services_strings_mn.xtb1
-rw-r--r--chromium/services/strings/services_strings_mr.xtb1
-rw-r--r--chromium/services/strings/services_strings_ms.xtb1
-rw-r--r--chromium/services/strings/services_strings_my.xtb1
-rw-r--r--chromium/services/strings/services_strings_ne.xtb1
-rw-r--r--chromium/services/strings/services_strings_nl.xtb1
-rw-r--r--chromium/services/strings/services_strings_no.xtb1
-rw-r--r--chromium/services/strings/services_strings_or.xtb1
-rw-r--r--chromium/services/strings/services_strings_pa.xtb1
-rw-r--r--chromium/services/strings/services_strings_pl.xtb1
-rw-r--r--chromium/services/strings/services_strings_pt-BR.xtb1
-rw-r--r--chromium/services/strings/services_strings_pt-PT.xtb1
-rw-r--r--chromium/services/strings/services_strings_ro.xtb1
-rw-r--r--chromium/services/strings/services_strings_ru.xtb1
-rw-r--r--chromium/services/strings/services_strings_si.xtb1
-rw-r--r--chromium/services/strings/services_strings_sk.xtb1
-rw-r--r--chromium/services/strings/services_strings_sl.xtb1
-rw-r--r--chromium/services/strings/services_strings_sq.xtb1
-rw-r--r--chromium/services/strings/services_strings_sr-Latn.xtb1
-rw-r--r--chromium/services/strings/services_strings_sr.xtb1
-rw-r--r--chromium/services/strings/services_strings_sv.xtb1
-rw-r--r--chromium/services/strings/services_strings_sw.xtb1
-rw-r--r--chromium/services/strings/services_strings_ta.xtb1
-rw-r--r--chromium/services/strings/services_strings_te.xtb1
-rw-r--r--chromium/services/strings/services_strings_th.xtb1
-rw-r--r--chromium/services/strings/services_strings_tr.xtb1
-rw-r--r--chromium/services/strings/services_strings_uk.xtb1
-rw-r--r--chromium/services/strings/services_strings_ur.xtb1
-rw-r--r--chromium/services/strings/services_strings_uz.xtb1
-rw-r--r--chromium/services/strings/services_strings_vi.xtb1
-rw-r--r--chromium/services/strings/services_strings_zh-CN.xtb1
-rw-r--r--chromium/services/strings/services_strings_zh-HK.xtb1
-rw-r--r--chromium/services/strings/services_strings_zh-TW.xtb1
-rw-r--r--chromium/services/strings/services_strings_zu.xtb1
-rw-r--r--chromium/services/tracing/BUILD.gn1
-rw-r--r--chromium/services/tracing/perfetto/consumer_host.cc5
-rw-r--r--chromium/services/tracing/perfetto/consumer_host.h11
-rw-r--r--chromium/services/tracing/perfetto/consumer_host_unittest.cc17
-rw-r--r--chromium/services/tracing/perfetto/perfetto_integration_unittest.cc9
-rw-r--r--chromium/services/tracing/perfetto/perfetto_service.h1
-rw-r--r--chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h18
-rw-r--r--chromium/services/tracing/perfetto/privacy_filtering_check.h2
-rw-r--r--chromium/services/tracing/perfetto/producer_host.h4
-rw-r--r--chromium/services/tracing/perfetto/system_perfetto_unittest.cc99
-rw-r--r--chromium/services/tracing/perfetto/test_utils.cc6
-rw-r--r--chromium/services/tracing/perfetto/test_utils.h10
-rw-r--r--chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h1
-rw-r--r--chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc3
-rw-r--r--chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_provider_impl.h1
-rw-r--r--chromium/services/tracing/public/cpp/base_agent.h1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.h1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.cc8
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.h4
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_parser_android.cc1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_session.h2
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc110
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h32
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc16
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/posix_system_producer.h1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_client.cc4
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_client.h6
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc7
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h5
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/shared_memory.h1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h6
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc20
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h17
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc28
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_string_lookup.cc2
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc3
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.cc2
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc5
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h3
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc7
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android.cc2
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc6
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc25
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h27
-rw-r--r--chromium/services/tracing/public/cpp/system_tracing_service_unittest.cc4
-rw-r--r--chromium/services/tracing/public/cpp/trace_event_agent.h4
-rw-r--r--chromium/services/tracing/public/cpp/trace_startup.cc4
-rw-r--r--chromium/services/tracing/public/cpp/trace_startup.h4
-rw-r--r--chromium/services/tracing/public/cpp/traced_process_impl.h4
-rw-r--r--chromium/services/tracing/tracing_service.h3
-rw-r--r--chromium/services/tracing/tracing_service_unittest.cc6
-rw-r--r--chromium/services/video_capture/broadcasting_receiver.cc8
-rw-r--r--chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc13
-rw-r--r--chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc3
-rw-r--r--chromium/services/video_capture/lacros/device_factory_adapter_lacros.cc13
-rw-r--r--chromium/services/video_capture/public/mojom/device_factory.mojom8
-rw-r--r--chromium/services/video_capture/public/mojom/video_source.mojom8
-rw-r--r--chromium/services/video_capture/push_video_stream_subscription_impl.cc18
-rw-r--r--chromium/services/video_capture/push_video_stream_subscription_impl.h7
-rw-r--r--chromium/services/video_capture/receiver_mojo_to_media_adapter.h2
-rw-r--r--chromium/services/video_capture/video_source_impl.cc48
-rw-r--r--chromium/services/video_capture/video_source_impl.h5
-rw-r--r--chromium/services/video_capture/video_source_provider_impl.h3
-rw-r--r--chromium/services/video_capture/virtual_device_enabled_device_factory.cc2
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/BUILD.gn10
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/DEPS1
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/display_private.mojom4
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom57
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc4
-rw-r--r--chromium/services/viz/privileged/mojom/gl/BUILD.gn7
-rw-r--r--chromium/services/viz/privileged/mojom/gl/gpu_service.mojom16
-rw-r--r--chromium/services/viz/privileged/mojom/viz_main.mojom5
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc7
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h14
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.cc15
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.h5
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc2
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h6
-rw-r--r--chromium/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc2
-rw-r--r--chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc6
-rw-r--r--chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc21
-rw-r--r--chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc14
-rw-r--r--chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h35
-rw-r--r--chromium/services/viz/public/cpp/compositing/region_capture_bounds_mojom_traits.h75
-rw-r--r--chromium/services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h30
-rw-r--r--chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc5
-rw-r--r--chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.h2
-rw-r--r--chromium/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h104
-rw-r--r--chromium/services/viz/public/cpp/gpu/BUILD.gn4
-rw-r--r--chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.cc2
-rw-r--r--chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.h1
-rw-r--r--chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h7
-rw-r--r--chromium/services/viz/public/cpp/gpu/gpu.cc12
-rw-r--r--chromium/services/viz/public/cpp/gpu/gpu.h3
-rw-r--r--chromium/services/viz/public/mojom/BUILD.gn53
-rw-r--r--chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom12
-rw-r--r--chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom6
-rw-r--r--chromium/services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom6
-rw-r--r--chromium/services/viz/public/mojom/compositing/compositor_render_pass.mojom2
-rw-r--r--chromium/services/viz/public/mojom/compositing/frame_sink_bundle.mojom5
-rw-r--r--chromium/services/viz/public/mojom/compositing/quads.mojom7
-rw-r--r--chromium/services/viz/public/mojom/compositing/region_capture_bounds.mojom37
-rw-r--r--chromium/services/viz/public/mojom/compositing/shared_element_resource_id.mojom22
973 files changed, 20156 insertions, 5904 deletions
diff --git a/chromium/services/BUILD.gn b/chromium/services/BUILD.gn
index 675f851f711..7297a67bb45 100644
--- a/chromium/services/BUILD.gn
+++ b/chromium/services/BUILD.gn
@@ -51,6 +51,10 @@ test("services_unittests") {
]
}
+ if (is_win) {
+ deps += [ "//services/proxy_resolver_win:tests" ]
+ }
+
if (is_android) {
deps += [
"//components/signin/public/android:java",
diff --git a/chromium/services/OWNERS b/chromium/services/OWNERS
index cd5feb02537..486a4405bbe 100644
--- a/chromium/services/OWNERS
+++ b/chromium/services/OWNERS
@@ -6,3 +6,6 @@ sky@chromium.org
# For adding or removing languages.
per-file *.grd=claudiomagni@chromium.org
+
+# Translation artifacts:
+per-file ....xtb=file://tools/translation/TRANSLATION_OWNERS \ No newline at end of file
diff --git a/chromium/services/audio/BUILD.gn b/chromium/services/audio/BUILD.gn
index 840aee92d0f..4b607ac74ef 100644
--- a/chromium/services/audio/BUILD.gn
+++ b/chromium/services/audio/BUILD.gn
@@ -2,10 +2,25 @@
# 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/chromeos/ui_mode.gni")
import("//testing/test.gni")
+declare_args() {
+ # Note: the audio service must be sandboxed for us to do audio processing
+ # there.
+ chrome_wide_echo_cancellation_supported = is_win || is_mac
+}
+
+buildflag_header("buildflags") {
+ header = "buildflags.h"
+
+ flags = [
+ "CHROME_WIDE_ECHO_CANCELLATION=$chrome_wide_echo_cancellation_supported",
+ ]
+}
+
source_set("audio") {
sources = [
"concurrent_stream_metric_reporter.cc",
@@ -14,8 +29,11 @@ source_set("audio") {
"debug_recording.h",
"delay_buffer.cc",
"delay_buffer.h",
+ "device_listener_output_stream.cc",
+ "device_listener_output_stream.h",
"device_notifier.cc",
"device_notifier.h",
+ "device_output_listener.h",
"group_coordinator-impl.h",
"group_coordinator.h",
"in_process_audio_manager_accessor.cc",
@@ -45,6 +63,7 @@ source_set("audio") {
"output_stream.h",
"owning_audio_manager_accessor.cc",
"owning_audio_manager_accessor.h",
+ "reference_output.h",
"service.cc",
"service.h",
"service_factory.cc",
@@ -71,6 +90,7 @@ source_set("audio") {
]
public_deps = [
+ ":buildflags",
"//base",
"//media",
"//media/mojo/mojom",
@@ -89,6 +109,27 @@ source_set("audio") {
]
}
+ if (chrome_wide_echo_cancellation_supported) {
+ sources += [
+ "audio_processor.cc",
+ "audio_processor.h",
+ "mixing_graph.cc",
+ "mixing_graph.h",
+ "mixing_graph_impl.cc",
+ "mixing_graph_impl.h",
+ "output_device_mixer.cc",
+ "output_device_mixer.h",
+ "output_device_mixer_impl.cc",
+ "output_device_mixer_impl.h",
+ "output_device_mixer_manager.cc",
+ "output_device_mixer_manager.h",
+ "sync_mixing_graph_input.cc",
+ "sync_mixing_graph_input.h",
+ ]
+
+ deps += []
+ }
+
configs += [
"//build/config/compiler:wexit_time_destructors",
"//media:media_config",
@@ -122,6 +163,7 @@ source_set("tests") {
sources = [
"debug_recording_unittest.cc",
"delay_buffer_unittest.cc",
+ "device_listener_output_stream_unittest.cc",
"device_notifier_unittest.cc",
"group_coordinator_unittest.cc",
"input_controller_unittest.cc",
@@ -171,4 +213,13 @@ source_set("tests") {
"public/cpp/sounds/sounds_manager_unittest.cc",
]
}
+
+ if (chrome_wide_echo_cancellation_supported) {
+ sources += [
+ "mixing_graph_impl_unittest.cc",
+ "mixing_graph_input_unittest.cc",
+ "output_device_mixer_impl_unittest.cc",
+ "output_device_mixer_manager_unittest.cc",
+ ]
+ }
}
diff --git a/chromium/services/audio/audio_processor.cc b/chromium/services/audio/audio_processor.cc
new file mode 100644
index 00000000000..5a9c742dd2e
--- /dev/null
+++ b/chromium/services/audio/audio_processor.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/audio_processor.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_bus.h"
+#include "services/audio/device_output_listener.h"
+
+namespace audio {
+
+class AudioProcessor::UmaLogger {
+ public:
+ UmaLogger(const std::string& device_id)
+ : is_default_(media::AudioDeviceDescription::IsDefaultDevice(device_id)),
+ start_(base::TimeTicks::Now()) {}
+
+ UmaLogger(const UmaLogger&) = delete;
+ UmaLogger& operator=(const UmaLogger&) = delete;
+
+ ~UmaLogger() {
+ base::UmaHistogramLongTimes(
+ base::StrCat({"Media.Audio.OutputDeviceListener.Duration.",
+ ((is_default_) ? "Default" : "NonDefault")}),
+ base::TimeTicks::Now() - start_);
+ }
+
+ private:
+ const bool is_default_;
+ base::TimeTicks start_;
+};
+
+AudioProcessor::AudioProcessor(DeviceOutputListener* device_output_listener,
+ LogCallback log_callback)
+ : device_output_listener_(device_output_listener),
+ log_callback_(std::move(log_callback)) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(device_output_listener_);
+}
+
+AudioProcessor::~AudioProcessor() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (active_)
+ Stop();
+}
+
+void AudioProcessor::SetOutputDeviceForAec(
+ const std::string& output_device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (output_device_id_ == output_device_id ||
+ (media::AudioDeviceDescription::IsDefaultDevice(output_device_id_) &&
+ media::AudioDeviceDescription::IsDefaultDevice(output_device_id))) {
+ return;
+ }
+
+ output_device_id_ = output_device_id;
+
+ if (active_)
+ StartListening();
+}
+
+void AudioProcessor::Start() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(!active_);
+ active_ = true;
+ StartListening();
+}
+
+void AudioProcessor::Stop() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(active_);
+ device_output_listener_->StopListening(this);
+ log_callback_.Run("AudioProcessor: stop listening");
+ active_ = false;
+ uma_logger_.reset();
+}
+
+void AudioProcessor::OnPlayoutData(const media::AudioBus& audio_bus,
+ int sample_rate,
+ base::TimeDelta delay) {
+ TRACE_EVENT2("audio", "AudioProcessor::OnData", " this ",
+ static_cast<void*>(this), "delay", delay.InMillisecondsF());
+}
+
+void AudioProcessor::StartListening() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(active_);
+ uma_logger_ = std::make_unique<UmaLogger>(output_device_id_);
+ log_callback_.Run(base::StrCat(
+ {"AudioProcessor: listening to output device: ", output_device_id_}));
+ device_output_listener_->StartListening(this, output_device_id_);
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/audio_processor.h b/chromium/services/audio/audio_processor.h
new file mode 100644
index 00000000000..aec014ab9ba
--- /dev/null
+++ b/chromium/services/audio/audio_processor.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_AUDIO_PROCESSOR_H_
+#define SERVICES_AUDIO_AUDIO_PROCESSOR_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/strings/string_piece.h"
+#include "services/audio/reference_output.h"
+
+namespace media {
+class AudioBus;
+} // namespace media
+
+namespace audio {
+class DeviceOutputListener;
+
+class AudioProcessor final : public ReferenceOutput::Listener {
+ public:
+ using LogCallback = base::RepeatingCallback<void(base::StringPiece)>;
+
+ AudioProcessor(DeviceOutputListener* device_output_listener,
+ LogCallback log_callback);
+ AudioProcessor(const AudioProcessor&) = delete;
+ AudioProcessor& operator=(const AudioProcessor&) = delete;
+ ~AudioProcessor() final;
+
+ void SetOutputDeviceForAec(const std::string& output_device_id);
+ void Start();
+ void Stop();
+
+ private:
+ class UmaLogger;
+ // Listener
+ void OnPlayoutData(const media::AudioBus& audio_bus,
+ int sample_rate,
+ base::TimeDelta delay) final;
+
+ void StartListening();
+
+ SEQUENCE_CHECKER(owning_sequence_);
+ bool active_ = false;
+ std::string output_device_id_;
+ raw_ptr<DeviceOutputListener> const device_output_listener_;
+ const LogCallback log_callback_;
+ std::unique_ptr<UmaLogger> uma_logger_;
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_AUDIO_PROCESSOR_H_
diff --git a/chromium/services/audio/debug_recording.h b/chromium/services/audio/debug_recording.h
index 653cd6d282d..25a323dcf9f 100644
--- a/chromium/services/audio/debug_recording.h
+++ b/chromium/services/audio/debug_recording.h
@@ -6,6 +6,7 @@
#define SERVICES_AUDIO_DEBUG_RECORDING_H_
#include "base/gtest_prod_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -46,7 +47,7 @@ class DebugRecording : public mojom::DebugRecording {
mojom::DebugRecordingFileProvider::CreateWavFileCallback reply_callback);
bool IsEnabled();
- media::AudioManager* const audio_manager_;
+ const raw_ptr<media::AudioManager> audio_manager_;
mojo::Receiver<mojom::DebugRecording> receiver_;
mojo::Remote<mojom::DebugRecordingFileProvider> file_provider_;
diff --git a/chromium/services/audio/debug_recording_unittest.cc b/chromium/services/audio/debug_recording_unittest.cc
index 3c821ac0cf2..075d5e606ad 100644
--- a/chromium/services/audio/debug_recording_unittest.cc
+++ b/chromium/services/audio/debug_recording_unittest.cc
@@ -41,6 +41,9 @@ class MockFileProvider : public mojom::DebugRecordingFileProvider {
const base::FilePath& file_name_base)
: receiver_(this, std::move(receiver)) {}
+ MockFileProvider(const MockFileProvider&) = delete;
+ MockFileProvider& operator=(const MockFileProvider&) = delete;
+
MOCK_METHOD2(DoCreateWavFile,
void(media::AudioDebugRecordingStreamType stream_type,
uint32_t id));
@@ -53,8 +56,6 @@ class MockFileProvider : public mojom::DebugRecordingFileProvider {
private:
mojo::Receiver<mojom::DebugRecordingFileProvider> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(MockFileProvider);
};
class DebugRecordingTest : public media::AudioDebugRecordingTest {
diff --git a/chromium/services/audio/delay_buffer.h b/chromium/services/audio/delay_buffer.h
index 833a4b892d9..4b2628eb75f 100644
--- a/chromium/services/audio/delay_buffer.h
+++ b/chromium/services/audio/delay_buffer.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/containers/circular_deque.h"
-#include "base/macros.h"
namespace media {
class AudioBus;
@@ -83,6 +82,9 @@ class DelayBuffer {
// Constructor for an InputChunk with data.
InputChunk(FrameTicks p, std::unique_ptr<media::AudioBus> b);
+ InputChunk(const InputChunk&) = delete;
+ InputChunk& operator=(const InputChunk&) = delete;
+
// Move constructor/assignment.
InputChunk(InputChunk&& other);
InputChunk& operator=(InputChunk&& other);
@@ -91,9 +93,6 @@ class DelayBuffer {
// Returns the position just after the last frame's position.
FrameTicks GetEndPosition() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InputChunk);
};
// The minimum number of un-read frames that must be kept.
diff --git a/chromium/services/audio/device_listener_output_stream.cc b/chromium/services/audio/device_listener_output_stream.cc
new file mode 100644
index 00000000000..221486fec1e
--- /dev/null
+++ b/chromium/services/audio/device_listener_output_stream.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/device_listener_output_stream.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/task/single_thread_task_runner.h"
+
+namespace audio {
+
+DeviceListenerOutputStream::DeviceListenerOutputStream(
+ media::AudioManager* audio_manager,
+ media::AudioOutputStream* wrapped_stream,
+ base::OnceClosure on_device_change_callback)
+ : audio_manager_(audio_manager),
+ stream_(wrapped_stream),
+ on_device_change_callback_(std::move(on_device_change_callback)),
+ task_runner_(audio_manager->GetTaskRunner()) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(stream_);
+ audio_manager_->AddOutputDeviceChangeListener(this);
+}
+
+DeviceListenerOutputStream::~DeviceListenerOutputStream() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ audio_manager_->RemoveOutputDeviceChangeListener(this);
+}
+
+bool DeviceListenerOutputStream::Open() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(on_device_change_callback_);
+ return stream_->Open();
+}
+
+void DeviceListenerOutputStream::Start(
+ media::AudioOutputStream::AudioSourceCallback* source_callback) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(!source_callback_);
+ DCHECK(source_callback);
+ DCHECK(on_device_change_callback_);
+ source_callback_ = source_callback;
+ stream_->Start(this);
+}
+
+void DeviceListenerOutputStream::Stop() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ stream_->Stop();
+ source_callback_ = nullptr;
+}
+
+void DeviceListenerOutputStream::SetVolume(double volume) {
+ stream_->SetVolume(volume);
+}
+
+void DeviceListenerOutputStream::GetVolume(double* volume) {
+ stream_->GetVolume(volume);
+}
+
+void DeviceListenerOutputStream::Close() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(!source_callback_);
+ stream_->Close();
+ // To match a typical AudioOutputStream usage pattern.
+ delete this;
+}
+
+void DeviceListenerOutputStream::Flush() {
+ stream_->Flush();
+}
+
+void DeviceListenerOutputStream::OnDeviceChange() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ std::move(on_device_change_callback_).Run();
+ // Close() must have been called and |this| deleted at this point.
+}
+
+int DeviceListenerOutputStream::OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) {
+ return source_callback_->OnMoreData(delay, delay_timestamp,
+ prior_frames_skipped, dest);
+}
+
+void DeviceListenerOutputStream::OnError(ErrorType type) {
+ if (type == ErrorType::kDeviceChange) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DeviceListenerOutputStream::OnDeviceChange,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+
+ // Handles errors on the audio manager thread. We defer errors for one
+ // second in case they are the result of a device change; delay chosen to
+ // exceed duration of device changes which take a few hundred milliseconds.
+ // |this| will be deleted after the client processes the device change, that
+ // way the posted callback will be cancelled.
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&DeviceListenerOutputStream::ReportError,
+ weak_factory_.GetWeakPtr(), type),
+ base::Seconds(1));
+}
+
+void DeviceListenerOutputStream::ReportError(ErrorType type) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK_NE(type, ErrorType::kDeviceChange);
+ if (source_callback_)
+ source_callback_->OnError(type);
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/device_listener_output_stream.h b/chromium/services/audio/device_listener_output_stream.h
new file mode 100644
index 00000000000..fd5687aa9ad
--- /dev/null
+++ b/chromium/services/audio/device_listener_output_stream.h
@@ -0,0 +1,81 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_DEVICE_LISTENER_OUTPUT_STREAM_H_
+#define SERVICES_AUDIO_DEVICE_LISTENER_OUTPUT_STREAM_H_
+
+#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_manager.h"
+
+namespace audio {
+
+// Simple wrapper class, which forwards all AudioOutputStream calls to the
+// wrapped |stream_|. It also listens for device change events (via
+// the AudioDeviceListener interface, or via errors reporting device changes),
+// and forwards them via the |on_device_change_callback_|, on the owning
+// (AudioManager) thread. |on_device_change_callback_| must synchronously close
+// the DeviceListenerOutputStream.
+class DeviceListenerOutputStream final
+ : public media::AudioOutputStream,
+ public media::AudioOutputStream::AudioSourceCallback,
+ public media::AudioManager::AudioDeviceListener {
+ public:
+ // Note: |on_device_change_callback| must synchronously call close(), which
+ // will delete |this|.
+ DeviceListenerOutputStream(media::AudioManager* audio_manager,
+ media::AudioOutputStream* wrapped_stream,
+ base::OnceClosure on_device_change_callback);
+
+ DeviceListenerOutputStream(const DeviceListenerOutputStream&) = delete;
+ DeviceListenerOutputStream& operator=(const DeviceListenerOutputStream&) =
+ delete;
+
+ // AudioOutputStream implementation
+ bool Open() final;
+ void Start(
+ media::AudioOutputStream::AudioSourceCallback* source_callback) final;
+ void Stop() final;
+ void SetVolume(double volume) final;
+ void GetVolume(double* volume) final;
+ void Close() final;
+ void Flush() final;
+
+ private:
+ ~DeviceListenerOutputStream() final;
+
+ // AudioManager::AudioDeviceListener implementation.
+ void OnDeviceChange() final;
+
+ // AudioOutputStream::AudioSourceCallback implementation.
+ int OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) final;
+ void OnError(ErrorType type) final;
+
+ void ReportError(ErrorType type);
+
+ const raw_ptr<media::AudioManager> audio_manager_;
+
+ const raw_ptr<media::AudioOutputStream> stream_;
+
+ // Callback to process the device change.
+ base::OnceClosure on_device_change_callback_;
+
+ // Actual producer of the audio.
+ raw_ptr<media::AudioOutputStream::AudioSourceCallback> source_callback_ =
+ nullptr;
+
+ // The task runner for the audio manager. The main task runner for the object.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // For posting cancelable tasks.
+ base::WeakPtrFactory<DeviceListenerOutputStream> weak_factory_{this};
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_DEVICE_LISTENER_OUTPUT_STREAM_H_
diff --git a/chromium/services/audio/device_listener_output_stream_unittest.cc b/chromium/services/audio/device_listener_output_stream_unittest.cc
new file mode 100644
index 00000000000..cbf03bae297
--- /dev/null
+++ b/chromium/services/audio/device_listener_output_stream_unittest.cc
@@ -0,0 +1,323 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/device_listener_output_stream.h"
+
+#include "base/memory/raw_ptr.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/task_environment.h"
+#include "media/audio/fake_audio_log_factory.h"
+#include "media/audio/fake_audio_manager.h"
+#include "media/audio/mock_audio_source_callback.h"
+#include "media/audio/test_audio_thread.h"
+#include "media/base/audio_parameters.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using ::testing::_;
+using ::testing::InSequence;
+
+using media::AudioBus;
+using media::AudioManager;
+using media::AudioOutputStream;
+using media::MockAudioSourceCallback;
+
+using base::test::RunOnceClosure;
+
+namespace audio {
+namespace {
+
+class MockAudioOutputStream : public AudioOutputStream {
+ public:
+ MockAudioOutputStream() = default;
+ ~MockAudioOutputStream() override = default;
+
+ void Start(AudioSourceCallback* callback) override {
+ provided_callback_ = callback;
+ StartCalled(provided_callback_);
+ }
+
+ MOCK_METHOD1(StartCalled, void(AudioSourceCallback*));
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD0(Open, bool());
+ MOCK_METHOD1(SetVolume, void(double volume));
+ MOCK_METHOD1(GetVolume, void(double* volume));
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(Flush, void());
+
+ int SimulateOnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ AudioBus* dest) {
+ DCHECK(provided_callback_);
+ return provided_callback_->OnMoreData(delay, delay_timestamp,
+ prior_frames_skipped, dest);
+ }
+
+ void SimulateError(AudioSourceCallback::ErrorType error) {
+ DCHECK(provided_callback_);
+ provided_callback_->OnError(error);
+ }
+
+ private:
+ raw_ptr<AudioOutputStream::AudioSourceCallback> provided_callback_ = nullptr;
+};
+
+class FakeAudioManagerForDeviceChange : public media::FakeAudioManager {
+ public:
+ FakeAudioManagerForDeviceChange()
+ : FakeAudioManager(std::make_unique<media::TestAudioThread>(),
+ &fake_audio_log_factory_) {}
+ ~FakeAudioManagerForDeviceChange() override = default;
+
+ void AddOutputDeviceChangeListener(AudioDeviceListener* listener) override {
+ media::FakeAudioManager::AddOutputDeviceChangeListener(listener);
+ AddOutputDeviceChangeListenerCalled(listener);
+ }
+
+ void RemoveOutputDeviceChangeListener(
+ AudioDeviceListener* listener) override {
+ media::FakeAudioManager::RemoveOutputDeviceChangeListener(listener);
+ RemoveOutputDeviceChangeListenerCalled(listener);
+ }
+
+ MOCK_METHOD1(AddOutputDeviceChangeListenerCalled,
+ void(AudioManager::AudioDeviceListener*));
+ MOCK_METHOD1(RemoveOutputDeviceChangeListenerCalled,
+ void(AudioManager::AudioDeviceListener*));
+
+ void SimulateDeviceChange() { NotifyAllOutputDeviceChangeListeners(); }
+
+ private:
+ media::FakeAudioLogFactory fake_audio_log_factory_;
+};
+
+class DeviceListenerOutputStreamTest : public ::testing::Test {
+ public:
+ using ErrorType = AudioOutputStream::AudioSourceCallback::ErrorType;
+
+ MOCK_METHOD0(DeviceChangeCallbackCalled, void());
+};
+
+// Verifies DeviceListenerOutputStream forwards all calls to the wrapped stream.
+TEST_F(DeviceListenerOutputStreamTest, DelegatesCallsToWrappedStream) {
+ base::test::SingleThreadTaskEnvironment task_environment;
+ FakeAudioManagerForDeviceChange mock_audio_manager;
+ MockAudioOutputStream mock_stream;
+ MockAudioSourceCallback mock_callback;
+
+ double volume = 200;
+ base::TimeDelta delay = base::Milliseconds(30);
+ base::TimeTicks delay_timestamp =
+ base::TimeTicks() + base::Milliseconds(21);
+ int prior_frames_skipped = 44;
+ std::unique_ptr<media::AudioBus> dest = media::AudioBus::Create(1, 128);
+
+ InSequence sequence;
+ EXPECT_CALL(mock_audio_manager, AddOutputDeviceChangeListenerCalled(_))
+ .Times(1);
+ EXPECT_CALL(mock_stream, Open()).Times(1);
+ EXPECT_CALL(mock_stream, StartCalled(_)).Times(1);
+ EXPECT_CALL(mock_callback, OnMoreData(delay, delay_timestamp,
+ prior_frames_skipped, dest.get()));
+ EXPECT_CALL(mock_stream, SetVolume(volume)).Times(1);
+ EXPECT_CALL(mock_stream, GetVolume(&volume)).Times(1);
+ EXPECT_CALL(mock_stream, Stop()).Times(1);
+ EXPECT_CALL(mock_stream, Flush()).Times(1);
+ EXPECT_CALL(mock_stream, Close()).Times(1);
+
+ DeviceListenerOutputStream* stream_under_test =
+ new DeviceListenerOutputStream(
+ &mock_audio_manager, &mock_stream,
+ base::BindRepeating(
+ &DeviceListenerOutputStreamTest::DeviceChangeCallbackCalled,
+ base::Unretained(this)));
+ EXPECT_CALL(mock_audio_manager,
+ RemoveOutputDeviceChangeListenerCalled(stream_under_test))
+ .Times(1);
+
+ stream_under_test->Open();
+ stream_under_test->Start(&mock_callback);
+ mock_stream.SimulateOnMoreData(delay, delay_timestamp, prior_frames_skipped,
+ dest.get());
+ stream_under_test->SetVolume(volume);
+ stream_under_test->GetVolume(&volume);
+ stream_under_test->Stop();
+ stream_under_test->Flush();
+ stream_under_test->Close();
+
+ mock_audio_manager.Shutdown();
+}
+
+// Verifies DeviceListenerOutputStream calls device change callback on device
+// change.
+TEST_F(DeviceListenerOutputStreamTest, DeviceChangeNotification) {
+ base::test::SingleThreadTaskEnvironment task_environment;
+ FakeAudioManagerForDeviceChange mock_audio_manager;
+ MockAudioOutputStream mock_stream;
+ MockAudioSourceCallback mock_callback;
+
+ // |stream_under_test| should call the provided callback on device change.
+ EXPECT_CALL(*this, DeviceChangeCallbackCalled()).Times(1);
+
+ DeviceListenerOutputStream* stream_under_test =
+ new DeviceListenerOutputStream(
+ &mock_audio_manager, &mock_stream,
+ base::BindRepeating(
+ &DeviceListenerOutputStreamTest::DeviceChangeCallbackCalled,
+ base::Unretained(this)));
+
+ stream_under_test->Open();
+ stream_under_test->Start(&mock_callback);
+
+ mock_audio_manager.SimulateDeviceChange();
+
+ stream_under_test->Stop();
+ stream_under_test->Close();
+ mock_audio_manager.Shutdown();
+}
+
+// Verifies DeviceListenerOutputStream calls device change callbacks on device
+// change errors.
+TEST_F(DeviceListenerOutputStreamTest, DeviceChangeError) {
+ base::test::SingleThreadTaskEnvironment task_environment;
+ FakeAudioManagerForDeviceChange mock_audio_manager;
+ MockAudioOutputStream mock_stream;
+ MockAudioSourceCallback mock_callback;
+
+ base::RunLoop loop;
+ // |stream_under_test| should call the provided callback if it received a
+ // device change error.
+ EXPECT_CALL(*this, DeviceChangeCallbackCalled())
+ .WillOnce(RunOnceClosure(loop.QuitClosure()));
+
+ // |stream_under_test| should not forward device change errors.
+ EXPECT_CALL(mock_callback, OnError(_)).Times(0);
+
+ DeviceListenerOutputStream* stream_under_test =
+ new DeviceListenerOutputStream(
+ &mock_audio_manager, &mock_stream,
+ base::BindRepeating(
+ &DeviceListenerOutputStreamTest::DeviceChangeCallbackCalled,
+ base::Unretained(this)));
+
+ stream_under_test->Open();
+ stream_under_test->Start(&mock_callback);
+
+ // Simulate a device change error.
+ mock_stream.SimulateError(ErrorType::kDeviceChange);
+
+ loop.Run();
+
+ stream_under_test->Stop();
+ stream_under_test->Close();
+ mock_audio_manager.Shutdown();
+}
+
+// Verifies DeviceListenerOutputStream forwards error callbacks.
+TEST_F(DeviceListenerOutputStreamTest, UnknownError) {
+ base::test::SingleThreadTaskEnvironment task_environment;
+ FakeAudioManagerForDeviceChange mock_audio_manager;
+ MockAudioOutputStream mock_stream;
+ MockAudioSourceCallback mock_callback;
+
+ base::RunLoop loop;
+ // |stream_under_test| should forward errors.
+ EXPECT_CALL(*this, DeviceChangeCallbackCalled()).Times(0);
+ EXPECT_CALL(mock_callback, OnError(ErrorType::kUnknown))
+ .WillOnce(RunOnceClosure(loop.QuitClosure()));
+
+ DeviceListenerOutputStream* stream_under_test =
+ new DeviceListenerOutputStream(
+ &mock_audio_manager, &mock_stream,
+ base::BindRepeating(
+ &DeviceListenerOutputStreamTest::DeviceChangeCallbackCalled,
+ base::Unretained(this)));
+
+ stream_under_test->Open();
+ stream_under_test->Start(&mock_callback);
+
+ // Simulate a device change error.
+ mock_stream.SimulateError(ErrorType::kUnknown);
+
+ loop.Run();
+
+ stream_under_test->Stop();
+ stream_under_test->Close();
+ mock_audio_manager.Shutdown();
+}
+
+// Verifies DeviceListenerOutputStream elides error notifications during device
+// changes.
+TEST_F(DeviceListenerOutputStreamTest, ErrorThenDeviceChange) {
+ base::test::SingleThreadTaskEnvironment task_environment;
+ FakeAudioManagerForDeviceChange mock_audio_manager;
+ MockAudioOutputStream mock_stream;
+ MockAudioSourceCallback mock_callback;
+
+ base::RunLoop loop;
+ // |stream_under_test| should call device change callback.
+ EXPECT_CALL(*this, DeviceChangeCallbackCalled())
+ .WillOnce(RunOnceClosure(loop.QuitClosure()));
+
+ // |stream_under_test| should drop deferred errors.
+ EXPECT_CALL(mock_callback, OnError(_)).Times(0);
+
+ DeviceListenerOutputStream* stream_under_test =
+ new DeviceListenerOutputStream(
+ &mock_audio_manager, &mock_stream,
+ base::BindRepeating(
+ &DeviceListenerOutputStreamTest::DeviceChangeCallbackCalled,
+ base::Unretained(this)));
+
+ stream_under_test->Open();
+ stream_under_test->Start(&mock_callback);
+
+ // Simulate an error, followed by a device change.
+ mock_stream.SimulateError(ErrorType::kUnknown);
+ mock_audio_manager.SimulateDeviceChange();
+
+ loop.Run();
+
+ stream_under_test->Stop();
+ stream_under_test->Close();
+ mock_audio_manager.Shutdown();
+}
+
+// Verifies DeviceListenerOutputStream can be stopped after receiving an error.
+TEST_F(DeviceListenerOutputStreamTest, ErrorThenStop) {
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+ FakeAudioManagerForDeviceChange mock_audio_manager;
+ MockAudioOutputStream mock_stream;
+ MockAudioSourceCallback mock_callback;
+
+ // |stream_under_test| should not call its error callback after it has been
+ // stopped.
+ EXPECT_CALL(mock_callback, OnError(_)).Times(0);
+
+ DeviceListenerOutputStream* stream_under_test =
+ new DeviceListenerOutputStream(
+ &mock_audio_manager, &mock_stream,
+ base::BindRepeating(
+ &DeviceListenerOutputStreamTest::DeviceChangeCallbackCalled,
+ base::Unretained(this)));
+
+ stream_under_test->Open();
+ stream_under_test->Start(&mock_callback);
+
+ // Call stop() immediately after an error.
+ mock_stream.SimulateError(ErrorType::kUnknown);
+ stream_under_test->Stop();
+
+ // Reporting the error should be delayed by 1s.
+ task_environment.FastForwardUntilNoTasksRemain();
+
+ stream_under_test->Close();
+ mock_audio_manager.Shutdown();
+}
+
+} // namespace
+} // namespace audio
diff --git a/chromium/services/audio/device_notifier.cc b/chromium/services/audio/device_notifier.cc
index 294475a4688..df15c2cc9f2 100644
--- a/chromium/services/audio/device_notifier.cc
+++ b/chromium/services/audio/device_notifier.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/services/audio/device_notifier_unittest.cc b/chromium/services/audio/device_notifier_unittest.cc
index 910fb808622..002bcbef584 100644
--- a/chromium/services/audio/device_notifier_unittest.cc
+++ b/chromium/services/audio/device_notifier_unittest.cc
@@ -25,12 +25,14 @@ class MockDeviceListener : public mojom::DeviceListener {
explicit MockDeviceListener(
mojo::PendingReceiver<audio::mojom::DeviceListener> receiver)
: receiver_(this, std::move(receiver)) {}
+
+ MockDeviceListener(const MockDeviceListener&) = delete;
+ MockDeviceListener& operator=(const MockDeviceListener&) = delete;
+
MOCK_METHOD0(DevicesChanged, void());
private:
mojo::Receiver<audio::mojom::DeviceListener> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDeviceListener);
};
} // namespace
@@ -40,6 +42,9 @@ class DeviceNotifierTest : public ::testing::Test {
DeviceNotifierTest()
: system_monitor_(std::make_unique<base::SystemMonitor>()) {}
+ DeviceNotifierTest(const DeviceNotifierTest&) = delete;
+ DeviceNotifierTest& operator=(const DeviceNotifierTest&) = delete;
+
protected:
void CreateDeviceNotifier() {
device_notifier_ = std::make_unique<DeviceNotifier>();
@@ -58,8 +63,6 @@ class DeviceNotifierTest : public ::testing::Test {
private:
std::unique_ptr<base::SystemMonitor> system_monitor_;
std::unique_ptr<DeviceNotifier> device_notifier_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceNotifierTest);
};
TEST_F(DeviceNotifierTest, DeviceNotifierNotifies) {
diff --git a/chromium/services/audio/device_output_listener.h b/chromium/services/audio/device_output_listener.h
new file mode 100644
index 00000000000..67cd5005f5a
--- /dev/null
+++ b/chromium/services/audio/device_output_listener.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_DEVICE_OUTPUT_LISTENER_H_
+#define SERVICES_AUDIO_DEVICE_OUTPUT_LISTENER_H_
+
+#include <string>
+
+#include "services/audio/reference_output.h"
+
+namespace audio {
+
+// Interface to start/stop listening to a device's reference output.
+class DeviceOutputListener {
+ public:
+ virtual ~DeviceOutputListener() = default;
+
+ // Starts listening to |device_id|'s output. Can be called multiple times
+ // without calling StopListening(); each new call will replace which device
+ // |listener| is listening to.
+ //
+ // |device_id| is expected to be a physical device ID, or the default device
+ // ID, as defined by media::AudioDeviceDescription::IsDefaultDevice().
+ //
+ // If ever |device_id|'s validity changes (after disconnecting/reconnecting a
+ // device), |listener| might start/stop receiving OnPlayoutData() calls.
+ virtual void StartListening(ReferenceOutput::Listener* listener,
+ const std::string& device_id) = 0;
+
+ // Stop |listener| from receiving its current device's reference output.
+ // Must be called when |listener| no longer wants to receive data (e.g.
+ // before it is destroyed). StartListening() must have been called.
+ virtual void StopListening(ReferenceOutput::Listener* listener) = 0;
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_DEVICE_OUTPUT_LISTENER_H_
diff --git a/chromium/services/audio/group_coordinator.h b/chromium/services/audio/group_coordinator.h
index e695a049309..0db1ee1bf76 100644
--- a/chromium/services/audio/group_coordinator.h
+++ b/chromium/services/audio/group_coordinator.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/check.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/unguessable_token.h"
@@ -34,6 +33,10 @@ class GroupCoordinator {
};
GroupCoordinator();
+
+ GroupCoordinator(const GroupCoordinator&) = delete;
+ GroupCoordinator& operator=(const GroupCoordinator&) = delete;
+
~GroupCoordinator();
// Registers/Unregisters a group |member|. The member must remain valid until
@@ -63,12 +66,14 @@ class GroupCoordinator {
std::vector<Observer*> observers;
Group();
- ~Group();
+
+ Group(const Group&) = delete;
+ Group& operator=(const Group&) = delete;
+
Group(Group&& other);
Group& operator=(Group&& other);
- private:
- DISALLOW_COPY_AND_ASSIGN(Group);
+ ~Group();
};
using GroupMap = std::vector<std::pair<base::UnguessableToken, Group>>;
@@ -90,8 +95,6 @@ class GroupCoordinator {
#endif
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(GroupCoordinator);
};
} // namespace audio
diff --git a/chromium/services/audio/in_process_audio_manager_accessor.cc b/chromium/services/audio/in_process_audio_manager_accessor.cc
index 4f889fe02ab..225ac3e2e8c 100644
--- a/chromium/services/audio/in_process_audio_manager_accessor.cc
+++ b/chromium/services/audio/in_process_audio_manager_accessor.cc
@@ -4,8 +4,7 @@
#include "services/audio/in_process_audio_manager_accessor.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "media/audio/audio_manager.h"
namespace audio {
diff --git a/chromium/services/audio/in_process_audio_manager_accessor.h b/chromium/services/audio/in_process_audio_manager_accessor.h
index 16f9b0fba75..dd9c183cb38 100644
--- a/chromium/services/audio/in_process_audio_manager_accessor.h
+++ b/chromium/services/audio/in_process_audio_manager_accessor.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_AUDIO_IN_PROCESS_AUDIO_MANAGER_ACCESSOR_H_
#define SERVICES_AUDIO_IN_PROCESS_AUDIO_MANAGER_ACCESSOR_H_
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "services/audio/service.h"
namespace media {
@@ -36,7 +36,7 @@ class InProcessAudioManagerAccessor final
void SetAudioLogFactory(media::AudioLogFactory* factory) final;
private:
- media::AudioManager* const audio_manager_;
+ const raw_ptr<media::AudioManager> audio_manager_;
};
} // namespace audio
diff --git a/chromium/services/audio/input_controller.cc b/chromium/services/audio/input_controller.cc
index 283527ac524..f13afc7d6c5 100644
--- a/chromium/services/audio/input_controller.cc
+++ b/chromium/services/audio/input_controller.cc
@@ -15,10 +15,11 @@
#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -27,7 +28,9 @@
#include "media/audio/audio_manager.h"
#include "media/base/audio_bus.h"
#include "media/base/user_input_monitor.h"
+#include "services/audio/audio_processor.h"
#include "services/audio/concurrent_stream_metric_reporter.h"
+#include "services/audio/device_output_listener.h"
namespace audio {
namespace {
@@ -193,7 +196,7 @@ class InputController::AudioCallback
}
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- InputController* const controller_;
+ const raw_ptr<InputController> controller_;
// We do not want any pending posted tasks generated from the callback class
// to keep the controller object alive longer than it should. So we use
// a weak ptr whenever we post, we use this weak pointer.
@@ -206,6 +209,7 @@ InputController::InputController(EventHandler* handler,
SyncWriter* sync_writer,
media::UserInputMonitor* user_input_monitor,
InputStreamActivityMonitor* activity_monitor,
+ DeviceOutputListener* device_output_listener,
const media::AudioParameters& params,
StreamType type)
: handler_(handler),
@@ -218,6 +222,16 @@ InputController::InputController(EventHandler* handler,
DCHECK(handler_);
DCHECK(sync_writer_);
DCHECK(activity_monitor_);
+
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ if (device_output_listener) {
+ // Unretained() is safe, because |handler_| outlives |audio_processor_|.
+ audio_processor_ = std::make_unique<AudioProcessor>(
+ device_output_listener,
+ base::BindRepeating(&EventHandler::OnLog, base::Unretained(handler_)));
+ }
+#endif
+
if (!user_input_monitor_) {
handler_->OnLog(
"AIC::InputController() => (WARNING: keypress monitoring is disabled)");
@@ -238,6 +252,7 @@ std::unique_ptr<InputController> InputController::Create(
SyncWriter* sync_writer,
media::UserInputMonitor* user_input_monitor,
InputStreamActivityMonitor* activity_monitor,
+ DeviceOutputListener* device_output_listener,
const media::AudioParameters& params,
const std::string& device_id,
bool enable_agc) {
@@ -254,8 +269,8 @@ std::unique_ptr<InputController> InputController::Create(
// Create the InputController object and ensure that it runs on
// the audio-manager thread.
std::unique_ptr<InputController> controller(new InputController(
- event_handler, sync_writer, user_input_monitor, activity_monitor, params,
- ParamsToStreamType(params)));
+ event_handler, sync_writer, user_input_monitor, activity_monitor,
+ device_output_listener, params, ParamsToStreamType(params)));
controller->DoCreate(audio_manager, params, device_id, enable_agc);
return controller;
@@ -278,6 +293,12 @@ void InputController::Record() {
stream_create_time_ = base::TimeTicks::Now();
audio_callback_ = std::make_unique<AudioCallback>(this);
+
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ if (audio_processor_)
+ audio_processor_->Start();
+#endif
+
stream_->Start(audio_callback_.get());
activity_monitor_->OnInputStreamActive();
return;
@@ -297,6 +318,10 @@ void InputController::Close() {
// Allow calling unconditionally and bail if we don't have a stream to close.
if (audio_callback_) {
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ if (audio_processor_)
+ audio_processor_->Stop();
+#endif
stream_->Stop();
activity_monitor_->OnInputStreamInactive();
@@ -389,6 +414,11 @@ void InputController::SetOutputDeviceForAec(
DCHECK_CALLED_ON_VALID_THREAD(owning_thread_);
if (stream_)
stream_->SetOutputDeviceForAec(output_device_id);
+
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ if (audio_processor_)
+ audio_processor_->SetOutputDeviceForAec(output_device_id);
+#endif
}
void InputController::OnStreamActive(Snoopable* output_stream) {
diff --git a/chromium/services/audio/input_controller.h b/chromium/services/audio/input_controller.h
index 88acc1194b2..3d485459979 100644
--- a/chromium/services/audio/input_controller.h
+++ b/chromium/services/audio/input_controller.h
@@ -11,6 +11,7 @@
#include <memory>
#include <string>
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
@@ -21,17 +22,21 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/audio/snoopable.h"
+#include "services/audio/buildflags.h"
#include "services/audio/stream_monitor.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace media {
class AudioBus;
class AudioInputStream;
class AudioManager;
+class Snoopable;
class UserInputMonitor;
} // namespace media
namespace audio {
+class AudioProcessor;
+class DeviceOutputListener;
class InputStreamActivityMonitor;
// Only do power monitoring for non-mobile platforms to save resources.
@@ -142,6 +147,7 @@ class InputController final : public StreamMonitor {
SyncWriter* sync_writer,
media::UserInputMonitor* user_input_monitor,
InputStreamActivityMonitor* activity_monitor,
+ DeviceOutputListener* device_output_listener,
const media::AudioParameters& params,
const std::string& device_id,
bool agc_is_enabled);
@@ -190,6 +196,7 @@ class InputController final : public StreamMonitor {
SyncWriter* sync_writer,
media::UserInputMonitor* user_input_monitor,
InputStreamActivityMonitor* activity_monitor,
+ DeviceOutputListener* device_output_listener,
const media::AudioParameters& params,
StreamType type);
@@ -245,23 +252,27 @@ class InputController final : public StreamMonitor {
// Contains the InputController::EventHandler which receives state
// notifications from this class.
- EventHandler* const handler_;
+ const raw_ptr<EventHandler> handler_;
// Pointer to the audio input stream object.
// Only used on the audio thread.
- media::AudioInputStream* stream_ = nullptr;
+ raw_ptr<media::AudioInputStream> stream_ = nullptr;
// SyncWriter is used only in low-latency mode for synchronous writing.
- SyncWriter* const sync_writer_;
+ const raw_ptr<SyncWriter> sync_writer_;
StreamType type_;
double max_volume_ = 0.0;
- media::UserInputMonitor* const user_input_monitor_;
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ std::unique_ptr<AudioProcessor> audio_processor_;
+#endif
+
+ const raw_ptr<media::UserInputMonitor> user_input_monitor_;
// Notified when the stream starts/stops recording.
- InputStreamActivityMonitor* const activity_monitor_;
+ const raw_ptr<InputStreamActivityMonitor> activity_monitor_;
#if defined(AUDIO_POWER_MONITORING)
// Whether the silence state and microphone levels should be checked and sent
diff --git a/chromium/services/audio/input_controller_unittest.cc b/chromium/services/audio/input_controller_unittest.cc
index ded0323557d..62e0ad9e70b 100644
--- a/chromium/services/audio/input_controller_unittest.cc
+++ b/chromium/services/audio/input_controller_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -21,6 +20,8 @@
#include "media/webrtc/webrtc_features.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/audio/concurrent_stream_metric_reporter.h"
+#include "services/audio/device_output_listener.h"
+#include "services/audio/reference_output.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -52,14 +53,16 @@ class MockInputControllerEventHandler : public InputController::EventHandler {
public:
MockInputControllerEventHandler() = default;
+ MockInputControllerEventHandler(const MockInputControllerEventHandler&) =
+ delete;
+ MockInputControllerEventHandler& operator=(
+ const MockInputControllerEventHandler&) = delete;
+
void OnLog(base::StringPiece) override {}
MOCK_METHOD1(OnCreated, void(bool initially_muted));
MOCK_METHOD1(OnError, void(InputController::ErrorCode error_code));
MOCK_METHOD1(OnMuted, void(bool is_muted));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockInputControllerEventHandler);
};
class MockSyncWriter : public InputController::SyncWriter {
@@ -136,10 +139,11 @@ class TimeSourceInputControllerTest : public ::testing::Test {
}
protected:
- void CreateAudioController() {
+ virtual void CreateAudioController() {
controller_ = InputController::Create(
audio_manager_.get(), &event_handler_, &sync_writer_,
- &user_input_monitor_, &mock_stream_activity_monitor_, params_,
+ &user_input_monitor_, &mock_stream_activity_monitor_,
+ /*device_output_listener =*/nullptr, params_,
media::AudioDeviceDescription::kDefaultDeviceId, false);
}
@@ -286,4 +290,91 @@ TEST_F(InputControllerTest, TestOnmutedCallbackInitiallyMuted) {
controller_->Close();
}
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+class MockDeviceOutputListener : public DeviceOutputListener {
+ public:
+ MockDeviceOutputListener() = default;
+ ~MockDeviceOutputListener() override = default;
+
+ MOCK_METHOD2(StartListening,
+ void(ReferenceOutput::Listener*, const std::string&));
+ MOCK_METHOD1(StopListening, void(ReferenceOutput::Listener*));
+};
+
+class InputControllerTestWithDeviceListener : public InputControllerTest {
+ protected:
+ void CreateAudioController() final {
+ controller_ = InputController::Create(
+ audio_manager_.get(), &event_handler_, &sync_writer_,
+ &user_input_monitor_, &mock_stream_activity_monitor_,
+ &device_output_listener_, params_,
+ media::AudioDeviceDescription::kDefaultDeviceId, false);
+ }
+
+ MockDeviceOutputListener device_output_listener_;
+};
+
+TEST_F(InputControllerTestWithDeviceListener, RecordBeforeSetOutputForAec) {
+ const std::string kOutputDeviceId = "0x123";
+ EXPECT_CALL(mock_stream_activity_monitor_, OnInputStreamActive()).Times(1);
+ EXPECT_CALL(mock_stream_activity_monitor_, OnInputStreamInactive()).Times(1);
+
+ // Calling Record() will start listening to the "" device by default.
+ EXPECT_CALL(device_output_listener_, StartListening(_, "")).Times(1);
+ EXPECT_CALL(device_output_listener_, StartListening(_, kOutputDeviceId))
+ .Times(1);
+ EXPECT_CALL(device_output_listener_, StopListening(_)).Times(1);
+
+ CreateAudioController();
+
+ ASSERT_TRUE(controller_.get());
+
+ controller_->Record();
+ controller_->SetOutputDeviceForAec(kOutputDeviceId);
+ controller_->Close();
+}
+
+TEST_F(InputControllerTestWithDeviceListener, RecordAfterSetOutputForAec) {
+ const std::string kOutputDeviceId = "0x123";
+ EXPECT_CALL(mock_stream_activity_monitor_, OnInputStreamActive()).Times(1);
+ EXPECT_CALL(mock_stream_activity_monitor_, OnInputStreamInactive()).Times(1);
+ EXPECT_CALL(device_output_listener_, StartListening(_, kOutputDeviceId))
+ .Times(1);
+ EXPECT_CALL(device_output_listener_, StopListening(_)).Times(1);
+
+ CreateAudioController();
+
+ ASSERT_TRUE(controller_.get());
+
+ controller_->SetOutputDeviceForAec(kOutputDeviceId);
+ controller_->Record();
+ controller_->Close();
+}
+
+TEST_F(InputControllerTestWithDeviceListener, ChangeOutputForAec) {
+ const std::string kOutputDeviceId = "0x123";
+ const std::string kOtherOutputDeviceId = "0x987";
+ EXPECT_CALL(mock_stream_activity_monitor_, OnInputStreamActive()).Times(1);
+ EXPECT_CALL(mock_stream_activity_monitor_, OnInputStreamInactive()).Times(1);
+
+ // Each output ID should receive one call to StartListening().
+ EXPECT_CALL(device_output_listener_, StartListening(_, kOutputDeviceId))
+ .Times(1);
+ EXPECT_CALL(device_output_listener_, StartListening(_, kOtherOutputDeviceId))
+ .Times(1);
+
+ // StopListening() should be called once, regardless of how many ID changes.
+ EXPECT_CALL(device_output_listener_, StopListening(_)).Times(1);
+
+ CreateAudioController();
+
+ ASSERT_TRUE(controller_.get());
+
+ controller_->SetOutputDeviceForAec(kOutputDeviceId);
+ controller_->Record();
+ controller_->SetOutputDeviceForAec(kOtherOutputDeviceId);
+ controller_->Close();
+}
+#endif // BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+
} // namespace audio
diff --git a/chromium/services/audio/input_stream.cc b/chromium/services/audio/input_stream.cc
index c0d037ca0d5..f74a35e92e2 100644
--- a/chromium/services/audio/input_stream.cc
+++ b/chromium/services/audio/input_stream.cc
@@ -72,6 +72,7 @@ InputStream::InputStream(
media::AudioManager* audio_manager,
std::unique_ptr<UserInputMonitor> user_input_monitor,
InputStreamActivityMonitor* activity_monitor,
+ DeviceOutputListener* device_output_listener,
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
@@ -132,7 +133,7 @@ InputStream::InputStream(
controller_ = InputController::Create(
audio_manager, this, writer_.get(), user_input_monitor_.get(),
- activity_monitor, params, device_id, enable_agc);
+ activity_monitor, device_output_listener, params, device_id, enable_agc);
}
InputStream::~InputStream() {
diff --git a/chromium/services/audio/input_stream.h b/chromium/services/audio/input_stream.h
index dac4597b965..e2b86ffb293 100644
--- a/chromium/services/audio/input_stream.h
+++ b/chromium/services/audio/input_stream.h
@@ -30,6 +30,7 @@ class AudioParameters;
namespace audio {
+class DeviceOutputListener;
class InputStreamActivityMonitor;
class InputSyncWriter;
class UserInputMonitor;
@@ -53,6 +54,7 @@ class InputStream final : public media::mojom::AudioInputStream,
media::AudioManager* manager,
std::unique_ptr<UserInputMonitor> user_input_monitor,
InputStreamActivityMonitor* activity_monitor,
+ DeviceOutputListener* device_output_listener,
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
diff --git a/chromium/services/audio/input_stream_unittest.cc b/chromium/services/audio/input_stream_unittest.cc
index bbb49aa6a31..aca923a6d6f 100644
--- a/chromium/services/audio/input_stream_unittest.cc
+++ b/chromium/services/audio/input_stream_unittest.cc
@@ -48,6 +48,9 @@ class MockStreamClient : public media::mojom::AudioInputStreamClient {
public:
MockStreamClient() = default;
+ MockStreamClient(const MockStreamClient&) = delete;
+ MockStreamClient& operator=(const MockStreamClient&) = delete;
+
mojo::PendingRemote<media::mojom::AudioInputStreamClient> MakeRemote() {
DCHECK(!receiver_.is_bound());
mojo::PendingRemote<media::mojom::AudioInputStreamClient> remote;
@@ -65,14 +68,15 @@ class MockStreamClient : public media::mojom::AudioInputStreamClient {
private:
mojo::Receiver<media::mojom::AudioInputStreamClient> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(MockStreamClient);
};
class MockStreamObserver : public media::mojom::AudioInputStreamObserver {
public:
MockStreamObserver() = default;
+ MockStreamObserver(const MockStreamObserver&) = delete;
+ MockStreamObserver& operator=(const MockStreamObserver&) = delete;
+
mojo::PendingRemote<media::mojom::AudioInputStreamObserver> MakeRemote() {
DCHECK(!receiver_.is_bound());
mojo::PendingRemote<media::mojom::AudioInputStreamObserver> remote;
@@ -90,14 +94,15 @@ class MockStreamObserver : public media::mojom::AudioInputStreamObserver {
private:
mojo::Receiver<media::mojom::AudioInputStreamObserver> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(MockStreamObserver);
};
class MockStream : public media::AudioInputStream {
public:
MockStream() {}
+ MockStream(const MockStream&) = delete;
+ MockStream& operator=(const MockStream&) = delete;
+
double GetMaxVolume() override { return 1; }
MOCK_METHOD0(Open, media::AudioInputStream::OpenOutcome());
@@ -110,9 +115,6 @@ class MockStream : public media::AudioInputStream {
MOCK_METHOD0(GetAutomaticGainControl, bool());
MOCK_METHOD0(IsMuted, bool());
MOCK_METHOD1(SetOutputDeviceForAec, void(const std::string&));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockStream);
};
} // namespace
diff --git a/chromium/services/audio/input_sync_writer.cc b/chromium/services/audio/input_sync_writer.cc
index b038cafa5b6..5221973defa 100644
--- a/chromium/services/audio/input_sync_writer.cc
+++ b/chromium/services/audio/input_sync_writer.cc
@@ -9,7 +9,7 @@
#include "base/format_macros.h"
#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -20,10 +20,10 @@ namespace {
// Used to log if any audio glitches have been detected during an audio session.
// Elements in this enum should not be added, deleted or rearranged.
-enum AudioGlitchResult {
- AUDIO_CAPTURER_NO_AUDIO_GLITCHES = 0,
- AUDIO_CAPTURER_AUDIO_GLITCHES = 1,
- AUDIO_CAPTURER_AUDIO_GLITCHES_MAX = AUDIO_CAPTURER_AUDIO_GLITCHES
+enum class AudioGlitchResult {
+ kNoGlitches = 0,
+ kGlitches = 1,
+ kMaxValue = kGlitches
};
} // namespace
@@ -111,17 +111,43 @@ InputSyncWriter::~InputSyncWriter() {
if (write_count_ == 0)
return;
- UMA_HISTOGRAM_PERCENTAGE("Media.AudioCapturerMissedReadDeadline",
- 100.0 * write_to_fifo_count_ / write_count_);
+ base::UmaHistogramPercentage("Media.AudioCapturerMissedReadDeadline",
+ 100.0 * write_to_fifo_count_ / write_count_);
- UMA_HISTOGRAM_PERCENTAGE("Media.AudioCapturerDroppedData",
- 100.0 * write_error_count_ / write_count_);
+ base::UmaHistogramPercentage("Media.AudioCapturerDroppedData",
+ 100.0 * write_error_count_ / write_count_);
- UMA_HISTOGRAM_ENUMERATION("Media.AudioCapturerAudioGlitches",
- write_error_count_ == 0
- ? AUDIO_CAPTURER_NO_AUDIO_GLITCHES
- : AUDIO_CAPTURER_AUDIO_GLITCHES,
- AUDIO_CAPTURER_AUDIO_GLITCHES_MAX + 1);
+ base::UmaHistogramEnumeration("Media.AudioCapturerAudioGlitches",
+ write_error_count_ == 0
+ ? AudioGlitchResult::kNoGlitches
+ : AudioGlitchResult::kGlitches);
+
+ const int kPermilleScaling = 1000;
+ // 10%: if we have more that 10% of callbacks having issues, the details are
+ // not very interesting any more, so we just log all those cases together to
+ // have a better resolution for lower values.
+ const int kHistogramRange = kPermilleScaling / 10;
+
+ // 30 s for 10 ms buffers.
+ const int kShortStreamMaxCallbackCount = 3000;
+ const std::string suffix =
+ write_count_ < kShortStreamMaxCallbackCount ? "Short" : "Long";
+
+ int missed_deadline =
+ std::ceil(kPermilleScaling * static_cast<double>(write_to_fifo_count_) /
+ write_count_);
+
+ base::UmaHistogramCustomCounts(
+ "Media.AudioCapturerMissedReadDeadline2." + suffix,
+ std::min(missed_deadline, kHistogramRange), 0, kHistogramRange + 1, 100);
+
+ int dropped_data =
+ std::ceil(kPermilleScaling * static_cast<double>(write_error_count_) /
+ write_count_);
+
+ base::UmaHistogramCustomCounts("Media.AudioCapturerDroppedData2." + suffix,
+ std::min(dropped_data, kHistogramRange), 0,
+ kHistogramRange + 1, 100);
std::string log_string = base::StringPrintf(
"AISW: number of detected audio glitches: %" PRIuS " out of %" PRIuS,
diff --git a/chromium/services/audio/input_sync_writer.h b/chromium/services/audio/input_sync_writer.h
index b5e88e0882a..bf7ece2a28f 100644
--- a/chromium/services/audio/input_sync_writer.h
+++ b/chromium/services/audio/input_sync_writer.h
@@ -13,7 +13,6 @@
#include <vector>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/sync_socket.h"
#include "base/time/time.h"
@@ -38,6 +37,8 @@ class InputSyncWriter final : public InputController::SyncWriter {
// media::AudioBuses.
enum { kMaxOverflowBusesSize = 100 };
+ InputSyncWriter() = delete;
+
// Create() automatically initializes the InputSyncWriter correctly,
// and should be strongly preferred over calling the constructor directly!
InputSyncWriter(
@@ -47,6 +48,9 @@ class InputSyncWriter final : public InputController::SyncWriter {
uint32_t shared_memory_segment_count,
const media::AudioParameters& params);
+ InputSyncWriter(const InputSyncWriter&) = delete;
+ InputSyncWriter& operator=(const InputSyncWriter&) = delete;
+
~InputSyncWriter() final;
static std::unique_ptr<InputSyncWriter> Create(
@@ -170,21 +174,22 @@ class InputSyncWriter final : public InputController::SyncWriter {
bool key_pressed,
base::TimeTicks capture_time,
std::unique_ptr<media::AudioBus> audio_bus);
- ~OverflowData();
+
+ OverflowData(const OverflowData&) = delete;
+ OverflowData& operator=(const OverflowData&) = delete;
+
OverflowData(OverflowData&&);
OverflowData& operator=(OverflowData&& other);
+
+ ~OverflowData();
+
double volume_;
bool key_pressed_;
base::TimeTicks capture_time_;
std::unique_ptr<media::AudioBus> audio_bus_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(OverflowData);
};
std::vector<OverflowData> overflow_data_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(InputSyncWriter);
};
} // namespace audio
diff --git a/chromium/services/audio/input_sync_writer_unittest.cc b/chromium/services/audio/input_sync_writer_unittest.cc
index d4cb081ffe0..22a6ac5167a 100644
--- a/chromium/services/audio/input_sync_writer_unittest.cc
+++ b/chromium/services/audio/input_sync_writer_unittest.cc
@@ -12,8 +12,8 @@
#include <utility>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/sync_socket.h"
#include "base/test/mock_callback.h"
@@ -49,6 +49,9 @@ class MockCancelableSyncSocket : public base::CancelableSyncSocket {
buffer_size_(buffer_size),
read_buffer_index_(0) {}
+ MockCancelableSyncSocket(const MockCancelableSyncSocket&) = delete;
+ MockCancelableSyncSocket& operator=(const MockCancelableSyncSocket&) = delete;
+
size_t Send(const void* buffer, size_t length) override {
EXPECT_EQ(length, sizeof(uint32_t));
@@ -98,8 +101,6 @@ class MockCancelableSyncSocket : public base::CancelableSyncSocket {
int receives_;
int buffer_size_;
uint32_t read_buffer_index_;
-
- DISALLOW_COPY_AND_ASSIGN(MockCancelableSyncSocket);
};
class InputSyncWriterTest : public testing::Test {
@@ -161,7 +162,7 @@ class InputSyncWriterTest : public testing::Test {
base::test::TaskEnvironment env_;
MockLogger mock_logger_;
std::unique_ptr<InputSyncWriter> writer_;
- MockCancelableSyncSocket* socket_;
+ raw_ptr<MockCancelableSyncSocket> socket_;
std::unique_ptr<media::AudioBus> audio_bus_;
};
diff --git a/chromium/services/audio/local_muter.h b/chromium/services/audio/local_muter.h
index d7d67098fbd..b70c04b4d34 100644
--- a/chromium/services/audio/local_muter.h
+++ b/chromium/services/audio/local_muter.h
@@ -6,7 +6,7 @@
#define SERVICES_AUDIO_LOCAL_MUTER_H_
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/unguessable_token.h"
#include "media/mojo/mojom/audio_stream_factory.mojom.h"
@@ -48,7 +48,7 @@ class LocalMuter final : public media::mojom::LocalMuter,
// Runs the |all_bindings_lost_callback_| when |bindings_| becomes empty.
void OnBindingLost();
- LoopbackCoordinator* const coordinator_;
+ const raw_ptr<LoopbackCoordinator> coordinator_;
const base::UnguessableToken group_id_;
mojo::AssociatedReceiverSet<media::mojom::LocalMuter> receivers_;
diff --git a/chromium/services/audio/log_factory_manager_unittest.cc b/chromium/services/audio/log_factory_manager_unittest.cc
index 57db26002ba..77107cc8a7d 100644
--- a/chromium/services/audio/log_factory_manager_unittest.cc
+++ b/chromium/services/audio/log_factory_manager_unittest.cc
@@ -52,6 +52,9 @@ class MockAudioLogFactory : public media::mojom::AudioLogFactory {
mock_logs_.push_back(new MockAudioLog());
}
+ MockAudioLogFactory(const MockAudioLogFactory&) = delete;
+ MockAudioLogFactory& operator=(const MockAudioLogFactory&) = delete;
+
MOCK_METHOD2(MockCreateAudioLog,
void(media::mojom::AudioLogComponent, int32_t));
@@ -71,7 +74,6 @@ class MockAudioLogFactory : public media::mojom::AudioLogFactory {
mojo::Receiver<media::mojom::AudioLogFactory> receiver_;
size_t current_mock_log_ = 0;
std::vector<MockAudioLog*> mock_logs_;
- DISALLOW_COPY_AND_ASSIGN(MockAudioLogFactory);
};
} // namespace
@@ -80,6 +82,9 @@ class LogFactoryManagerTest : public ::testing::Test {
public:
LogFactoryManagerTest() = default;
+ LogFactoryManagerTest(const LogFactoryManagerTest&) = delete;
+ LogFactoryManagerTest& operator=(const LogFactoryManagerTest&) = delete;
+
protected:
void CreateLogFactoryManager() {
log_factory_manager_ = std::make_unique<LogFactoryManager>();
@@ -95,10 +100,6 @@ class LogFactoryManagerTest : public ::testing::Test {
base::test::TaskEnvironment task_environment_;
mojo::Remote<mojom::LogFactoryManager> remote_log_factory_manager_;
std::unique_ptr<LogFactoryManager> log_factory_manager_;
-
- private:
-
- DISALLOW_COPY_AND_ASSIGN(LogFactoryManagerTest);
};
TEST_F(LogFactoryManagerTest, LogFactoryManagerQueuesRequestsAndSetsFactory) {
diff --git a/chromium/services/audio/loopback_stream.h b/chromium/services/audio/loopback_stream.h
index f48ba7bdd1a..dcbacb96391 100644
--- a/chromium/services/audio/loopback_stream.h
+++ b/chromium/services/audio/loopback_stream.h
@@ -11,12 +11,12 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
@@ -116,6 +116,9 @@ class LoopbackStream final : public media::mojom::AudioInputStream,
const media::AudioParameters& output_params,
std::unique_ptr<InputSyncWriter> writer);
+ FlowNetwork(const FlowNetwork&) = delete;
+ FlowNetwork& operator=(const FlowNetwork&) = delete;
+
// These must be called to override the Clock/SyncWriter before Start().
void set_clock_for_testing(const base::TickClock* clock) { clock_ = clock; }
void set_writer_for_testing(
@@ -159,7 +162,7 @@ class LoopbackStream final : public media::mojom::AudioInputStream,
// becomes stopped.
void GenerateMoreAudio();
- const base::TickClock* clock_;
+ raw_ptr<const base::TickClock> clock_;
// Task runner that calls GenerateMoreAudio() to drive all the audio data
// flows.
@@ -210,8 +213,6 @@ class LoopbackStream final : public media::mojom::AudioInputStream,
const std::unique_ptr<media::AudioBus> mix_bus_;
SEQUENCE_CHECKER(control_sequence_);
-
- DISALLOW_COPY_AND_ASSIGN(FlowNetwork);
};
// Reports a fatal error to the client, and then runs the BindingLostCallback.
@@ -228,7 +229,7 @@ class LoopbackStream final : public media::mojom::AudioInputStream,
mojo::Remote<media::mojom::AudioInputStreamObserver> observer_;
// Used for identifying group members and snooping on their audio data flow.
- LoopbackCoordinator* const coordinator_;
+ const raw_ptr<LoopbackCoordinator> coordinator_;
const base::UnguessableToken group_id_;
// The snoopers associated with each group member. This is not a flat_map
diff --git a/chromium/services/audio/loopback_stream_unittest.cc b/chromium/services/audio/loopback_stream_unittest.cc
index bc22603844a..ae50ef54e14 100644
--- a/chromium/services/audio/loopback_stream_unittest.cc
+++ b/chromium/services/audio/loopback_stream_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/task_environment.h"
#include "base/unguessable_token.h"
@@ -257,7 +258,7 @@ class LoopbackStreamTest : public testing::Test {
std::vector<std::unique_ptr<FakeLoopbackGroupMember>> sources_;
NiceMock<MockClientAndObserver> client_;
std::unique_ptr<LoopbackStream> stream_;
- FakeSyncWriter* consumer_ = nullptr; // Owned by |stream_|.
+ raw_ptr<FakeSyncWriter> consumer_ = nullptr; // Owned by |stream_|.
mojo::Remote<media::mojom::AudioInputStream> remote_input_stream_;
};
diff --git a/chromium/services/audio/mixing_graph.cc b/chromium/services/audio/mixing_graph.cc
new file mode 100644
index 00000000000..32c77a64547
--- /dev/null
+++ b/chromium/services/audio/mixing_graph.cc
@@ -0,0 +1,18 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/mixing_graph.h"
+#include "services/audio/mixing_graph_impl.h"
+
+namespace audio {
+
+// static
+std::unique_ptr<MixingGraph> MixingGraph::Create(
+ const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb) {
+ return std::make_unique<MixingGraphImpl>(
+ output_params, std::move(on_more_data_cb), std::move(on_error_cb));
+}
+} // namespace audio
diff --git a/chromium/services/audio/mixing_graph.h b/chromium/services/audio/mixing_graph.h
new file mode 100644
index 00000000000..5d3aa2511e6
--- /dev/null
+++ b/chromium/services/audio/mixing_graph.h
@@ -0,0 +1,94 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_MIXING_GRAPH_H_
+#define SERVICES_AUDIO_MIXING_GRAPH_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "media/audio/audio_io.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_converter.h"
+#include "media/base/audio_parameters.h"
+
+namespace audio {
+
+// The graph is mixing audio provided by multiple audio sources
+// (AudioOutputStream::AudioSourceCallback instances) and represents the mix as
+// a single AudioOutputStream::AudioSourceCallback, which in turn serves as an
+// audio source providing audio buffers to AudioOutputStream for playback.
+class MixingGraph : public media::AudioOutputStream::AudioSourceCallback {
+ public:
+ using InputCallback = media::AudioConverter::InputCallback;
+
+ using OnMoreDataCallback =
+ base::RepeatingCallback<void(const media::AudioBus&, base::TimeDelta)>;
+
+ using OnErrorCallback = base::RepeatingCallback<void(
+ media::AudioOutputStream::AudioSourceCallback::ErrorType)>;
+
+ // A helper class for the clients to pass MixingGraph::Create() around as a
+ // callback.
+ using CreateCallback = base::OnceCallback<std::unique_ptr<MixingGraph>(
+ const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb)>;
+
+ // Represents an audio source as an input to MixingGraph.
+ // An adapter from AudioOutputStream::AudioSourceCallback to
+ // AudioConverter::InputCallback.
+ class Input : public InputCallback {
+ public:
+ Input() = default;
+ ~Input() override = default;
+ Input(const Input&) = delete;
+ Input& operator=(const Input&) = delete;
+
+ // Returns the audio source parameters.
+ virtual const media::AudioParameters& GetParams() const = 0;
+
+ // Sets the volume.
+ virtual void SetVolume(double volume) = 0;
+
+ // Starts providing audio from |source_callback| to the graph which created
+ // the given Input.
+ virtual void Start(
+ media::AudioOutputStream::AudioSourceCallback* source_callback) = 0;
+
+ // Stops providing audio to the graph which created the given Input.
+ virtual void Stop() = 0;
+ };
+
+ // Creates a graph which will provide the audio mix formatted as
+ // |output_params| each time its
+ // AudioOutputStream::AudioSourceCallback::OnMoreData() method is called, and
+ // will also provide the audio mix to |on_more_data_cb| callback.
+ // |on_error_cb| will be used to notify the client about audio rendering
+ // errors.
+ static std::unique_ptr<MixingGraph> Create(
+ const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb);
+
+ MixingGraph() = default;
+ MixingGraph(const MixingGraph&) = delete;
+ MixingGraph& operator=(const MixingGraph&) = delete;
+
+ // Creates a graph input with given audio source parameters.
+ virtual std::unique_ptr<Input> CreateInput(
+ const media::AudioParameters& params) = 0;
+
+ protected:
+ friend class SyncMixingGraphInput;
+
+ // Adds an input to the graph. To be called by Input::Start().
+ virtual void AddInput(Input* node) = 0;
+ // Removes an input from the graph. To be called by Input::Stop().
+ virtual void RemoveInput(Input* node) = 0;
+};
+
+} // namespace audio
+#endif // SERVICES_AUDIO_MIXING_GRAPH_H_
diff --git a/chromium/services/audio/mixing_graph_impl.cc b/chromium/services/audio/mixing_graph_impl.cc
new file mode 100644
index 00000000000..50efc86c409
--- /dev/null
+++ b/chromium/services/audio/mixing_graph_impl.cc
@@ -0,0 +1,215 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/mixing_graph_impl.h"
+
+#include "base/compiler_specific.h"
+#include "base/trace_event/trace_event.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/base/loopback_audio_converter.h"
+#include "services/audio/sync_mixing_graph_input.h"
+
+namespace audio {
+namespace {
+std::unique_ptr<media::LoopbackAudioConverter> CreateConverter(
+ const media::AudioParameters& input_params,
+ const media::AudioParameters& output_params) {
+ return std::make_unique<media::LoopbackAudioConverter>(
+ input_params, output_params, /*disable_fifo=*/true);
+}
+
+// Clamps all samples to the interval [-1, 1].
+void SanitizeOutput(media::AudioBus* bus) {
+ for (int channel = 0; channel < bus->channels(); ++channel) {
+ float* data = bus->channel(channel);
+ for (int frame = 0; frame < bus->frames(); frame++) {
+ float value = data[frame];
+ if (LIKELY(value * value <= 1.0f)) {
+ continue;
+ }
+ // The sample is out of range. Negative values are clamped to -1. Positive
+ // values and NaN are clamped to 1.
+ data[frame] = value < 0.0f ? -1.0f : 1.0f;
+ }
+ }
+}
+} // namespace
+
+MixingGraphImpl::MixingGraphImpl(const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb)
+ : MixingGraphImpl(output_params,
+ on_more_data_cb,
+ on_error_cb,
+ base::BindRepeating(&CreateConverter)) {}
+
+MixingGraphImpl::MixingGraphImpl(const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb,
+ CreateConverterCallback create_converter_cb)
+ : output_params_(output_params),
+ on_more_data_cb_(std::move(on_more_data_cb)),
+ on_error_cb_(std::move(on_error_cb)),
+ create_converter_cb_(std::move(create_converter_cb)),
+ main_converter_(output_params, output_params, /*disable_fifo=*/true) {}
+
+MixingGraphImpl::~MixingGraphImpl() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(main_converter_.empty());
+ DCHECK(converters_.empty());
+}
+
+std::unique_ptr<MixingGraph::Input> MixingGraphImpl::CreateInput(
+ const media::AudioParameters& params) {
+ return std::make_unique<SyncMixingGraphInput>(this, params);
+}
+
+media::LoopbackAudioConverter* MixingGraphImpl::FindOrAddConverter(
+ const media::AudioParameters& input_params,
+ const media::AudioParameters& output_params,
+ media::LoopbackAudioConverter* parent_converter) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ AudioConverterKey key(input_params.sample_rate(),
+ input_params.channel_layout());
+ auto converter = converters_.find(key);
+ if (converter == converters_.end()) {
+ // No existing suitable converter. Add a new converter to the graph.
+ std::pair<AudioConverters::iterator, bool> result =
+ converters_.insert(std::make_pair(
+ key, create_converter_cb_.Run(input_params, output_params)));
+ converter = result.first;
+
+ // Add the new converter as an input to its parent converter.
+ base::AutoLock scoped_lock(lock_);
+ if (parent_converter) {
+ parent_converter->AddInput(converter->second.get());
+ } else {
+ main_converter_.AddInput(converter->second.get());
+ }
+ }
+
+ return converter->second.get();
+}
+
+void MixingGraphImpl::AddInput(Input* input) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ const auto& input_params = input->GetParams();
+ DCHECK(input_params.format() ==
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY);
+
+ // Resampler input format is the same as output except sample rate.
+ media::AudioParameters resampler_input_params(
+ output_params_.format(), output_params_.channel_layout(),
+ input_params.sample_rate(), output_params_.frames_per_buffer());
+
+ // Channel mixer input format is the same as resampler input except channel
+ // layout.
+ media::AudioParameters channel_mixer_input_params(
+ resampler_input_params.format(), input_params.channel_layout(),
+ resampler_input_params.sample_rate(),
+ resampler_input_params.frames_per_buffer());
+
+ media::LoopbackAudioConverter* converter = nullptr;
+
+ // Check if resampling is needed.
+ if (resampler_input_params.sample_rate() != output_params_.sample_rate()) {
+ // Re-use or create a resampler.
+ converter =
+ FindOrAddConverter(resampler_input_params, output_params_, converter);
+ }
+
+ // Check if channel mixing is needed.
+ if (channel_mixer_input_params.channel_layout() !=
+ resampler_input_params.channel_layout()) {
+ // Re-use or create a channel mixer.
+ converter = FindOrAddConverter(channel_mixer_input_params,
+ resampler_input_params, converter);
+ }
+
+ // Add the input to the mixing graph.
+ base::AutoLock scoped_lock(lock_);
+ if (converter) {
+ converter->AddInput(input);
+ } else {
+ main_converter_.AddInput(input);
+ }
+}
+
+void MixingGraphImpl::Remove(const AudioConverterKey& key,
+ media::AudioConverter::InputCallback* input) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (key == AudioConverterKey(output_params_)) {
+ base::AutoLock scoped_lock(lock_);
+ main_converter_.RemoveInput(input);
+ return;
+ }
+
+ auto converter = converters_.find(key);
+ DCHECK(converter != converters_.end());
+ media::LoopbackAudioConverter* parent = converter->second.get();
+ {
+ base::AutoLock scoped_lock(lock_);
+ parent->RemoveInput(input);
+ }
+
+ // Remove parent converter if empty.
+ if (parent->empty()) {
+ // With knowledge of the tree structure (resampling closer to the
+ // main converter than channel mixing) the key of the grandparent converter
+ // can be deduced. This key is used to find the grandparent and remove the
+ // reference to the empty parent converter.
+ AudioConverterKey next_key(key);
+ if (key.channel_layout != output_params_.channel_layout()) {
+ next_key.channel_layout = output_params_.channel_layout();
+ } else {
+ // If the parent converter is not the main converter its key (and input
+ // parameters) should differ from the output parameters in sample rate,
+ // channel layout or both.
+ DCHECK_NE(key.sample_rate, output_params_.sample_rate());
+ next_key.sample_rate = output_params_.sample_rate();
+ }
+ Remove(next_key, parent);
+ converters_.erase(converter);
+ }
+}
+
+void MixingGraphImpl::RemoveInput(Input* input) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ Remove(AudioConverterKey(input->GetParams()), input);
+}
+
+int MixingGraphImpl::OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) {
+ TRACE_EVENT_BEGIN2(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "MixingGraphImpl::OnMoreData", "delay", delay,
+ "delay_timestamp", delay_timestamp);
+
+ base::TimeDelta total_delay =
+ base::TimeTicks::Now() - delay_timestamp + delay;
+ if (total_delay < base::TimeDelta())
+ total_delay = base::TimeDelta();
+
+ uint32_t frames_delayed = media::AudioTimestampHelper::TimeToFrames(
+ total_delay, output_params_.sample_rate());
+ {
+ base::AutoLock scoped_lock(lock_);
+ main_converter_.ConvertWithDelay(frames_delayed, dest);
+ }
+
+ SanitizeOutput(dest);
+
+ on_more_data_cb_.Run(*dest, total_delay);
+
+ TRACE_EVENT_END2(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "MixingGraphImpl::OnMoreData", "total_delay", total_delay,
+ "frames_delayed", frames_delayed);
+ return dest->frames();
+}
+
+void MixingGraphImpl::OnError(ErrorType error) {
+ on_error_cb_.Run(error);
+}
+} // namespace audio
diff --git a/chromium/services/audio/mixing_graph_impl.h b/chromium/services/audio/mixing_graph_impl.h
new file mode 100644
index 00000000000..fadfcb90683
--- /dev/null
+++ b/chromium/services/audio/mixing_graph_impl.h
@@ -0,0 +1,115 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_MIXING_GRAPH_IMPL_H_
+#define SERVICES_AUDIO_MIXING_GRAPH_IMPL_H_
+
+#include "services/audio/mixing_graph.h"
+
+#include <map>
+
+#include "base/synchronization/lock.h"
+
+namespace media {
+class LoopbackAudioConverter;
+}
+
+namespace audio {
+
+class MixingGraphImpl : public MixingGraph {
+ public:
+ using CreateConverterCallback =
+ base::RepeatingCallback<std::unique_ptr<media::LoopbackAudioConverter>(
+ const media::AudioParameters& input_params,
+ const media::AudioParameters& output_params)>;
+ MixingGraphImpl(const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb);
+ MixingGraphImpl(const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb,
+ CreateConverterCallback create_converter_cb);
+ ~MixingGraphImpl() override;
+
+ std::unique_ptr<Input> CreateInput(
+ const media::AudioParameters& params) final;
+ void AddInput(Input* node) final;
+ void RemoveInput(Input* node) final;
+
+ // media::AudioOutputStream::AudioSourceCallback
+ int OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) final;
+
+ void OnError(ErrorType type) final;
+
+ protected:
+ media::LoopbackAudioConverter* FindOrAddConverter(
+ const media::AudioParameters& input_params,
+ const media::AudioParameters& output_params,
+ media::LoopbackAudioConverter* parent_converter);
+
+ struct AudioConverterKey {
+ explicit AudioConverterKey(const media::AudioParameters& params)
+ : sample_rate(params.sample_rate()),
+ channel_layout(params.channel_layout()) {}
+
+ AudioConverterKey(int sample_rate, media::ChannelLayout channel_layout)
+ : sample_rate(sample_rate), channel_layout(channel_layout) {}
+
+ inline bool operator==(const AudioConverterKey& other) const {
+ return sample_rate == other.sample_rate &&
+ channel_layout == other.channel_layout;
+ }
+
+ inline bool operator<(const AudioConverterKey& other) const {
+ if (sample_rate != other.sample_rate)
+ return sample_rate < other.sample_rate;
+ return channel_layout < other.channel_layout;
+ }
+ int sample_rate;
+ media::ChannelLayout channel_layout;
+ };
+
+ void Remove(const AudioConverterKey& key,
+ media::AudioConverter::InputCallback* input);
+
+ using AudioConverters =
+ std::map<AudioConverterKey,
+ std::unique_ptr<media::LoopbackAudioConverter>>;
+
+ SEQUENCE_CHECKER(owning_sequence_);
+
+ // The audio format of the mixed audio leaving the mixing graph.
+ const media::AudioParameters output_params_;
+ // Called from OnMoreData() with mixed audio as input.
+ const OnMoreDataCallback on_more_data_cb_;
+ // Notifies the client about audio rendering errors.
+ const OnErrorCallback on_error_cb_;
+ // Called when a new converter needs to be created.
+ const CreateConverterCallback create_converter_cb_;
+
+ base::Lock lock_;
+
+ // The |main_converter_|, the |converters_| and the inputs are connected
+ // to form a graph (tree structure) that determines how the input audio is
+ // channel mixed, resampled, and added to the final output. Channel mixing
+ // and resampling are handled by converters. The tree is constructed to
+ // minimize the use of resampling, which is the most complex operation.
+ // 1. For inputs with a channel layout different from the output channel
+ // layout: All inputs of the same sample rate and channel layout are combined
+ // and channel mixed to produce new inputs with the output channel layout.
+ // 2. For inputs with a sample rate different from the output sample rate: All
+ // inputs of the same sample rate (and after channel mixing the same channel
+ // layout) are combined and resampled to produce new inputs of the
+ // output sample rate (and channel layout).
+ // 3. All inputs of the output sample rate and channel layout are combined by
+ // the main converter to produce a single output.
+ AudioConverters converters_;
+ media::AudioConverter main_converter_;
+};
+
+} // namespace audio
+#endif // SERVICES_AUDIO_MIXING_GRAPH_IMPL_H_
diff --git a/chromium/services/audio/mixing_graph_impl_unittest.cc b/chromium/services/audio/mixing_graph_impl_unittest.cc
new file mode 100644
index 00000000000..fc10e962bf7
--- /dev/null
+++ b/chromium/services/audio/mixing_graph_impl_unittest.cc
@@ -0,0 +1,396 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/mixing_graph_impl.h"
+#include "media/base/loopback_audio_converter.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace audio {
+// Wrapper for MixingGraphImpl that exposes converters_ and main_converter_ for
+// testing.
+class MixingGraphImplUnderTest : public MixingGraphImpl {
+ public:
+ MixingGraphImplUnderTest(const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb,
+ CreateConverterCallback create_converter_cb)
+ : MixingGraphImpl(output_params,
+ on_more_data_cb,
+ on_error_cb,
+ create_converter_cb) {}
+ MixingGraphImplUnderTest(const media::AudioParameters& output_params,
+ OnMoreDataCallback on_more_data_cb,
+ OnErrorCallback on_error_cb)
+ : MixingGraphImpl(output_params, on_more_data_cb, on_error_cb) {}
+ const auto& converters() { return converters_; }
+ const auto& main_converter() { return main_converter_; }
+};
+
+class MockInput : public MixingGraph::Input {
+ public:
+ explicit MockInput(media::AudioParameters params) : params(params) {}
+
+ const media::AudioParameters& GetParams() const override { return params; }
+ MOCK_METHOD(void, SetVolume, (double));
+ MOCK_METHOD(void, Start, (media::AudioOutputStream::AudioSourceCallback*));
+ MOCK_METHOD(void, Stop, ());
+ MOCK_METHOD(double, ProvideInput, (media::AudioBus*, uint32_t));
+
+ media::AudioParameters params;
+};
+
+class MockConverterFactory {
+ public:
+ std::unique_ptr<media::LoopbackAudioConverter> CreateConverter(
+ const media::AudioParameters& input_params,
+ const media::AudioParameters& output_params) {
+ VerifyInput(input_params.sample_rate(), input_params.channel_layout());
+ VerifyOutput(output_params.sample_rate(), output_params.channel_layout());
+ return std::make_unique<media::LoopbackAudioConverter>(input_params,
+ output_params, true);
+ }
+ MOCK_METHOD(void, VerifyInput, (int, media::ChannelLayout));
+ MOCK_METHOD(void, VerifyOutput, (int, media::ChannelLayout));
+};
+
+TEST(MixingGraphImpl, AddInputToMainConverter) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ MixingGraph::OnMoreDataCallback on_more_data_cb;
+ MixingGraph::OnErrorCallback on_error_cb;
+ MixingGraphImplUnderTest mixing_graph(output_params, on_more_data_cb,
+ on_error_cb);
+ const auto& converters = mixing_graph.converters();
+ const auto& main_converter = mixing_graph.main_converter();
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+
+ // Create a new input with the same audio parameters as the output.
+ MockInput input(output_params);
+ mixing_graph.AddInput(&input);
+
+ // The input should be connected to the main_converter_.
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ mixing_graph.RemoveInput(&input);
+
+ // Expect main_converter to be empty again.
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+}
+
+TEST(MixingGraphImpl, AddMultipleInputsToMainConverter) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ MixingGraph::OnMoreDataCallback on_more_data_cb;
+ MixingGraph::OnErrorCallback on_error_cb;
+ MixingGraphImplUnderTest mixing_graph(output_params, on_more_data_cb,
+ on_error_cb);
+ const auto& converters = mixing_graph.converters();
+ const auto& main_converter = mixing_graph.main_converter();
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+
+ // Create some new inputs with the same audio parameters as the output.
+ MockInput input1(output_params);
+ MockInput input2(output_params);
+ MockInput input3(output_params);
+ mixing_graph.AddInput(&input1);
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_FALSE(main_converter.empty());
+ mixing_graph.AddInput(&input2);
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_FALSE(main_converter.empty());
+ mixing_graph.AddInput(&input3);
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ mixing_graph.RemoveInput(&input1);
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_FALSE(main_converter.empty());
+ mixing_graph.RemoveInput(&input2);
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_FALSE(main_converter.empty());
+ mixing_graph.RemoveInput(&input3);
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+}
+
+TEST(MixingGraphImpl, AddInputWithChannelMixer) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 48000, 480);
+ MixingGraph::OnMoreDataCallback on_more_data_cb;
+ MixingGraph::OnErrorCallback on_error_cb;
+ MixingGraphImplUnderTest mixing_graph(output_params, on_more_data_cb,
+ on_error_cb);
+ const auto& converters = mixing_graph.converters();
+ const auto& main_converter = mixing_graph.main_converter();
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+
+ // Create a new input which differs from the output in number of channels.
+ MockInput input(input_params);
+ mixing_graph.AddInput(&input);
+
+ // A channel mixer converter should be added to converters_ and connected to
+ // the main_converter_.
+ EXPECT_EQ(converters.size(), 1UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ mixing_graph.RemoveInput(&input);
+
+ // Expect the channel mixer to have been removed from converters_ and the
+ // main_converter to be empty again.
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+}
+
+TEST(MixingGraphImpl, AddInputWithResampler) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 16000, 160);
+ MixingGraph::OnMoreDataCallback on_more_data_cb;
+ MixingGraph::OnErrorCallback on_error_cb;
+ MixingGraphImplUnderTest mixing_graph(output_params, on_more_data_cb,
+ on_error_cb);
+ const auto& converters = mixing_graph.converters();
+ const auto& main_converter = mixing_graph.main_converter();
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+
+ // Create a new input which differs from the output in sample rate.
+ MockInput input(input_params);
+ mixing_graph.AddInput(&input);
+
+ // A resampler converter should be added to converters_ and connected to
+ // the main_converter_.
+ EXPECT_EQ(converters.size(), 1UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ mixing_graph.RemoveInput(&input);
+
+ // Expect the resampler to have been removed from converters_ and the
+ // main_converter to be empty again.
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+}
+
+TEST(MixingGraphImpl, BuildComplexGraph) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ MixingGraph::OnMoreDataCallback on_more_data_cb;
+ MixingGraph::OnErrorCallback on_error_cb;
+ MixingGraphImplUnderTest mixing_graph(output_params, on_more_data_cb,
+ on_error_cb);
+ const auto& converters = mixing_graph.converters();
+ const auto& main_converter = mixing_graph.main_converter();
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+
+ // Create a new input which differs from the output in sample rate.
+ media::AudioParameters input_params_resamp(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 16000, 160);
+ MockInput input1(input_params_resamp);
+ mixing_graph.AddInput(&input1);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ EXPECT_EQ(converters.size(), 1UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Adding a new input with the same configuration should not change the
+ // number of converters.
+ MockInput input2(input_params_resamp);
+ mixing_graph.AddInput(&input2);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ EXPECT_EQ(converters.size(), 1UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Create a new input which differs from the output in channel layout.
+ media::AudioParameters input_params_downmix(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 48000, 480);
+ MockInput input3(input_params_downmix);
+ mixing_graph.AddInput(&input3);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input3
+ EXPECT_EQ(converters.size(), 2UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Create a new input which needs resampling (re-used) and channel mixing
+ // (new).
+ media::AudioParameters input_params_resamp_downmix(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 16000, 160);
+ MockInput input4(input_params_resamp_downmix);
+ mixing_graph.AddInput(&input4);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input4
+ // <--- converter (ch. mixer) <--- input3
+ EXPECT_EQ(converters.size(), 3UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Adding a new input with the same configuration should not change the
+ // number of converters.
+ MockInput input5(input_params_resamp_downmix);
+ mixing_graph.AddInput(&input5);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input4
+ // <--- input5
+ // <--- converter (ch. mixer) <--- input3
+ EXPECT_EQ(converters.size(), 3UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Adding a couple of inputs connected directly to the main_converter_
+ // should not change the number of converters.
+ MockInput input6(output_params);
+ MockInput input7(output_params);
+ mixing_graph.AddInput(&input6);
+ mixing_graph.AddInput(&input7);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input4
+ // <--- input5
+ // <--- converter (ch. mixer) <--- input3
+ // <--- input6
+ // <--- input7
+ EXPECT_EQ(converters.size(), 3UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Removing input{1,2,4,6,7} will not allow any converters to be removed.
+ mixing_graph.RemoveInput(&input1);
+ mixing_graph.RemoveInput(&input2);
+ mixing_graph.RemoveInput(&input4);
+ mixing_graph.RemoveInput(&input6);
+ mixing_graph.RemoveInput(&input7);
+ // Graph:
+ // main <--- converter (resampler) <--- converter (ch. mixer) <--- input5
+ // <--- converter (ch. mixer) <--- input3
+ EXPECT_EQ(converters.size(), 3UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Removing input5 should cause removal of the resampler and a channel
+ // mixer.
+ mixing_graph.RemoveInput(&input5);
+ // Graph:
+ // main <--- converter (ch. mixer) <--- input3
+ EXPECT_EQ(converters.size(), 1UL);
+ EXPECT_FALSE(main_converter.empty());
+
+ // Removing the last input should result in no converters left and an empty
+ // main_converter_.
+ mixing_graph.RemoveInput(&input3);
+ // Graph:
+ // main
+ EXPECT_EQ(converters.size(), 0UL);
+ EXPECT_TRUE(main_converter.empty());
+}
+
+// Builds the same graph as above, but verifies the converter parameters.
+TEST(MixingGraphImpl, VerifyConverters) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ MockConverterFactory mock_converter_factory;
+ MixingGraph::OnMoreDataCallback on_more_data_cb;
+ MixingGraph::OnErrorCallback on_error_cb;
+ MixingGraphImpl::CreateConverterCallback create_converter_cb =
+ base::BindRepeating(&MockConverterFactory::CreateConverter,
+ base::Unretained(&mock_converter_factory));
+ MixingGraphImpl mixing_graph(output_params, on_more_data_cb, on_error_cb,
+ create_converter_cb);
+
+ // Create a new input which differs from the output in sample rate.
+ media::AudioParameters input_params_resamp(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 16000, 160);
+ MockInput input1(input_params_resamp);
+ EXPECT_CALL(mock_converter_factory,
+ VerifyInput(16000, media::ChannelLayout::CHANNEL_LAYOUT_MONO));
+ EXPECT_CALL(mock_converter_factory,
+ VerifyOutput(48000, media::ChannelLayout::CHANNEL_LAYOUT_MONO));
+ mixing_graph.AddInput(&input1);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+
+ // Adding a new input with the same configuration should not change the
+ // number of converters.
+ MockInput input2(input_params_resamp);
+ mixing_graph.AddInput(&input2);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+
+ // Create a new input which differs from the output in channel layout.
+ media::AudioParameters input_params_downmix(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 48000, 480);
+ MockInput input3(input_params_downmix);
+ EXPECT_CALL(mock_converter_factory,
+ VerifyInput(48000, media::ChannelLayout::CHANNEL_LAYOUT_STEREO));
+ EXPECT_CALL(mock_converter_factory,
+ VerifyOutput(48000, media::ChannelLayout::CHANNEL_LAYOUT_MONO));
+ mixing_graph.AddInput(&input3);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input3
+
+ // Create a new input which needs resampling (re-used) and channel mixing
+ // (new).
+ media::AudioParameters input_params_resamp_downmix(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 16000, 160);
+ MockInput input4(input_params_resamp_downmix);
+ EXPECT_CALL(mock_converter_factory,
+ VerifyInput(16000, media::ChannelLayout::CHANNEL_LAYOUT_STEREO));
+ EXPECT_CALL(mock_converter_factory,
+ VerifyOutput(16000, media::ChannelLayout::CHANNEL_LAYOUT_MONO));
+ mixing_graph.AddInput(&input4);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input4
+ // <--- converter (ch. mixer) <--- input3
+
+ // Adding a new input with the same configuration should not change the
+ // number of converters.
+ MockInput input5(input_params_resamp_downmix);
+ mixing_graph.AddInput(&input5);
+ // Graph:
+ // main <--- converter (resampler) <--- input1
+ // <--- input2
+ // <--- converter (ch. mixer) <--- input4
+ // <--- input5
+ // <--- converter (ch. mixer) <--- input3
+
+ mixing_graph.RemoveInput(&input1);
+ mixing_graph.RemoveInput(&input2);
+ mixing_graph.RemoveInput(&input3);
+ mixing_graph.RemoveInput(&input4);
+ mixing_graph.RemoveInput(&input5);
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/mixing_graph_input_unittest.cc b/chromium/services/audio/mixing_graph_input_unittest.cc
new file mode 100644
index 00000000000..1405a049540
--- /dev/null
+++ b/chromium/services/audio/mixing_graph_input_unittest.cc
@@ -0,0 +1,406 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <array>
+#include <limits>
+#include "services/audio/mixing_graph.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace audio {
+// Test fixture to verify the functionality of the mixing graph inputs.
+class MixingGraphInputTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ output_params_ = media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 480);
+ mixing_graph_ = MixingGraph::Create(
+ output_params_,
+ base::BindRepeating(&MixingGraphInputTest::OnMoreDataCallBack,
+ base::Unretained(this)),
+ base::BindRepeating(&MixingGraphInputTest::OnErrorCallback,
+ base::Unretained(this)));
+ dest_ = media::AudioBus::Create(output_params_);
+ }
+
+ void PullAndVerifyData(int num_runs,
+ float expected_first_sample,
+ float expected_sample_increment,
+ float epsilon) {
+ float expected_data = expected_first_sample;
+ for (int i = 0; i < num_runs; i++) {
+ mixing_graph_->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
+ dest_.get());
+ float* data = dest_.get()->channel(0);
+ for (int j = 0; j < dest_.get()->frames(); ++j) {
+ EXPECT_NEAR(data[j], expected_data, epsilon);
+ expected_data += expected_sample_increment;
+ }
+ }
+ }
+
+ void OnMoreDataCallBack(const media::AudioBus&, base::TimeDelta) {}
+ void OnErrorCallback(
+ media::AudioOutputStream::AudioSourceCallback::ErrorType) {}
+
+ media::AudioParameters output_params_;
+ std::unique_ptr<MixingGraph> mixing_graph_;
+ std::unique_ptr<media::AudioBus> dest_;
+};
+
+// Simple audio source callback where a sample value is the value of the
+// previous sample plus |increment|. When using stereo the values of the right
+// channel will be the values of the left channel plus |increment|.
+class SampleCounter : public media::AudioOutputStream::AudioSourceCallback {
+ public:
+ explicit SampleCounter(float counter, float increment)
+ : counter_(counter), increment_(increment) {}
+ int OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) final {
+ // Fill the audio bus with a simple, predictable pattern.
+ for (int channel = 0; channel < dest->channels(); ++channel) {
+ float* data = dest->channel(channel);
+ for (int frame = 0; frame < dest->frames(); frame++) {
+ data[frame] = counter_ + increment_ * frame + increment_ * channel;
+ }
+ }
+ counter_ += static_cast<float>(increment_ * dest->frames());
+ return 0;
+ }
+ void OnError(ErrorType type) final {}
+
+ private:
+ float counter_ = 0.0f;
+ const float increment_;
+};
+
+// Simple audio source callback where all samples are set to the same value.
+// The value is incremented by |increment| for each callback.
+class CallbackCounter : public media::AudioOutputStream::AudioSourceCallback {
+ public:
+ explicit CallbackCounter(float counter, float increment)
+ : counter_(counter), increment_(increment) {}
+ int OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) final {
+ // Fill the audio bus with the counter value.
+ for (int channel = 0; channel < dest->channels(); ++channel) {
+ float* data = dest->channel(channel);
+ for (int frame = 0; frame < dest->frames(); frame++) {
+ data[frame] = counter_;
+ }
+ }
+ counter_ += increment_;
+ return 0;
+ }
+ void OnError(ErrorType type) final {}
+
+ private:
+ float counter_ = 0.0f;
+ const float increment_;
+};
+
+// Simple audio source callback where all samples are set to a specified value.
+class ConstantInput : public media::AudioOutputStream::AudioSourceCallback {
+ public:
+ explicit ConstantInput(float value) : value_(value) {}
+ int OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) final {
+ // Fill the audio bus with the value specified at construction.
+ for (int channel = 0; channel < dest->channels(); ++channel) {
+ float* data = dest->channel(channel);
+ for (int frame = 0; frame < dest->frames(); frame++) {
+ data[frame] = value_;
+ }
+ }
+ return 0;
+ }
+ void OnError(ErrorType type) final {}
+
+ private:
+ const float value_;
+};
+
+// Verifies that the mixing graph outputs zeros when no inputs have been added.
+TEST_F(MixingGraphInputTest, NoInputs) {
+ // The mixing graph is expected to output zeros when it has no inputs.
+ PullAndVerifyData(/*num_runs=*/2, /*expected_first_sample=*/0.0f,
+ /*expected_sample_increment=*/0.0f, /*epsilon=*/0.0f);
+}
+
+// Verifies the output of a single input with the same parameters as the mixing
+// graph.
+TEST_F(MixingGraphInputTest, SingleInput) {
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(output_params_);
+ input->Start(&source_callback);
+ PullAndVerifyData(/*num_runs=*/2,
+ /*expected_first_sample=*/kInitialCounterValue,
+ /*expected_sample_increment=*/kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input->Stop();
+}
+
+// Verifies the output of the mixing graph when adding multiple inputs.
+TEST_F(MixingGraphInputTest, MultipleInputs) {
+ constexpr float kInitialCounterValue1 = 0.1f;
+ constexpr float kInitialCounterValue2 = 0.5f;
+ constexpr float kInitialCounterValue3 = -0.7f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback1(kInitialCounterValue1, kCounterIncrement);
+ SampleCounter source_callback2(kInitialCounterValue2, kCounterIncrement);
+ SampleCounter source_callback3(kInitialCounterValue3, kCounterIncrement);
+ auto input1 = mixing_graph_->CreateInput(output_params_);
+ input1->Start(&source_callback1);
+ auto input2 = mixing_graph_->CreateInput(output_params_);
+ input2->Start(&source_callback2);
+ auto input3 = mixing_graph_->CreateInput(output_params_);
+ input3->Start(&source_callback3);
+ PullAndVerifyData(/*num_runs=*/2,
+ /*expected_first_sample=*/kInitialCounterValue1 +
+ kInitialCounterValue2 + kInitialCounterValue3,
+ /*expected_sample_increment=*/3.0f * kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input1->Stop();
+ input2->Stop();
+ input3->Stop();
+}
+
+// Verifies the mixing graph output when adding an input in need of channel
+// mixing.
+TEST_F(MixingGraphInputTest, ChannelMixing) {
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 48000, 480);
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(input_params);
+ input->Start(&source_callback);
+ // The right channel has the values of the left channel + kCounterIncrement.
+ // When down-mixing (averaging) the two channels this will cause a bias of
+ // kCounterIncrement/2.
+ PullAndVerifyData(
+ /*num_runs=*/2,
+ /*expected_first_sample=*/kInitialCounterValue + 0.5f * kCounterIncrement,
+ /*expected_sample_increment=*/kCounterIncrement, /*epsilon=*/1e-5f);
+ input->Stop();
+}
+
+// Verifies the mixing graph output when adding an input in need of resampling.
+TEST_F(MixingGraphInputTest, Resampling) {
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 24000, 480);
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(input_params);
+ input->Start(&source_callback);
+ // The input signal will increase by kCounterIncrement for each sample and be
+ // upsampled by a factor 2. The output will therefore increase by
+ // ~kCounterIncrement/2 per sample.
+ PullAndVerifyData(/*num_runs=*/2,
+ /*expected_first_sample=*/kInitialCounterValue,
+ /*expected_sample_increment=*/0.5f * kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input->Stop();
+}
+
+// Verifies the use of FIFO when an input produces less data per call than
+// requested by the mixing graph.
+TEST_F(MixingGraphInputTest, Buffering1) {
+ // Input produces 5 ms of audio. Output consumes 10 ms.
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 240);
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(input_params);
+ input->Start(&source_callback);
+ PullAndVerifyData(/*num_runs=*/2,
+ /*expected_first_sample=*/kInitialCounterValue,
+ /*expected_sample_increment=*/kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input->Stop();
+}
+
+// Verifies the use of FIFO when an input produces more data per call than
+// requested by the mixing graph.
+TEST_F(MixingGraphInputTest, Buffering2) {
+ // Input produces 15 ms of audio. Output consumes 10 ms.
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 720);
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(input_params);
+ input->Start(&source_callback);
+ PullAndVerifyData(/*num_runs=*/2,
+ /*expected_first_sample=*/kInitialCounterValue,
+ /*expected_sample_increment=*/kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input->Stop();
+}
+
+// Verifies that no left-over samples from the FIFO are pulled after stopping
+// and restarting the input.
+TEST_F(MixingGraphInputTest, BufferClearedAtRestart) {
+ // Input produces 15 ms of audio. Output consumes 10 ms.
+ media::AudioParameters input_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_MONO, 48000, 720);
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ CallbackCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(input_params);
+ input->Start(&source_callback);
+
+ // Get the last sample of the first output.
+ mixing_graph_->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
+ dest_.get());
+ float last_sample = dest_.get()->channel(0)[dest_.get()->frames() - 1];
+
+ // Stop and restart.
+ input->Stop();
+ input->Start(&source_callback);
+
+ // Get the first sample of the second output.
+ mixing_graph_->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
+ dest_.get());
+ float first_sample = dest_.get()->channel(0)[0];
+
+ // If the first sample of the second output is equal to the last sample of
+ // the first output left-over data has been consumed.
+ EXPECT_NE(first_sample, last_sample);
+ input->Stop();
+}
+
+// Verifies the output of the mixing graph when adding and removing inputs on
+// the fly.
+TEST_F(MixingGraphInputTest, AddingAndRemovingInputs) {
+ constexpr float kInitialCounterValue1 = -0.3f;
+ constexpr float kInitialCounterValue2 = 0.2f;
+ constexpr float kCounterIncrement = 1e-4f;
+ SampleCounter source_callback1(kInitialCounterValue1, kCounterIncrement);
+ SampleCounter source_callback2(kInitialCounterValue2, kCounterIncrement);
+ auto input1 = mixing_graph_->CreateInput(output_params_);
+ auto input2 = mixing_graph_->CreateInput(output_params_);
+
+ // Start the first input.
+ input1->Start(&source_callback1);
+ PullAndVerifyData(/*num_runs=*/1,
+ /*expected_first_sample=*/kInitialCounterValue1,
+ /*expected_sample_increment=*/kCounterIncrement,
+ /*epsilon=*/1e-5f);
+
+ // Start the second input.
+ input2->Start(&source_callback2);
+ PullAndVerifyData(/*num_runs=*/1,
+ /*expected_first_sample=*/kInitialCounterValue1 +
+ kCounterIncrement * dest_->frames() +
+ kInitialCounterValue2,
+ /*expected_sample_increment=*/2.0f * kCounterIncrement,
+ /*epsilon=*/1e-5f);
+
+ // Stop the first input.
+ input1->Stop();
+ PullAndVerifyData(
+ /*num_runs=*/1,
+ /*expected_first_sample=*/kInitialCounterValue2 +
+ kCounterIncrement * dest_->frames(),
+ /*expected_sample_increment=*/kCounterIncrement, /*epsilon=*/1e-5f);
+
+ // Stop the second input.
+ input2->Stop();
+ PullAndVerifyData(/*num_runs=*/1,
+ /*expected_first_sample=*/0.f,
+ /*expected_sample_increment=*/0.0f, /*epsilon=*/0.0f);
+}
+
+// Verifies that the volume is applied correctly.
+TEST_F(MixingGraphInputTest, SetVolume) {
+ constexpr float kInitialCounterValue = 0.0f;
+ constexpr float kCounterIncrement = 1e-4f;
+ constexpr float kVolume1 = 0.77f;
+ constexpr float kVolume2 = 0.13f;
+ SampleCounter source_callback(kInitialCounterValue, kCounterIncrement);
+ auto input = mixing_graph_->CreateInput(output_params_);
+ input->Start(&source_callback);
+ input->SetVolume(kVolume1);
+ PullAndVerifyData(/*num_runs=*/1,
+ /*expected_first_sample=*/kInitialCounterValue * kVolume1,
+ /*expected_sample_increment=*/kVolume1 * kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input->SetVolume(kVolume2);
+ PullAndVerifyData(
+ /*num_runs=*/1,
+ /*expected_first_sample=*/
+ (kInitialCounterValue + kCounterIncrement * dest_->frames()) * kVolume2,
+ /*expected_sample_increment=*/kVolume2 * kCounterIncrement,
+ /*epsilon=*/1e-5f);
+ input->Stop();
+}
+
+// Verifies that out-of-range output values are sanitized.
+TEST_F(MixingGraphInputTest, OutOfRange) {
+ constexpr float kInputValue1 = -0.6f;
+ constexpr float kInputValue2 = -0.5f;
+ ConstantInput source_callback1(kInputValue1);
+ ConstantInput source_callback2(kInputValue2);
+ auto input1 = mixing_graph_->CreateInput(output_params_);
+ input1->Start(&source_callback1);
+ auto input2 = mixing_graph_->CreateInput(output_params_);
+ input2->Start(&source_callback2);
+ // The two inputs should add to -1.1 and be clamped to -1.0.
+ PullAndVerifyData(/*num_runs=*/1,
+ /*expected_first_sample=*/-1.0f,
+ /*expected_sample_increment=*/0.0f, /*epsilon=*/0.0f);
+ // Lowering the volume of input 1 removes the need of clamping.
+ input1->SetVolume(0.5f);
+ PullAndVerifyData(
+ /*num_runs=*/1,
+ /*expected_first_sample=*/kInputValue1 * 0.5f + kInputValue2,
+ /*expected_sample_increment=*/0.0f, /*epsilon=*/0.0f);
+ input1->Stop();
+ input2->Stop();
+}
+
+// Verifies that invalid input is sanitized.
+TEST_F(MixingGraphInputTest, InvalidInput) {
+ // Pairs of input values and expected output values.
+ std::array<std::pair<float, float>, 8> test_values = {{
+ {-1.5f, -1.0f}, // Negative overflow.
+ {2.0f, 1.0f}, // Positive overflow.
+ {-0.8, -0.8f}, // Valid.
+ {0.3, 0.3f}, // Valid.
+ {0.0, 0.0f}, // Valid.
+ {std::numeric_limits<float>::infinity(), 1.0f}, // Positive infinity.
+ {-std::numeric_limits<float>::infinity(), -1.0f}, // Negative infinity.
+ {NAN, 1.0f}, // NaN.
+ }};
+ for (const auto& test_pair : test_values) {
+ float input_value = test_pair.first;
+ float expected_output_value = test_pair.second;
+
+ auto input = mixing_graph_->CreateInput(output_params_);
+ ConstantInput source_callback(input_value);
+ input->Start(&source_callback);
+ PullAndVerifyData(
+ /*num_runs=*/1,
+ /*expected_first_sample=*/expected_output_value,
+ /*expected_sample_increment=*/0.0f, /*epsilon=*/0.0f);
+ input->Stop();
+ }
+}
+} // namespace audio
diff --git a/chromium/services/audio/output_controller.cc b/chromium/services/audio/output_controller.cc
index 42a6baa36c2..c73ae36215d 100644
--- a/chromium/services/audio/output_controller.cc
+++ b/chromium/services/audio/output_controller.cc
@@ -19,11 +19,12 @@
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
-#include "base/task_runner_util.h"
+#include "base/task/task_runner_util.h"
#include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h"
#include "media/base/audio_timestamp_helper.h"
#include "services/audio/concurrent_stream_metric_reporter.h"
+#include "services/audio/device_listener_output_stream.h"
#include "services/audio/stream_monitor.h"
@@ -119,9 +120,13 @@ OutputController::OutputController(
OutputStreamActivityMonitor* activity_monitor,
const media::AudioParameters& params,
const std::string& output_device_id,
- SyncReader* sync_reader)
+ SyncReader* sync_reader,
+ ManagedDeviceOutputStreamCreateCallback
+ managed_device_output_stream_create_callback)
: audio_manager_(audio_manager),
params_(params),
+ managed_device_output_stream_create_callback_(
+ std::move(managed_device_output_stream_create_callback)),
handler_(handler),
activity_monitor_(activity_monitor),
task_runner_(audio_manager->GetTaskRunner()),
@@ -207,7 +212,7 @@ void OutputController::RecreateStream(OutputController::RecreateReason reason) {
if (state_ == kClosed)
return;
- StopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener().
+ StopCloseAndClearStream();
DCHECK_EQ(kEmpty, state_);
if (disable_local_output_) {
@@ -222,9 +227,21 @@ void OutputController::RecreateStream(OutputController::RecreateReason reason) {
stream_ = audio_manager_->MakeAudioOutputStream(
mute_params, std::string(),
/*log_callback, not used*/ base::DoNothing());
+ } else if (managed_device_output_stream_create_callback_) {
+ stream_ = managed_device_output_stream_create_callback_.Run(
+ output_device_id_, params_,
+ base::BindRepeating(&OutputController::ProcessDeviceChange,
+ base::Unretained(this)));
} else {
- stream_ =
+ media::AudioOutputStream* stream =
audio_manager_->MakeAudioOutputStreamProxy(params_, output_device_id_);
+ if (stream) {
+ // ProcessDeviceChange must close |stream_|.
+ stream_ = new DeviceListenerOutputStream(
+ audio_manager_, stream,
+ base::BindRepeating(&OutputController::ProcessDeviceChange,
+ base::Unretained(this)));
+ }
}
if (!stream_) {
@@ -235,7 +252,6 @@ void OutputController::RecreateStream(OutputController::RecreateReason reason) {
return;
}
- weak_this_for_stream_ = weak_factory_for_stream_.GetWeakPtr();
if (!stream_->Open()) {
SendLogMessage("%s => (ERROR: failed to open the created output stream)",
__func__);
@@ -246,7 +262,6 @@ void OutputController::RecreateStream(OutputController::RecreateReason reason) {
return;
}
-
// Finally set the state to kCreated. Note that, it is possible that the
// stream is fake in this state due to the fallback mechanism in the audio
// output dispatcher which falls back to a fake stream if audio parameters
@@ -256,8 +271,6 @@ void OutputController::RecreateStream(OutputController::RecreateReason reason) {
// We have successfully opened the stream. Set the initial volume.
stream_->SetVolume(volume_);
-
- audio_manager_->AddOutputDeviceChangeListener(this);
}
void OutputController::Play() {
@@ -387,18 +400,6 @@ void OutputController::SetVolume(double volume) {
}
}
-void OutputController::ReportError() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- TRACE_EVENT0("audio", "OutputController::ReportError");
- DLOG(ERROR) << "OutputController::ReportError";
- SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
- if (state_ != kClosed) {
- if (stats_tracker_)
- stats_tracker_->RegisterError();
- handler_->OnControllerError();
- }
-}
-
int OutputController::OnMoreData(base::TimeDelta delay,
base::TimeTicks delay_timestamp,
int prior_frames_skipped,
@@ -470,26 +471,21 @@ void OutputController::LogAudioPowerLevel(const char* call_name) {
}
bool OutputController::StreamIsActive() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
return (state_ == kPlaying) && !disable_local_output_;
}
void OutputController::OnError(ErrorType type) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
SendLogMessage("%s({type=%s} [state=%s])", __func__, ErrorTypeToString(type),
StateToString(state_));
- if (type == ErrorType::kDeviceChange) {
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(&OutputController::OnDeviceChange,
- weak_this_for_stream_));
- return;
+ TRACE_EVENT0("audio", "OutputController::OnError");
+ DLOG(ERROR) << "OutputController::OnError";
+ if (state_ != kClosed) {
+ if (stats_tracker_)
+ stats_tracker_->RegisterError();
+ handler_->OnControllerError();
}
-
- // Handle error on the audio controller thread. We defer errors for one
- // second in case they are the result of a device change; delay chosen to
- // exceed duration of device changes which take a few hundred milliseconds.
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&OutputController::ReportError, weak_this_for_stream_),
- base::Seconds(1));
}
void OutputController::StopCloseAndClearStream() {
@@ -497,17 +493,8 @@ void OutputController::StopCloseAndClearStream() {
// Allow calling unconditionally and bail if we don't have a stream_ to close.
if (stream_) {
- // Ensure any pending tasks, specific to the stream_, are canceled.
- weak_factory_for_stream_.InvalidateWeakPtrs();
-
- // De-register from state change callbacks if stream_ was created via
- // AudioManager.
- audio_manager_->RemoveOutputDeviceChangeListener(this);
-
StopStream();
stream_->Close();
- stats_tracker_.reset();
-
stream_ = nullptr;
}
@@ -583,14 +570,12 @@ void OutputController::ToggleLocalOutput() {
}
}
-void OutputController::OnDeviceChange() {
+void OutputController::ProcessDeviceChange() {
DCHECK(task_runner_->BelongsToCurrentThread());
- TRACE_EVENT0("audio", "OutputController::OnDeviceChange");
-
- if (disable_local_output_)
- return; // No actions need to be taken while local output is disabled.
-
SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
+ TRACE_EVENT0("audio", "OutputController::ProcessDeviceChange");
+
+ DCHECK(!disable_local_output_);
// TODO(dalecurtis): Notify the renderer side that a device change has
// occurred. Currently querying the hardware information here will lead to
diff --git a/chromium/services/audio/output_controller.h b/chromium/services/audio/output_controller.h
index 55b31d578dc..666181c233c 100644
--- a/chromium/services/audio/output_controller.h
+++ b/chromium/services/audio/output_controller.h
@@ -14,8 +14,6 @@
#include "base/atomic_ref_count.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -23,7 +21,6 @@
#include "build/build_config.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
-#include "media/audio/audio_source_diverter.h"
#include "media/base/audio_power_monitor.h"
#include "services/audio/loopback_group_member.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -61,8 +58,7 @@ namespace audio {
class OutputStreamActivityMonitor;
class OutputController : public media::AudioOutputStream::AudioSourceCallback,
- public LoopbackGroupMember,
- public media::AudioManager::AudioDeviceListener {
+ public LoopbackGroupMember {
public:
// An event handler that receives events from the OutputController. The
// following methods are called on the audio manager thread.
@@ -112,15 +108,30 @@ class OutputController : public media::AudioOutputStream::AudioSourceCallback,
kError,
};
+ // OutputController guarantees that |on_device_change_callback| will
+ // synchronously close the stream received in
+ // ManagedDeviceOutputStreamCreateCallback.
+ using ManagedDeviceOutputStreamCreateCallback =
+ base::RepeatingCallback<media::AudioOutputStream*(
+ const std::string&,
+ const media::AudioParameters&,
+ base::OnceClosure on_device_change_callback)>;
+
// |audio_manager| and |handler| must outlive OutputController. The
// |output_device_id| can be either empty (default device) or specify a
// specific hardware device for audio output.
+ // If |managed_device_output_stream_create_callback| is provided, it will be
+ // used to create a device stream under control; otherwise the stream will be
+ // created using |audio_manager|.
OutputController(media::AudioManager* audio_manager,
EventHandler* handler,
OutputStreamActivityMonitor* activity_monitor,
const media::AudioParameters& params,
const std::string& output_device_id,
- SyncReader* sync_reader);
+ SyncReader* sync_reader,
+ ManagedDeviceOutputStreamCreateCallback
+ managed_device_output_stream_create_callback =
+ ManagedDeviceOutputStreamCreateCallback());
OutputController(const OutputController&) = delete;
OutputController& operator=(const OutputController&) = delete;
@@ -175,11 +186,6 @@ class OutputController : public media::AudioOutputStream::AudioSourceCallback,
void StartMuting() override;
void StopMuting() override;
- // AudioDeviceListener implementation. When called OutputController will
- // shutdown the existing |stream_|, create a new stream, and then transition
- // back to an equivalent state prior to being called.
- void OnDeviceChange() override;
-
// Accessor for AudioPowerMonitor::ReadCurrentPowerAndClip(). See comments in
// audio_power_monitor.h for usage. This may be called on any thread.
std::pair<float, bool> ReadCurrentPowerAndClip();
@@ -279,9 +285,19 @@ class OutputController : public media::AudioOutputStream::AudioSourceCallback,
// change.
void ToggleLocalOutput();
+ // When called, OutputController will shutdown the existing |stream_|, create
+ // a new stream, and then transition back to an equivalent state prior to
+ // being called.
+ void ProcessDeviceChange();
+
media::AudioManager* const audio_manager_;
const media::AudioParameters params_;
+ // Callback to create a device output stream; if not specified -
+ // |audio_manager_| will be used to create a device output stream.
+ ManagedDeviceOutputStreamCreateCallback
+ managed_device_output_stream_create_callback_;
+
// This object (OC) is owned by an OutputStream (OS) object which is an
// EventHandler. |handler_| is set at construction by the OS (using this).
// It is safe to use a raw pointer here since the OS will always outlive
@@ -332,11 +348,6 @@ class OutputController : public media::AudioOutputStream::AudioSourceCallback,
// and destroyed when a stream stops. Also reset every time there is a stream
// being created due to device changes.
absl::optional<ErrorStatisticsTracker> stats_tracker_;
-
- // WeakPtrFactory+WeakPtr that is used to post tasks that are canceled when a
- // stream is closed.
- base::WeakPtr<OutputController> weak_this_for_stream_;
- base::WeakPtrFactory<OutputController> weak_factory_for_stream_{this};
};
} // namespace audio
diff --git a/chromium/services/audio/output_controller_unittest.cc b/chromium/services/audio/output_controller_unittest.cc
index 705aec3d04f..84b1c36c4f4 100644
--- a/chromium/services/audio/output_controller_unittest.cc
+++ b/chromium/services/audio/output_controller_unittest.cc
@@ -15,12 +15,12 @@
#include "base/check.h"
#include "base/environment.h"
#include "base/location.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/notreached.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/test_message_loop.h"
#include "base/threading/thread.h"
@@ -75,39 +75,45 @@ class MockOutputControllerEventHandler : public OutputController::EventHandler {
public:
MockOutputControllerEventHandler() = default;
+ MockOutputControllerEventHandler(const MockOutputControllerEventHandler&) =
+ delete;
+ MockOutputControllerEventHandler& operator=(
+ const MockOutputControllerEventHandler&) = delete;
+
MOCK_METHOD0(OnControllerPlaying, void());
MOCK_METHOD0(OnControllerPaused, void());
MOCK_METHOD0(OnControllerError, void());
void OnLog(base::StringPiece) override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockOutputControllerEventHandler);
};
class MockOutputControllerSyncReader : public OutputController::SyncReader {
public:
MockOutputControllerSyncReader() = default;
+ MockOutputControllerSyncReader(const MockOutputControllerSyncReader&) =
+ delete;
+ MockOutputControllerSyncReader& operator=(
+ const MockOutputControllerSyncReader&) = delete;
+
MOCK_METHOD3(RequestMoreData,
void(base::TimeDelta delay,
base::TimeTicks delay_timestamp,
int prior_frames_skipped));
MOCK_METHOD1(Read, void(AudioBus* dest));
MOCK_METHOD0(Close, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockOutputControllerSyncReader);
};
class MockOutputStreamActivityMonitor : public OutputStreamActivityMonitor {
public:
MockOutputStreamActivityMonitor() = default;
+ MockOutputStreamActivityMonitor(const MockOutputStreamActivityMonitor&) =
+ delete;
+ MockOutputStreamActivityMonitor& operator=(
+ const MockOutputStreamActivityMonitor&) = delete;
+
MOCK_METHOD0(OnOutputStreamActive, void());
MOCK_METHOD0(OnOutputStreamInactive, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockOutputStreamActivityMonitor);
};
// Wraps an AudioOutputStream instance, calling DidXYZ() mock methods for test
@@ -121,6 +127,9 @@ class MockAudioOutputStream : public AudioOutputStream,
MockAudioOutputStream(AudioOutputStream* impl, AudioParameters::Format format)
: impl_(impl), format_(format) {}
+ MockAudioOutputStream(const MockAudioOutputStream&) = delete;
+ MockAudioOutputStream& operator=(const MockAudioOutputStream&) = delete;
+
AudioParameters::Format format() const { return format_; }
void set_close_callback(base::OnceClosure callback) {
@@ -144,7 +153,7 @@ class MockAudioOutputStream : public AudioOutputStream,
}
void Start(AudioOutputStream::AudioSourceCallback* cb) override {
- EXPECT_EQ(nullptr, callback_);
+ EXPECT_EQ(nullptr, callback_.get());
callback_ = cb;
if (impl_) {
impl_->Start(this);
@@ -226,14 +235,12 @@ class MockAudioOutputStream : public AudioOutputStream,
NOTREACHED();
}
- AudioOutputStream* impl_;
+ raw_ptr<AudioOutputStream> impl_;
const AudioParameters::Format format_;
base::OnceClosure close_callback_;
- AudioOutputStream::AudioSourceCallback* callback_ = nullptr;
+ raw_ptr<AudioOutputStream::AudioSourceCallback> callback_ = nullptr;
double volume_ = 1.0;
std::unique_ptr<base::Thread> data_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(MockAudioOutputStream);
};
class MockSnooper : public Snoopable::Snooper {
@@ -311,14 +318,16 @@ class AudioManagerForControllerTest final : public media::FakeAudioManager {
return last_created_stream_;
}
+ void SimulateDeviceChange() { NotifyAllOutputDeviceChangeListeners(); }
+
private:
void SetLastClosedStream(MockAudioOutputStream* stream) {
last_closed_stream_ = stream;
}
media::FakeAudioLogFactory fake_audio_log_factory_;
- MockAudioOutputStream* last_created_stream_ = nullptr;
- MockAudioOutputStream* last_closed_stream_ = nullptr;
+ raw_ptr<MockAudioOutputStream> last_created_stream_ = nullptr;
+ raw_ptr<MockAudioOutputStream> last_closed_stream_ = nullptr;
};
ACTION(PopulateBuffer) {
@@ -396,16 +405,23 @@ class OutputControllerTest : public ::testing::Test {
Mock::VerifyAndClearExpectations(&mock_event_handler_);
}
- void ChangeDevice() {
- // Expect the event handler to receive one OnControllerPaying() call and no
- // OnControllerPaused() call.
- EXPECT_CALL(mock_event_handler_, OnControllerPlaying());
+ void ChangeDevice(bool expect_play_event = true) {
+ // If the stream was already playing before the device change, expect the
+ // event handler to receive one OnControllerPaying() call.
+ if (expect_play_event) {
+ EXPECT_CALL(mock_event_handler_, OnControllerPlaying());
+ } else {
+ EXPECT_CALL(mock_event_handler_, OnControllerPlaying()).Times(0);
+ }
+
+ // Never expect a OnControllerPaused() call.
EXPECT_CALL(mock_event_handler_, OnControllerPaused()).Times(0);
// Simulate a device change event to OutputController from the AudioManager.
audio_manager_.GetTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(&OutputController::OnDeviceChange,
- base::Unretained(&(*controller_))));
+ FROM_HERE,
+ base::BindOnce(&AudioManagerForControllerTest::SimulateDeviceChange,
+ base::Unretained(&audio_manager_)));
// Wait for device change to take effect.
base::RunLoop loop;
@@ -462,32 +478,6 @@ class OutputControllerTest : public ::testing::Test {
void Flush() { controller_->Flush(); }
- void SimulateErrorThenDeviceChange() {
- audio_manager_.GetTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&OutputControllerTest::TriggerErrorThenDeviceChange,
- base::Unretained(this)));
-
- base::RunLoop loop;
- audio_manager_.GetTaskRunner()->PostTask(FROM_HERE, loop.QuitClosure());
- loop.Run();
- }
-
- void TriggerErrorThenDeviceChange() {
- DCHECK(audio_manager_.GetTaskRunner()->BelongsToCurrentThread());
-
- // Errors should be deferred; the device change should ensure it's dropped.
- EXPECT_CALL(mock_event_handler_, OnControllerError()).Times(0);
- controller_->OnError(
- media::AudioOutputStream::AudioSourceCallback::ErrorType::kUnknown);
-
- EXPECT_CALL(mock_event_handler_, OnControllerPlaying());
- EXPECT_CALL(mock_event_handler_, OnControllerPaused()).Times(0);
- controller_->OnDeviceChange();
-
- Mock::VerifyAndClearExpectations(&mock_event_handler_);
- }
-
StrictMock<MockOutputControllerEventHandler> mock_event_handler_;
StrictMock<MockOutputStreamActivityMonitor> mock_stream_activity_monitor_;
@@ -543,13 +533,34 @@ TEST_F(OutputControllerTest, PlayDeviceChangeClose) {
Close();
}
-TEST_F(OutputControllerTest, PlayDeviceChangeError) {
+TEST_F(OutputControllerTest, PlayDeviceChangeDeviceChangeClose) {
EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamActive()).Times(1);
EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamInactive()).Times(1);
Create();
Play();
- SimulateErrorThenDeviceChange();
+ ChangeDevice();
+ ChangeDevice();
+ Close();
+}
+
+TEST_F(OutputControllerTest, PlayPauseDeviceChangeClose) {
+ EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamActive()).Times(1);
+ EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamInactive()).Times(1);
+
+ Create();
+ Play();
+ Pause();
+ ChangeDevice(/*expect_play_event=*/false);
+ Close();
+}
+
+TEST_F(OutputControllerTest, CreateDeviceChangeClose) {
+ EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamActive()).Times(0);
+ EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamInactive()).Times(0);
+
+ Create();
+ ChangeDevice(/*expect_play_event=*/false);
Close();
}
@@ -777,6 +788,20 @@ TEST_F(OutputControllerTest, FlushesWhenStreamIsNotPlaying) {
Close();
}
+TEST_F(OutputControllerTest, FlushesAfterDeviceChange) {
+ EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamActive()).Times(0);
+ EXPECT_CALL(mock_stream_activity_monitor_, OnOutputStreamInactive()).Times(0);
+
+ Create();
+ ChangeDevice(/*expect_play_event=*/false);
+
+ MockAudioOutputStream* const mock_stream = last_created_stream();
+ EXPECT_CALL(*mock_stream, DidFlush()).Times(1);
+ Flush();
+
+ Close();
+}
+
// Tests that stream activity (play/pause, taking muting into account) is
// correctly signalled to the OutputStreamActivityMonitor.
TEST_F(OutputControllerTest, ReportActivity) {
@@ -841,5 +866,104 @@ TEST_F(OutputControllerTest, ReportActivity) {
EXPECT_FALSE(stream_active_state);
}
+class MockAudioOutputStreamForMixing : public AudioOutputStream {
+ public:
+ MOCK_METHOD0(Open, bool());
+ MOCK_METHOD1(Start, void(AudioSourceCallback*));
+ MOCK_METHOD0(Stop, void());
+ void SetVolume(double volume) override {}
+ void GetVolume(double* volume) override {}
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(Flush, void());
+};
+
+TEST(OutputControllerMixingTest,
+ ControllerUsesProvidedCManagedDeviceOutputStreamCreateCallbackCorrectly) {
+ base::TestMessageLoop message_loop_;
+ // Controller creation parameters.
+ AudioManagerForControllerTest audio_manager;
+ NiceMock<MockOutputControllerEventHandler> mock_event_handler;
+ NiceMock<MockOutputStreamActivityMonitor> mock_stream_activity_monitor;
+ NiceMock<MockOutputControllerSyncReader> mock_sync_reader;
+ const std::string controller_device_id("device id");
+ const AudioParameters controller_params(GetTestParams());
+
+ // Callback that OutputController should provide when calling
+ // ManagedDeviceOutputStreamCreateCallback to create a stream.
+ base::OnceClosure provided_on_device_change_callback;
+
+ // Mock outputstream which will be returned to the OutputController when it
+ // calls ManagedDeviceOutputStreamCreateCallback.
+ StrictMock<MockAudioOutputStreamForMixing> mock_output_stream;
+
+ // Mock to be used for ManagedDeviceOutputStreamCreateCallback implementation.
+ auto CreateStream =
+ [](const std::string& controller_device_id,
+ const AudioParameters& controller_params,
+ MockAudioOutputStreamForMixing* const mock_output_stream,
+ base::OnceClosure* provided_on_device_change_callback,
+ const std::string& device_id, const AudioParameters& params,
+ base::OnceClosure on_device_change_callback) -> AudioOutputStream* {
+ EXPECT_TRUE(params.Equals(controller_params));
+ EXPECT_EQ(device_id, controller_device_id);
+ *provided_on_device_change_callback = std::move(on_device_change_callback);
+ return mock_output_stream;
+ };
+
+ ON_CALL(mock_output_stream, Open()).WillByDefault(Return(true));
+
+ OutputController::ManagedDeviceOutputStreamCreateCallback
+ mock_create_stream_cb = base::BindRepeating(
+ CreateStream, controller_device_id, controller_params,
+ &mock_output_stream, &provided_on_device_change_callback);
+
+ EXPECT_FALSE(provided_on_device_change_callback);
+
+ // Check that controller called |mock_create_stream_cb| on its CreateStream(),
+ // and uses the result AudioOutputStream.
+ EXPECT_CALL(mock_output_stream, Open()).Times(1);
+
+ OutputController controller(&audio_manager, &mock_event_handler,
+ &mock_stream_activity_monitor, controller_params,
+ controller_device_id, &mock_sync_reader,
+ std::move(mock_create_stream_cb));
+
+ controller.CreateStream();
+
+ // When invoking |mock_create_stream_cb|, OutputController
+ // provided a callback to handle device changes.
+ EXPECT_TRUE(provided_on_device_change_callback);
+ Mock::VerifyAndClearExpectations(&mock_output_stream);
+
+ {
+ // When |provided_on_device_change_callback| is called, OutputController
+ // must synchronously close the output stream, and then it will call
+ // |mock_create_stream_cb| to create a new one.
+ testing::InSequence s;
+ EXPECT_CALL(mock_output_stream, Close()).Times(1);
+ EXPECT_CALL(mock_output_stream, Open()).Times(1);
+ EXPECT_TRUE(provided_on_device_change_callback);
+
+ std::move(provided_on_device_change_callback).Run();
+ Mock::VerifyAndClearExpectations(&mock_output_stream);
+ }
+
+ {
+ // After the first device change, OutputController handles the next device
+ // change correctly as well.
+ testing::InSequence s;
+ EXPECT_CALL(mock_output_stream, Close()).Times(1);
+ EXPECT_CALL(mock_output_stream, Open()).Times(1);
+ EXPECT_TRUE(provided_on_device_change_callback);
+
+ std::move(provided_on_device_change_callback).Run();
+ Mock::VerifyAndClearExpectations(&mock_output_stream);
+ }
+
+ EXPECT_CALL(mock_output_stream, Close()).Times(1);
+ controller.Close();
+ audio_manager.Shutdown();
+}
+
} // namespace
} // namespace audio
diff --git a/chromium/services/audio/output_device_mixer.cc b/chromium/services/audio/output_device_mixer.cc
new file mode 100644
index 00000000000..dbf3b9d887b
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer.cc
@@ -0,0 +1,26 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/output_device_mixer.h"
+
+#include "services/audio/mixing_graph.h"
+#include "services/audio/output_device_mixer_impl.h"
+
+namespace audio {
+
+// static
+std::unique_ptr<OutputDeviceMixer> OutputDeviceMixer::Create(
+ const std::string& device_id,
+ const media::AudioParameters& output_params,
+ CreateStreamCallback create_stream_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ return std::make_unique<OutputDeviceMixerImpl>(
+ device_id, output_params, base::BindOnce(&MixingGraph::Create),
+ std::move(create_stream_callback));
+}
+
+OutputDeviceMixer::OutputDeviceMixer(const std::string& device_id)
+ : device_id_(device_id) {}
+
+} // namespace audio
diff --git a/chromium/services/audio/output_device_mixer.h b/chromium/services/audio/output_device_mixer.h
new file mode 100644
index 00000000000..b83959102a0
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer.h
@@ -0,0 +1,83 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_H_
+#define SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/task/single_thread_task_runner.h"
+#include "media/base/audio_parameters.h"
+#include "services/audio/reference_output.h"
+
+namespace media {
+class AudioOutputStream;
+}
+
+namespace audio {
+
+// Manages mixing and rendering of all audio outputs going to a specific output
+// device. As ReferenceOutput provides to Listeners an ability to listen to the
+// audio mix being rendered. If there is at least one listener connected, the
+// mixer is mixing all the audio output and rendering the mix as a single audio
+// output stream. Otherwise the streams are rendered independently.
+class OutputDeviceMixer : public ReferenceOutput {
+ public:
+ // Callback to be used by OutputDeviceMixer to create actual output streams
+ // playing audio.
+ using CreateStreamCallback =
+ base::RepeatingCallback<media::AudioOutputStream*(
+ const std::string& device_id,
+ const media::AudioParameters& params)>;
+
+ // A helper class for the clients to pass OutputDeviceMixer::Create around as
+ // a callback.
+ using CreateCallback =
+ base::RepeatingCallback<std::unique_ptr<OutputDeviceMixer>(
+ const std::string& device_id,
+ const media::AudioParameters& output_params,
+ CreateStreamCallback create_stream_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)>;
+
+ // Creates OutputDeviceMixer which manages playback to the device identified
+ // by |device_id|. |output_params| - parameters for the audio mix playback;
+ // |create_stream_callback| will be used by OutputDeviceMixer to create output
+ // streams playing audio; |task_runner| is the main task runner of
+ // OutputDeviceMixer.
+ static std::unique_ptr<OutputDeviceMixer> Create(
+ const std::string& device_id,
+ const media::AudioParameters& output_params,
+ CreateStreamCallback create_stream_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ // |device_id| is the id of the output device to manage the playback to.
+ explicit OutputDeviceMixer(const std::string& device_id);
+
+ OutputDeviceMixer(const OutputDeviceMixer&) = delete;
+ OutputDeviceMixer& operator=(const OutputDeviceMixer&) = delete;
+
+ // Id of the device audio output to which is managed by OutputDeviceMixer.
+ const std::string& device_id() const { return device_id_; }
+
+ // Creates an audio output stream managed by the given OutputDeviceMixer.
+ // |params| - output stream parameters; |on_device_change_callback| - callback
+ // to notify the AudioOutputStream client about device change events observed
+ // by OutputDeviceMixer.
+ virtual media::AudioOutputStream* MakeMixableStream(
+ const media::AudioParameters& params,
+ base::OnceCallback<void()> on_device_change_callback) = 0;
+
+ // Notify OutputDeviceMixer about the device change event.
+ virtual void ProcessDeviceChange() = 0;
+
+ private:
+ // Id of the device output to which is managed by the mixer.
+ const std::string device_id_;
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_H_
diff --git a/chromium/services/audio/output_device_mixer_impl.cc b/chromium/services/audio/output_device_mixer_impl.cc
new file mode 100644
index 00000000000..b3323330298
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer_impl.cc
@@ -0,0 +1,867 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/output_device_mixer_impl.h"
+
+#include "base/check.h"
+#include "base/containers/contains.h"
+#include "base/dcheck_is_on.h"
+#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+#include "base/trace_event/trace_event.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_io.h"
+
+namespace audio {
+
+constexpr base::TimeDelta OutputDeviceMixerImpl::kSwitchToUnmixedPlaybackDelay;
+constexpr double OutputDeviceMixerImpl::kDefaultVolume;
+
+namespace {
+
+const char* LatencyToUmaSuffix(media::AudioLatency::LatencyType latency) {
+ switch (latency) {
+ case media::AudioLatency::LATENCY_EXACT_MS:
+ return "LatencyExactMs";
+ case media::AudioLatency::LATENCY_INTERACTIVE:
+ return "LatencyInteractive";
+ case media::AudioLatency::LATENCY_RTC:
+ return "LatencyRtc";
+ case media::AudioLatency::LATENCY_PLAYBACK:
+ return "LatencyPlayback";
+ default:
+ return "LatencyUnknown";
+ }
+}
+
+const char* DeviceIdToUmaSuffix(const std::string& device_id) {
+ if (device_id == "")
+ return ".Default";
+ return ".NonDefault";
+}
+
+// Do not change: used for UMA reporting, matches
+// AudioOutputDeviceMixerStreamStatus from enums.xml.
+enum class TrackError {
+ kNone = 0,
+ kIndependentOpenFailed,
+ kIndependentPlaybackFailed,
+ kMixedOpenFailed,
+ kMixedPlaybackFailed,
+ kMaxValue = kMixedPlaybackFailed
+};
+
+const char* TrackErrorToString(TrackError error) {
+ switch (error) {
+ case TrackError::kIndependentOpenFailed:
+ return "Failed to open independent rendering stream";
+ case TrackError::kIndependentPlaybackFailed:
+ return "Error during independent playback";
+ case TrackError::kMixedOpenFailed:
+ return "Failed to open mixing rendering stream";
+ case TrackError::kMixedPlaybackFailed:
+ return "Error during mixed playback";
+ default:
+ NOTREACHED();
+ return "No error";
+ }
+}
+
+} // namespace
+
+// Audio data flow though the mixer:
+//
+// * Independent (ummixed) audio stream playback:
+// MixTrack::|audio_source_callback_|
+// -> MixTrack::|rendering_stream_|.
+//
+// * Mixed playback:
+// MixTrack::|audio_source_callback_|
+// -> MixTrack::|graph_input_|
+// --> OutputDeviceMixerImpl::|mixing_graph_|
+// ---> OutputDeviceMixerImpl::|mixing_graph_rendering_stream_|
+
+// Helper class which stores all the data associated with a specific audio
+// output managed by the mixer. To the clients such an audio output is
+// represented as MixableOutputStream (below).
+class OutputDeviceMixerImpl::MixTrack final
+ : public media::AudioOutputStream::AudioSourceCallback {
+ public:
+ MixTrack(OutputDeviceMixerImpl* mixer,
+ std::unique_ptr<MixingGraph::Input> graph_input,
+ base::OnceClosure on_device_change_callback)
+ : mixer_(mixer),
+ on_device_change_callback_(std::move(on_device_change_callback)),
+ graph_input_(std::move(graph_input)) {}
+
+ ~MixTrack() final {
+ DCHECK(!audio_source_callback_);
+ base::UmaHistogramEnumeration(
+ "Media.Audio.OutputDeviceMixer.StreamPlaybackStatus", error_);
+ }
+
+ void SetSource(
+ media::AudioOutputStream::AudioSourceCallback* audio_source_callback) {
+ DCHECK(!audio_source_callback_ || !audio_source_callback);
+ audio_source_callback_ = audio_source_callback;
+ }
+
+ void SetVolume(double volume) {
+ volume_ = volume;
+ graph_input_->SetVolume(volume);
+ if (rendering_stream_)
+ rendering_stream_->SetVolume(volume);
+ }
+
+ double GetVolume() const { return volume_; }
+
+ void StartProvidingAudioToMixingGraph() {
+ DCHECK(audio_source_callback_);
+ RegisterPlaybackStarted();
+ graph_input_->Start(audio_source_callback_);
+ }
+
+ void StopProvidingAudioToMixingGraph() {
+ DCHECK(audio_source_callback_);
+ graph_input_->Stop();
+ RegisterPlaybackStopped(PlaybackType::kMixed);
+ }
+
+ void StartIndependentRenderingStream() {
+ DCHECK(audio_source_callback_);
+ if (!rendering_stream_) {
+ // Open the rendering stream if it's not open yet. It will be closed in
+ // CloseIndependentRenderingStream() or during destruction.
+ rendering_stream_.reset(
+ mixer_->CreateAndOpenDeviceStream(graph_input_->GetParams()));
+
+ if (!rendering_stream_) {
+ ReportError(TrackError::kIndependentOpenFailed);
+ return;
+ }
+ rendering_stream_->SetVolume(volume_);
+ }
+
+ RegisterPlaybackStarted();
+ rendering_stream_->Start(this);
+ }
+
+ void StopIndependentRenderingStream() {
+ DCHECK(audio_source_callback_);
+ if (rendering_stream_) {
+ rendering_stream_->Stop();
+ RegisterPlaybackStopped(PlaybackType::kIndependent);
+ }
+ }
+
+ void CloseIndependentRenderingStream() {
+ DCHECK(!audio_source_callback_);
+ // Closes the stream.
+ rendering_stream_.reset();
+ }
+
+ void ReportError(TrackError error) {
+ DCHECK(audio_source_callback_);
+ DCHECK_NE(error, TrackError::kNone);
+ LOG(ERROR) << "MixableOutputStream: " << TrackErrorToString(error);
+ error_ = error;
+ audio_source_callback_->OnError(ErrorType::kUnknown);
+ }
+
+ void OnDeviceChange() {
+ DCHECK(!on_device_change_callback_.is_null());
+ std::move(on_device_change_callback_).Run();
+ }
+
+ private:
+ enum class PlaybackType { kMixed, kIndependent };
+
+ void RegisterPlaybackStarted() {
+ DCHECK(playback_activation_time_for_uma_.is_null());
+ playback_activation_time_for_uma_ = base::TimeTicks::Now();
+ }
+
+ void RegisterPlaybackStopped(PlaybackType playback_type) {
+ if (playback_type == PlaybackType::kIndependent &&
+ playback_activation_time_for_uma_.is_null()) {
+ return; // Stop() for an independent stream can be called multiple times.
+ }
+ DCHECK(!playback_activation_time_for_uma_.is_null());
+
+ base::UmaHistogramLongTimes(
+ base::StrCat(
+ {"Media.Audio.OutputDeviceMixer.StreamDuration.",
+ ((playback_type == PlaybackType::kMixed) ? "Mixed." : "Unmixed."),
+ LatencyToUmaSuffix(graph_input_->GetParams().latency_tag())}),
+ base::TimeTicks::Now() - playback_activation_time_for_uma_);
+ playback_activation_time_for_uma_ = base::TimeTicks();
+ }
+
+ // media::AudioOutputStream::AudioSourceCallback implementation to intercept
+ // error reporting during independent playback.
+ int OnMoreData(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest) final {
+ DCHECK(audio_source_callback_);
+ return audio_source_callback_->OnMoreData(delay, delay_timestamp,
+ prior_frames_skipped, dest);
+ }
+
+ void OnError(ErrorType type) final {
+ // Device change events are intercepted by the underlying physical streams.
+ DCHECK_EQ(type, ErrorType::kUnknown);
+ ReportError(TrackError::kIndependentPlaybackFailed);
+ }
+
+ double volume_ = kDefaultVolume;
+
+ const raw_ptr<OutputDeviceMixerImpl> mixer_;
+
+ // Callback to notify the audio output client of the device change. Note that
+ // all the device change events are initially routed to MixerManager which
+ // does the centralized processing and notifies each mixer via
+ // OutputDeviceMixer::ProcessDeviceChange(). There OutputDeviceMixerImpl does
+ // the cleanup and then dispatches the device change event to all its clients
+ // via |on_device_change_callback_| of its MixTracks.
+ base::OnceClosure on_device_change_callback_;
+
+ // Callback to request the audio output data from the client.
+ raw_ptr<media::AudioOutputStream::AudioSourceCallback>
+ audio_source_callback_ = nullptr;
+
+ // Delivers the audio output into MixingGraph, to be mixed for the reference
+ // signal playback.
+ const std::unique_ptr<MixingGraph::Input> graph_input_;
+
+ // When non-nullptr, points to an open physical output stream used to render
+ // the audio output independently when mixing is not required.
+ std::unique_ptr<media::AudioOutputStream, StreamAutoClose> rendering_stream_ =
+ nullptr;
+
+ base::TimeTicks playback_activation_time_for_uma_;
+
+ TrackError error_ = TrackError::kNone;
+};
+
+// A proxy which represents MixTrack as media::AudioOutputStream.
+class OutputDeviceMixerImpl::MixableOutputStream final
+ : public media::AudioOutputStream {
+ public:
+ MixableOutputStream(base::WeakPtr<OutputDeviceMixerImpl> mixer,
+ MixTrack* mix_track)
+ : mixer_(std::move(mixer)), mix_track_(mix_track) {}
+
+ MixableOutputStream(const MixableOutputStream&) = delete;
+ MixableOutputStream& operator=(const MixableOutputStream&) = delete;
+
+ ~MixableOutputStream() final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ }
+
+ // AudioOutputStream interface.
+ bool Open() final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (!mixer_) {
+ LOG(ERROR) << "Stream start failed: device changed";
+ return false;
+ }
+
+ // No-op: required resources are determened when the stream starts playing.
+ return true;
+ }
+
+ void Start(AudioSourceCallback* callback) final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(callback);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ TRACE_DISABLED_BY_DEFAULT("audio"), "MixableOutputStream::IsPlaying",
+ this, "device_id", mixer_ ? mixer_->device_id() : "device changed");
+ if (!mixer_) {
+ LOG(ERROR) << "Stream start failed: device changed";
+ callback->OnError(ErrorType::kDeviceChange);
+ return;
+ }
+ mixer_->StartStream(mix_track_, callback);
+ }
+
+ void Stop() final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ TRACE_EVENT_NESTABLE_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "MixableOutputStream::IsPlaying", this);
+ if (!mixer_)
+ return;
+ mixer_->StopStream(mix_track_);
+ }
+
+ void SetVolume(double volume) final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (!mixer_)
+ return;
+ mix_track_->SetVolume(volume);
+ }
+
+ void GetVolume(double* volume) final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(volume);
+ if (!mixer_)
+ return;
+ *volume = mix_track_->GetVolume();
+ }
+
+ void Close() final {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (mixer_) {
+ mixer_->CloseStream(mix_track_);
+ }
+
+ // To match the typical usage pattern of AudioOutputStream.
+ delete this;
+ }
+
+ void Flush() final {}
+
+ private:
+ SEQUENCE_CHECKER(owning_sequence_);
+ // OutputDeviceMixerImpl will release all the resources and invalidate its
+ // weak pointers in OutputDeviceMixer::ProcessDeviceChange(). After that
+ // MixableOutputStream becomes a no-op.
+ base::WeakPtr<OutputDeviceMixerImpl> const mixer_
+ GUARDED_BY_CONTEXT(owning_sequence_);
+ const raw_ptr<MixTrack> mix_track_; // Valid only when |mixer_| is valid.
+};
+
+// Logs mixing statistics upon the destruction. Should be created when mixing
+// playback starts, and destroyed when it ends.
+class OutputDeviceMixerImpl::MixingStats {
+ public:
+ MixingStats(const std::string& device_id,
+ int active_track_count,
+ int listener_count)
+ : suffix_(DeviceIdToUmaSuffix(device_id)),
+ active_track_count_(active_track_count),
+ listener_count_(listener_count),
+ start_(base::TimeTicks::Now()) {
+ DCHECK_GT(active_track_count, 0);
+ DCHECK_GT(listener_count, 0);
+ }
+
+ ~MixingStats() {
+ if (!noop_mixing_start_.is_null()) {
+ LogNoopMixingDuration();
+ }
+
+ DCHECK(!start_.is_null());
+ base::TimeDelta duration = base::TimeTicks::Now() - start_;
+ LogPerDeviceUma(duration, suffix_);
+ LogPerDeviceUma(duration, ""); // Combined.
+ }
+
+ void AddListener() { listener_count_.Increment(); }
+
+ void RemoveListener() { listener_count_.Decrement(); }
+
+ void AddActiveTrack() {
+ active_track_count_.Increment();
+ if (!noop_mixing_start_.is_null()) {
+ // First track after a period of feeding silence to the listeners.
+ DCHECK_EQ(active_track_count_.GetCurrent(), 1);
+ DCHECK(listener_count_.GetCurrent());
+ LogNoopMixingDuration();
+ }
+ }
+
+ void RemoveActiveTrack() {
+ active_track_count_.Decrement();
+ if (listener_count_.GetCurrent() && !active_track_count_.GetCurrent()) {
+ // No more tracks, so we start feeding silence to listeners.
+ DCHECK(noop_mixing_start_.is_null());
+ noop_mixing_start_ = base::TimeTicks::Now();
+ }
+ }
+
+ private:
+ // A helper to track the max value.
+ class MaxTracker {
+ public:
+ explicit MaxTracker(int value) : value_(value), max_value_(value) {}
+ int GetCurrent() { return value_; }
+ int GetMax() { return max_value_; }
+ void Increment() {
+ if (++value_ > max_value_)
+ max_value_ = value_;
+ }
+ void Decrement() {
+ DCHECK(value_ > 0);
+ value_--;
+ }
+
+ private:
+ int value_;
+ int max_value_;
+ };
+
+ void LogNoopMixingDuration() {
+ DCHECK(!noop_mixing_start_.is_null());
+ base::UmaHistogramLongTimes(
+ "Media.Audio.OutputDeviceMixer.NoopMixingDuration",
+ base::TimeTicks::Now() - noop_mixing_start_);
+ noop_mixing_start_ = base::TimeTicks();
+ }
+
+ void LogPerDeviceUma(base::TimeDelta duration, const char* suffix) {
+ constexpr int kMaxActiveStreamCount = 50;
+ constexpr int kMaxListeners = 20;
+
+ base::UmaHistogramLongTimes(
+ base::StrCat({"Media.Audio.OutputDeviceMixer.MixingDuration", suffix}),
+ duration);
+ base::UmaHistogramExactLinear(
+ base::StrCat(
+ {"Media.Audio.OutputDeviceMixer.MaxMixedStreamCount", suffix}),
+ active_track_count_.GetMax(), kMaxActiveStreamCount);
+ base::UmaHistogramExactLinear(
+ base::StrCat(
+ {"Media.Audio.OutputDeviceMixer.MaxListenerCount", suffix}),
+ listener_count_.GetMax(), kMaxListeners);
+ }
+
+ const char* const suffix_;
+ MaxTracker active_track_count_;
+ MaxTracker listener_count_;
+ const base::TimeTicks start_;
+
+ // Start of the period when there are no active tracks and we play and feed
+ // silence to the listeners.
+ base::TimeTicks noop_mixing_start_;
+};
+
+OutputDeviceMixerImpl::OutputDeviceMixerImpl(
+ const std::string& device_id,
+ const media::AudioParameters& output_params,
+ MixingGraph::CreateCallback create_mixing_graph_callback,
+ CreateStreamCallback create_stream_callback)
+ : OutputDeviceMixer(device_id),
+ create_stream_callback_(std::move(create_stream_callback)),
+ mixing_graph_output_params_(output_params),
+ mixing_graph_(std::move(create_mixing_graph_callback)
+ .Run(output_params,
+ base::BindRepeating(
+ &OutputDeviceMixerImpl::BroadcastToListeners,
+ base::Unretained(this)),
+ base::BindRepeating(
+ &OutputDeviceMixerImpl::OnMixingGraphError,
+ base::Unretained(this)))) {
+ DCHECK(mixing_graph_output_params_.IsValid());
+ DCHECK_EQ(mixing_graph_output_params_.format(),
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl", this, "device_id",
+ device_id);
+}
+
+OutputDeviceMixerImpl::~OutputDeviceMixerImpl() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(!active_tracks_.size());
+ DCHECK(!HasListeners());
+ DCHECK(!mixing_graph_output_stream_);
+
+ TRACE_EVENT_NESTABLE_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl", this);
+}
+
+media::AudioOutputStream* OutputDeviceMixerImpl::MakeMixableStream(
+ const media::AudioParameters& params,
+ base::OnceClosure on_device_change_callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+ if (!(params.IsValid() &&
+ params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY)) {
+ LOG(ERROR) << "Invalid output stream patameters for device [" << device_id()
+ << "], parameters: " << params.AsHumanReadableString();
+ return nullptr;
+ }
+
+ auto mix_track =
+ std::make_unique<MixTrack>(this, mixing_graph_->CreateInput(params),
+ std::move(on_device_change_callback));
+
+ media::AudioOutputStream* mixable_stream =
+ new MixableOutputStream(weak_factory_.GetWeakPtr(), mix_track.get());
+ mix_tracks_.insert(std::move(mix_track));
+ return mixable_stream;
+}
+
+void OutputDeviceMixerImpl::ProcessDeviceChange() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+ device_changed_ = true;
+#endif
+
+ // Make all MixableOutputStream instances no-op.
+ weak_factory_.InvalidateWeakPtrs();
+
+ // Stop and close all audio playback.
+ if (mixing_graph_output_stream_) {
+ StopMixingGraphPlayback(MixingError::kNone);
+ } else {
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->StopIndependentRenderingStream();
+ }
+
+ // For consistency.
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->SetSource(nullptr);
+
+ active_tracks_.clear();
+
+ // Close independent rendering streams: the clients will want to restore
+ // active playback in mix_track->OnDeviceChange() calls below; we don't want
+ // to exceed the limit of simultaneously open output streams when they do so.
+ for (auto&& mix_track : mix_tracks_)
+ mix_track->CloseIndependentRenderingStream();
+
+ {
+ base::AutoLock scoped_lock(listener_lock_);
+ listeners_.clear();
+ }
+
+ // Notify MixableOutputStream users of the device change. Normally they should
+ // close the current stream they are holding to, create/open a new one and
+ // resume the playback. We already released all the resources; closing a
+ // MixableOutputStream will be a no-op since weak pointers to |this| have just
+ // been invalidated.
+ for (auto&& mix_track : mix_tracks_)
+ mix_track->OnDeviceChange();
+}
+
+void OutputDeviceMixerImpl::StartListening(Listener* listener) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+#endif
+ DVLOG(1) << "Reference output listener added for device [" << device_id()
+ << "]";
+
+ // A new listener came: cancel scheduled switch to independent playback.
+ switch_to_unmixed_playback_delay_timer_.Stop();
+ {
+ base::AutoLock scoped_lock(listener_lock_);
+ DCHECK(listeners_.find(listener) == listeners_.end());
+ listeners_.insert(listener);
+ if (mixing_stats_) {
+ DCHECK(mixing_graph_output_stream_); // We are mixing.
+ mixing_stats_->AddListener();
+ }
+ }
+ if (!mixing_graph_output_stream_ && active_tracks_.size()) {
+ // Start reference playback only if at least one audio stream is playing.
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->StopIndependentRenderingStream();
+ StartMixingGraphPlayback();
+ // Note that if StartMixingGraphPlayback() failed, no audio will be playing
+ // and each client of a playing MixableOutputStream will receive OnError()
+ // callback call.
+ }
+}
+
+void OutputDeviceMixerImpl::StopListening(Listener* listener) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+#endif
+ DVLOG(1) << "Reference output listener removed for device [" << device_id()
+ << "]";
+ {
+ base::AutoLock scoped_lock(listener_lock_);
+ auto iter = listeners_.find(listener);
+ DCHECK(iter != listeners_.end());
+ listeners_.erase(iter);
+ }
+
+ if (mixing_stats_) {
+ DCHECK(mixing_graph_output_stream_); // We are mixing.
+ mixing_stats_->RemoveListener();
+ }
+
+ if (HasListeners()) {
+ // We still have some listeners left, so no need to switch to independent
+ // playback.
+ return;
+ }
+
+ if (!mixing_graph_output_stream_)
+ return;
+
+ // Mixing graph playback is ongoing.
+
+ if (!active_tracks_.size()) {
+ // There is no actual playback: we were just sending silence to the
+ // listener as a reference.
+ StopMixingGraphPlayback(MixingError::kNone);
+ } else {
+ // No listeners left, and we are playing via the mixing graph. Schedule
+ // switching to independent playback.
+ switch_to_unmixed_playback_delay_timer_.Start(
+ FROM_HERE, kSwitchToUnmixedPlaybackDelay, this,
+ &OutputDeviceMixerImpl::SwitchToUnmixedPlaybackTimerHelper);
+ }
+}
+
+void OutputDeviceMixerImpl::StartStream(
+ MixTrack* mix_track,
+ media::AudioOutputStream::AudioSourceCallback* callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+#endif
+ DCHECK(mix_track);
+ DCHECK(callback);
+ DCHECK(!base::Contains(active_tracks_, mix_track));
+
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl::StartStream", "device_id", device_id(),
+ "mix_track", static_cast<void*>(mix_track));
+
+ mix_track->SetSource(callback);
+ active_tracks_.emplace(mix_track);
+
+ if (mixing_graph_output_stream_) {
+ // We are playing all audio as a |mixing_graph_| output.
+ mix_track->StartProvidingAudioToMixingGraph();
+ DCHECK(mixing_stats_);
+ mixing_stats_->AddActiveTrack();
+ } else if (HasListeners()) {
+ // Either we are starting the first active stream, or the previous switch to
+ // playing via the mixing graph failed because the its output stream failed
+ // to open. In any case, none of the active streams are playing individually
+ // at this point.
+ StartMixingGraphPlayback();
+ } else {
+ // No reference signal is requested.
+ mix_track->StartIndependentRenderingStream();
+ }
+}
+
+void OutputDeviceMixerImpl::StopStream(MixTrack* mix_track) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+#endif
+ DCHECK(mix_track);
+ if (!base::Contains(active_tracks_, mix_track)) {
+ // MixableOutputStream::Stop() can be called multiple times, even if the
+ // stream has not been started. See media::AudioOutputStream documentation.
+ return;
+ }
+
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl::StopStream", "device_id", device_id(),
+ "mix_track", static_cast<void*>(mix_track));
+
+ active_tracks_.erase(mix_track);
+
+ if (mixing_graph_output_stream_) {
+ // We are playing all audio a |mixing_graph_| output.
+ mix_track->StopProvidingAudioToMixingGraph();
+ DCHECK(mixing_stats_);
+ mixing_stats_->RemoveActiveTrack();
+
+ // Note: we do not stop the reference playback even if there are no active
+ // mix members. This way the echo canceller will be in a consistent state
+ // when the playback is activated again. Drawback: we keep playing silent
+ // audio. An example would some occasional notification sounds and no other
+ // audio output: we start the mixing playback at the first notification, and
+ // stop it only when the echo cancellation session is finished (i.e. all the
+ // listeners are gone).
+ } else {
+ mix_track->StopIndependentRenderingStream();
+ }
+ mix_track->SetSource(nullptr);
+}
+
+void OutputDeviceMixerImpl::CloseStream(MixTrack* mix_track) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+#endif
+ DCHECK(mix_track);
+ DCHECK(!base::Contains(active_tracks_, mix_track));
+
+ auto iter = mix_tracks_.find(mix_track);
+ DCHECK(iter != mix_tracks_.end());
+
+ mix_tracks_.erase(iter);
+}
+
+media::AudioOutputStream* OutputDeviceMixerImpl::CreateAndOpenDeviceStream(
+ const media::AudioParameters& params) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(params.IsValid());
+ DCHECK_EQ(params.format(), media::AudioParameters::AUDIO_PCM_LOW_LATENCY);
+
+ media::AudioOutputStream* stream =
+ create_stream_callback_.Run(device_id(), params);
+ if (!stream)
+ return nullptr;
+
+ if (!stream->Open()) {
+ LOG(ERROR) << "Failed to open stream";
+ stream->Close();
+ return nullptr;
+ }
+
+ return stream;
+}
+
+void OutputDeviceMixerImpl::BroadcastToListeners(
+ const media::AudioBus& audio_bus,
+ base::TimeDelta delay) {
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl::BroadcastToListeners", "delay ms",
+ delay.InMilliseconds());
+
+ base::AutoLock scoped_lock(listener_lock_);
+ for (Listener* listener : listeners_) {
+ listener->OnPlayoutData(audio_bus,
+ mixing_graph_output_params_.sample_rate(), delay);
+ }
+}
+
+// Processes errors coming from |mixing_graph_| during mixed playback.
+void OutputDeviceMixerImpl::OnMixingGraphError(ErrorType error) {
+ // |mixing_graph_output_stream_| guarantees this.
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ // Device change events are intercepted by the underlying physical stream.
+ DCHECK_EQ(error, ErrorType::kUnknown);
+ // This call is expected only during mixed playback.
+ DCHECK(mixing_graph_output_stream_);
+
+ StopMixingGraphPlayback(MixingError::kPlaybackFailed);
+}
+
+bool OutputDeviceMixerImpl::HasListeners() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ return TS_UNCHECKED_READ(listeners_).size();
+}
+
+void OutputDeviceMixerImpl::StartMixingGraphPlayback() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(!mixing_graph_output_stream_);
+
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl mixing", this,
+ "device_id", device_id());
+
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl::StartMixingGraphPlayback", "device_id",
+ device_id());
+
+ // Unlike output streams for individual rendering, we create and open the
+ // mixing output stream each time we are about to start playing audio via the
+ // mixing graph, to provide the reference signal to the listeners; and stop
+ // and close it when the reference playback is not needed any more - just for
+ // simplicity. |switch_to_unmixed_playback_delay_timer_| helps to avoid
+ // situations when we recreate the stream immediately; also the physical
+ // stream is managed by media::AudioOutputDispatcher which optimizes reopening
+ // of an output device if it happens soon after it was closed, and starting
+ // such a stream after a period of inactivity is the same as
+ // recreating/opening/starting it.
+ mixing_graph_output_stream_.reset(
+ CreateAndOpenDeviceStream(mixing_graph_output_params_));
+ if (!mixing_graph_output_stream_) {
+ StopMixingGraphPlayback(MixingError::kOpenFailed);
+ return;
+ }
+
+ DCHECK(!mixing_stats_);
+ mixing_stats_ = std::make_unique<MixingStats>(
+ device_id(), active_tracks_.size(), TS_UNCHECKED_READ(listeners_).size());
+
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->StartProvidingAudioToMixingGraph();
+
+ mixing_graph_output_stream_->Start(mixing_graph_.get());
+
+ DVLOG(1) << " Mixing started for device [" << device_id() << "]";
+}
+
+void OutputDeviceMixerImpl::StopMixingGraphPlayback(MixingError error) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ if (mixing_graph_output_stream_) {
+ // Mixing was in progress, we should stop it.
+ DCHECK_NE(error, MixingError::kOpenFailed);
+
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl::StopMixingGraphPlayback", "device_id",
+ device_id());
+
+ switch_to_unmixed_playback_delay_timer_.Stop();
+
+ mixing_graph_output_stream_->Stop();
+ mixing_graph_output_stream_.reset(); // Auto-close the stream.
+
+ DCHECK(mixing_stats_);
+ mixing_stats_.reset();
+
+ DVLOG(1) << " Mixing stopped for device [" << device_id() << "]";
+
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->StopProvidingAudioToMixingGraph();
+
+ TRACE_EVENT_NESTABLE_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerImpl mixing", this);
+ }
+
+ DCHECK(!mixing_graph_output_stream_);
+
+ if (error != MixingError::kNone) {
+ LOG(ERROR) << ErrorToString(error) << " for device [" << device_id() << "]";
+ TrackError track_error = (error == MixingError::kOpenFailed)
+ ? TrackError::kMixedOpenFailed
+ : TrackError::kMixedPlaybackFailed;
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->ReportError(track_error);
+ }
+
+ base::UmaHistogramEnumeration(
+ "Media.Audio.OutputDeviceMixer.MixedPlaybackStatus", error);
+}
+
+void OutputDeviceMixerImpl::SwitchToUnmixedPlaybackTimerHelper() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ NON_REENTRANT_SCOPE(reentrancy_checker_);
+ DCHECK(mixing_graph_output_stream_);
+#if DCHECK_IS_ON()
+ DCHECK(!device_changed_);
+#endif
+ StopMixingGraphPlayback(MixingError::kNone);
+ for (MixTrack* mix_track : active_tracks_)
+ mix_track->StartIndependentRenderingStream();
+}
+
+// static
+const char* OutputDeviceMixerImpl::ErrorToString(MixingError error) {
+ switch (error) {
+ case MixingError::kOpenFailed:
+ return "Failed to open mixing rendering stream";
+ case MixingError::kPlaybackFailed:
+ return "Error during mixed playback";
+ default:
+ NOTREACHED();
+ return "No error";
+ }
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/output_device_mixer_impl.h b/chromium/services/audio/output_device_mixer_impl.h
new file mode 100644
index 00000000000..317efe8759a
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer_impl.h
@@ -0,0 +1,184 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_IMPL_H_
+#define SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_IMPL_H_
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "base/callback.h"
+#include "base/check.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/dcheck_is_on.h"
+#include "base/synchronization/lock.h"
+#include "base/timer/timer.h"
+#include "media/audio/audio_io.h"
+#include "media/base/audio_parameters.h"
+#include "media/base/reentrancy_checker.h"
+#include "services/audio/mixing_graph.h"
+#include "services/audio/output_device_mixer.h"
+
+namespace audio {
+class MixingGraph;
+
+// OutputDeviceMixerImpl manages the rendering of all output streams created by
+// MakeMixableStream(). It has two rendering modes: if there
+// are not listeners attached, each active output stream is rendered
+// independently. If the mixer has listeners and at least one of the managed
+// streams there is playing, all output streams are mixed by
+// |mixing_graph_| and the result is played by |mixing_graph_output_stream_|.
+// After mixing started, the mixed playback will stop only when the last
+// listener is gone; this means the mixed playback will continue even when there
+// are no managed streams playing. That is done because the listeners do not
+// like when the reference signal stops and then starts again: it can cause
+// reference signal delay jumps. TODO(olka): add metrics for how often/how long
+// we may have listeners forsing such silent mixed playback.
+class OutputDeviceMixerImpl final : public OutputDeviceMixer {
+ public:
+ using ErrorType = media::AudioOutputStream::AudioSourceCallback::ErrorType;
+
+ static constexpr base::TimeDelta kSwitchToUnmixedPlaybackDelay =
+ base::Seconds(1);
+
+ static constexpr double kDefaultVolume = 1.0;
+
+ // |device_id| is the id of the device to manage the playback for (expected to
+ // be a valid physical output device id); |output_params| are the parameters
+ // of the audio mix the mixer will be playing in case there are listeners
+ // attached (otherwise, each output stream is played independently using its
+ // individual parameters); |create_mixing_graph_callback| is used to create
+ // a mixing graph object which will combine individual audio streams into a
+ // mixed signal; |create_stream_callback| is used to create physical output
+ // streams to be used for audio rendering.
+ OutputDeviceMixerImpl(
+ const std::string& device_id,
+ const media::AudioParameters& output_params,
+ MixingGraph::CreateCallback create_mixing_graph_callback,
+ CreateStreamCallback create_stream_callback);
+ OutputDeviceMixerImpl(const OutputDeviceMixerImpl&) = delete;
+ OutputDeviceMixerImpl& operator=(const OutputDeviceMixerImpl&) = delete;
+ ~OutputDeviceMixerImpl() final;
+
+ // Creates an output stream managed by |this|.
+ media::AudioOutputStream* MakeMixableStream(
+ const media::AudioParameters& params,
+ base::OnceCallback<void()> on_device_change_callback) final;
+
+ void ProcessDeviceChange() final;
+
+ // ReferenceOutput implementation.
+ // Starts listening to the mixed audio stream.
+ void StartListening(Listener* listener) final;
+ // Stops listening to the mixed audio stream.
+ void StopListening(Listener* listener) final;
+
+ private:
+ class MixTrack;
+ class MixableOutputStream;
+ class MixingStats;
+
+ struct StreamAutoClose {
+ void operator()(media::AudioOutputStream* stream) {
+ if (!stream)
+ return;
+ stream->Close();
+ stream = nullptr;
+ }
+ };
+
+ // Do not change: used for UMA reporting, matches
+ // AudioOutputDeviceMixerMixedPlaybackStatus from enums.xml.
+ enum class MixingError {
+ kNone = 0,
+ kOpenFailed,
+ kPlaybackFailed,
+ kMaxValue = kPlaybackFailed
+ };
+
+ using MixTracks =
+ std::set<std::unique_ptr<MixTrack>, base::UniquePtrComparator>;
+ using ActiveTracks = std::set<MixTrack*>;
+ using Listeners = std::set<Listener*>;
+
+ // Operations delegated by MixableOutputStream.
+ void StartStream(MixTrack* mix_track,
+ media::AudioOutputStream::AudioSourceCallback* callback);
+ void StopStream(MixTrack* mix_track);
+ void CloseStream(MixTrack* mix_track);
+
+ // Helper to create physical audio streams.
+ media::AudioOutputStream* CreateAndOpenDeviceStream(
+ const media::AudioParameters& params);
+
+ // Delivers audio to listeners; provided as a callback to MixingGraph.
+ void BroadcastToListeners(const media::AudioBus& audio_bus,
+ base::TimeDelta delay);
+ // Processes |mixing_output_stream_| rendering errors; provided as a callback
+ // to MixingGraph.
+ void OnMixingGraphError(ErrorType error);
+
+ // Helpers to manage audio playback.
+ bool HasListeners() const;
+ void StartMixingGraphPlayback();
+ void StopMixingGraphPlayback(MixingError mixing_error);
+ void SwitchToUnmixedPlaybackTimerHelper();
+
+ static const char* ErrorToString(MixingError error);
+
+ SEQUENCE_CHECKER(owning_sequence_);
+
+ // Callback to create physical audio streams.
+ const CreateStreamCallback create_stream_callback_;
+
+ // Streams managed by the mixer.
+ MixTracks mix_tracks_ GUARDED_BY_CONTEXT(owning_sequence_);
+
+ // Active tracks rendering audio.
+ ActiveTracks active_tracks_ GUARDED_BY_CONTEXT(owning_sequence_);
+
+ // Listeners receiving the reference output (mixed playback). Playback is
+ // mixed if and only if there is at least one listener.
+ mutable base::Lock listener_lock_;
+ Listeners listeners_ GUARDED_BY(listener_lock_);
+
+ // Audio parameters for mixed playback.
+ const media::AudioParameters mixing_graph_output_params_;
+
+ // Provides the audio mix combined of |active_members_| audio to
+ // |mixing_output_stream_| for playback.
+ const std::unique_ptr<MixingGraph> mixing_graph_
+ GUARDED_BY_CONTEXT(owning_sequence_);
+
+ // Stream to render the audio mix. Non-null if and only if the playback is
+ // being mixed at the moment.
+ std::unique_ptr<media::AudioOutputStream, StreamAutoClose>
+ mixing_graph_output_stream_ GUARDED_BY_CONTEXT(owning_sequence_);
+
+ // Delays switching to unmixed playback in case a new listener is coming
+ // soon (within kSwitchToIndependentPlaybackDelay).
+ base::OneShotTimer switch_to_unmixed_playback_delay_timer_;
+
+ // Non-null when the playback is being mixed. Collects mixing statistics.
+ // Logs them upon the destruction when mixing stops.
+ std::unique_ptr<MixingStats> mixing_stats_;
+
+#if DCHECK_IS_ON()
+ bool device_changed_ = false;
+#endif
+
+ // A mixable stream operation cannot be invoked within a context of another
+ // such operation. In practice it means that AudioOutputStream created by the
+ // mixer cannot be stopped/closed synchronously from AudioSourceCallback
+ // provided to it on AudioOutputStream::Start().
+ REENTRANCY_CHECKER(reentrancy_checker_);
+
+ // Supplies weak pointers to |this| for MixableOutputStream instances.
+ base::WeakPtrFactory<OutputDeviceMixerImpl> weak_factory_{this};
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_IMPL_H_
diff --git a/chromium/services/audio/output_device_mixer_impl_unittest.cc b/chromium/services/audio/output_device_mixer_impl_unittest.cc
new file mode 100644
index 00000000000..03a02a452dc
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer_impl_unittest.cc
@@ -0,0 +1,1260 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/output_device_mixer_impl.h"
+
+#include <array>
+
+#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
+#include "base/test/task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::InSequence;
+using testing::Mock;
+using testing::Return;
+using testing::StrictMock;
+
+namespace audio {
+namespace {
+
+using media::AudioOutputStream;
+
+const std::string kDeviceId = "device-id";
+
+MATCHER_P(AudioParamsEq, other, "AudioParameters matcher") {
+ return arg.Equals(other);
+}
+
+// Mock listener.
+class MockListener : public ReferenceOutput::Listener {
+ public:
+ MOCK_METHOD3(OnPlayoutData,
+ void(const media::AudioBus& audio_bus,
+ int sample_rate,
+ base::TimeDelta delay));
+};
+
+// Mock of a physical output stream_under_test.
+class MockAudioOutputStream : public AudioOutputStream {
+ public:
+ MockAudioOutputStream() = default;
+ ~MockAudioOutputStream() override = default;
+ MockAudioOutputStream(MockAudioOutputStream&& other) {
+ provided_callback_ = other.provided_callback_;
+ }
+
+ void Start(AudioSourceCallback* callback) override {
+ provided_callback_ = callback;
+ StartCalled();
+ }
+
+ MOCK_METHOD0(StartCalled, void());
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD0(Open, bool());
+ void SetVolume(double volume) final { volume_ = volume; }
+ double GetVolume() { return volume_; }
+ MOCK_METHOD1(GetVolume, void(double*));
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(Flush, void());
+
+ void SimulateOnMoreData() {
+ DCHECK(provided_callback_);
+ provided_callback_->OnMoreData(base::TimeDelta(), base::TimeTicks(), 0,
+ nullptr);
+ }
+
+ void SimulateError() {
+ DCHECK(provided_callback_);
+ provided_callback_->OnError(AudioSourceCallback::ErrorType::kUnknown);
+ }
+
+ private:
+ raw_ptr<AudioOutputStream::AudioSourceCallback> provided_callback_ = nullptr;
+ double volume_ = 0;
+};
+
+class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
+ public:
+ MockAudioSourceCallback() = default;
+ MockAudioSourceCallback(MockAudioSourceCallback&& other) {}
+
+ MOCK_METHOD4(OnMoreData,
+ int(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest));
+
+ MOCK_METHOD1(OnError,
+ void(AudioOutputStream::AudioSourceCallback::ErrorType type));
+};
+
+// Mocks interesting calls of MixingGraph::Input.
+class MockMixingGraphInput : public MixingGraph::Input {
+ public:
+ MockMixingGraphInput() = default;
+ MockMixingGraphInput(MockMixingGraphInput&& other) {}
+ MOCK_CONST_METHOD0(GetParams, const media::AudioParameters&());
+ void SetVolume(double volume) final { volume_ = volume; }
+ double GetVolume() { return volume_; }
+ MOCK_METHOD1(Start,
+ void(AudioOutputStream::AudioSourceCallback* source_callback));
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD2(ProvideInput,
+ double(media::AudioBus* audio_bus, uint32_t frames_delayed));
+
+ private:
+ double volume_ = 0;
+};
+
+// MixingGraph::Input eventually produced by MockMixingGraph::CreateInput().
+// Delegates all the interesting calls to MockMixingGraphInput.
+class FakeMixingGraphInput : public MixingGraph::Input {
+ public:
+ FakeMixingGraphInput(const media::AudioParameters& params,
+ MockMixingGraphInput* mock_input)
+ : params_(params), mock_input_(mock_input) {}
+ const media::AudioParameters& GetParams() const final { return params_; }
+ void SetVolume(double volume) final { mock_input_->SetVolume(volume); }
+ void Start(AudioOutputStream::AudioSourceCallback* source_callback) final {
+ mock_input_->Start(source_callback);
+ }
+ void Stop() final { mock_input_->Stop(); }
+
+ MOCK_METHOD2(ProvideInput,
+ double(media::AudioBus* audio_bus, uint32_t frames_delayed));
+
+ private:
+ const media::AudioParameters params_;
+ const raw_ptr<MockMixingGraphInput> mock_input_;
+};
+
+// Created and owned by OutputMixerManagerImpl; it's essentially a factory
+// producing FGraphakeMixerInput instances.
+class MockMixingGraph : public MixingGraph {
+ public:
+ using CreateGraphInputCallback =
+ base::RepeatingCallback<std::unique_ptr<MixingGraph::Input>(
+ const media::AudioParameters& params)>;
+
+ MockMixingGraph(CreateGraphInputCallback create_graph_input_cb,
+ MixingGraph::OnMoreDataCallback on_more_data_cb,
+ MixingGraph::OnErrorCallback on_error_cb)
+ : create_graph_input_cb_(std::move(create_graph_input_cb)),
+ on_more_data_cb_(std::move(on_more_data_cb)),
+ on_error_cb_(std::move(on_error_cb)) {}
+
+ std::unique_ptr<Input> CreateInput(
+ const media::AudioParameters& params) final {
+ return create_graph_input_cb_.Run(params);
+ }
+
+ MOCK_METHOD4(OnMoreData,
+ int(base::TimeDelta delay,
+ base::TimeTicks delay_timestamp,
+ int prior_frames_skipped,
+ media::AudioBus* dest));
+
+ void OnError(AudioOutputStream::AudioSourceCallback::ErrorType type) final {
+ on_error_cb_.Run(type);
+ }
+
+ void SimulateOnMoreData() {
+ auto audio_bus = media::AudioBus::Create(2, 480);
+ on_more_data_cb_.Run(*audio_bus.get(), base::TimeDelta());
+ }
+
+ private:
+ MOCK_METHOD1(AddInput, void(MixingGraph::Input* input));
+ MOCK_METHOD1(RemoveInput, void(MixingGraph::Input* input));
+ CreateGraphInputCallback create_graph_input_cb_;
+ MixingGraph::OnMoreDataCallback on_more_data_cb_;
+ MixingGraph::OnErrorCallback on_error_cb_;
+};
+
+class OutputDeviceMixerImplTestBase {
+ protected:
+ enum class PlaybackMode { kMixing, kIndependent };
+
+ // Holds all the mocks associated with a given audio output.
+ struct MixTrackMock {
+ explicit MixTrackMock(int frames_per_buffer)
+ : params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ 48000,
+ frames_per_buffer) {}
+ StrictMock<MockMixingGraphInput> graph_input;
+ StrictMock<MockAudioOutputStream> rendering_stream;
+ const media::AudioParameters params;
+ StrictMock<MockAudioSourceCallback> source_callback;
+ // Set to true when independent rendering started successfully for the first
+ // time.
+ bool independent_rendergin_stream_was_open = false;
+ };
+
+ // Helper.
+ struct StreamUnderTest {
+ // MixableOutputStream produced by OutputMixerImpl.
+ AudioOutputStream* mixable_stream;
+ // All the mocks associated with it.
+ MixTrackMock* mix_track_mock;
+ };
+
+ // Registers physical output stream creation.
+ MOCK_METHOD1(MockCreateOutputStream,
+ bool(const media::AudioParameters& params));
+
+ // Creates the mixer for testing, passing callbacks to produce mock
+ // MixingGraph and mock physical output stream_under_test.
+ std::unique_ptr<OutputDeviceMixer> CreateMixerUnderTest(
+ const std::string& device_id = kDeviceId) {
+ auto mixer = std::make_unique<OutputDeviceMixerImpl>(
+ device_id, mixer_output_params_,
+ base::BindOnce(&OutputDeviceMixerImplTestBase::CreateMockMixingGraph,
+ base::Unretained(this)),
+ base::BindRepeating(&OutputDeviceMixerImplTestBase::CreateOutputStream,
+ base::Unretained(this), device_id));
+ return mixer;
+ }
+
+ // Helper which calls the mixer to create an output stream
+ // (MixabeOutputStream) and associates the result output stream with its
+ // corresponding set of mocks.
+ StreamUnderTest CreateNextStreamUnderTest(OutputDeviceMixer* mixer) {
+ EXPECT_LE(mix_track_mocks_in_use_count_, mix_track_mocks_.size() - 1);
+ const media::AudioParameters params =
+ mix_track_mocks_[mix_track_mocks_in_use_count_].params;
+ return {mixer->MakeMixableStream(
+ params,
+ base::BindOnce(
+ &OutputDeviceMixerImplTestBase::OnDeviceChangeForMixMember,
+ base::Unretained(this), params)),
+ &mix_track_mocks_[mix_track_mocks_in_use_count_++]};
+ }
+
+ // Opens a MixabeOutputStream created by the mixer under test and sets
+ // expectations on associated mocks.
+ void OpenAndVerifyStreamUnderTest(StreamUnderTest& stream_under_test) {
+ EXPECT_TRUE(stream_under_test.mixable_stream->Open());
+ VerifyAndClearAllExpectations();
+ }
+
+ // Closes a MixabeOutputStream created by the mixer under test and sets
+ // expectations on associated mocks.
+ void CloseAndVerifyStreamUnderTest(StreamUnderTest& stream_under_test) {
+ if (stream_under_test.mix_track_mock
+ ->independent_rendergin_stream_was_open) {
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Close());
+ }
+ stream_under_test.mixable_stream->Close();
+ VerifyAndClearAllExpectations();
+ }
+
+ // Starts a MixabeOutputStream created by the mixer under test and sets
+ // expectations on associated mocks. |playback_mode| is the mode
+ // OutputMixerImpl is expected to be in at the moment.
+ void StartAndVerifyStreamUnderTest(StreamUnderTest& stream_under_test,
+ PlaybackMode playback_mode) {
+ ExpectPlaybackStarted(stream_under_test.mix_track_mock, playback_mode);
+ stream_under_test.mixable_stream->Start(
+ &stream_under_test.mix_track_mock->source_callback);
+ VerifyAndClearAllExpectations();
+ }
+
+ // Stops a MixabeOutputStream created by the mixer under test and sets
+ // expectations on associated mocks. |playback_mode| is the mode
+ // OutputMixerImpl is expected to be in at the moment.
+ void StopAndVerifyStreamUnderTest(StreamUnderTest& stream_under_test,
+ PlaybackMode playback_mode) {
+ ExpectPlaybackStopped(stream_under_test.mix_track_mock, playback_mode);
+ stream_under_test.mixable_stream->Stop();
+ VerifyAndClearAllExpectations();
+ }
+
+ // Sets expectations for the mixer to start rendeing mixed audio.
+ void ExpectMixingGraphOutputStreamStarted() {
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Open())
+ .WillOnce(Return(true));
+ EXPECT_CALL(mock_mixing_graph_output_stream_, StartCalled());
+ mixing_graph_output_stream_not_running_ = false;
+ }
+
+ // Sets expectations for the mixer to stop rendeing mixed audio.
+ void ExpectMixingGraphOutputStreamStopped() {
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Stop);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Close);
+ mixing_graph_output_stream_not_running_ = true;
+ }
+
+ void ExpectPlaybackStarted(MixTrackMock* mix_track_mock,
+ PlaybackMode playback_mode) {
+ if (playback_mode == PlaybackMode::kIndependent) {
+ if (!mix_track_mock->independent_rendergin_stream_was_open) {
+ // The rendering straem must be open on first start.
+ EXPECT_CALL(*this, MockCreateOutputStream(
+ AudioParamsEq(mix_track_mock->params)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(mix_track_mock->rendering_stream, Open())
+ .WillOnce(Return(true));
+ mix_track_mock->independent_rendergin_stream_was_open = true;
+ }
+ EXPECT_CALL(mix_track_mock->rendering_stream, StartCalled());
+ } else {
+ EXPECT_CALL(mix_track_mock->graph_input,
+ Start(&mix_track_mock->source_callback));
+ if (mixing_graph_output_stream_not_running_) {
+ ExpectMixingGraphOutputStreamStarted();
+ }
+ }
+ }
+
+ void ExpectPlaybackStopped(MixTrackMock* mix_track_mock,
+ PlaybackMode playback_mode) {
+ if (playback_mode == PlaybackMode::kIndependent) {
+ if (mix_track_mock->independent_rendergin_stream_was_open) {
+ EXPECT_CALL(mix_track_mock->rendering_stream, Stop);
+ }
+ } else {
+ EXPECT_CALL(mix_track_mock->graph_input, Stop);
+ }
+ }
+
+ // Sets "start mixing" expectations for a given set of mocks.
+ void ExpectMixingStarted(const std::set<MixTrackMock*>& mocks) {
+ for (MixTrackMock* mock : mocks)
+ EXPECT_CALL(mock->graph_input, Start(&mock->source_callback));
+ if (mocks.size() && mixing_graph_output_stream_not_running_)
+ ExpectMixingGraphOutputStreamStarted();
+ }
+
+ // Sets "stop mixing" expectations for a given set of mocks.
+ void ExpectMixingStopped(const std::set<MixTrackMock*>& mocks) {
+ for (MixTrackMock* mock : mocks)
+ EXPECT_CALL(mock->graph_input, Stop);
+ if (mocks.size() && !mixing_graph_output_stream_not_running_)
+ ExpectMixingGraphOutputStreamStopped();
+ }
+
+ // Sets "start playing independently" expectations for a given set of mocks.
+ void ExpectIndependentPlaybackStarted(const std::set<MixTrackMock*>& mocks) {
+ for (MixTrackMock* mock : mocks)
+ ExpectPlaybackStarted(mock, PlaybackMode::kIndependent);
+ }
+
+ // Sets "stop playing independently" expectations for a given set of mocks.
+ void ExpectIndependentPlaybackStopped(const std::set<MixTrackMock*>& mocks) {
+ for (MixTrackMock* mock : mocks)
+ ExpectPlaybackStopped(mock, PlaybackMode::kIndependent);
+ }
+
+ // Sets "no playback change" expectations for a given set of mocks.
+ void ExpectNoPlaybackModeChange(const std::set<MixTrackMock*>& mocks) {
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Stop).Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, StartCalled()).Times(0);
+
+ for (MixTrackMock* mock : mocks) {
+ EXPECT_CALL(mock->graph_input, Stop).Times(0);
+ EXPECT_CALL(mock->rendering_stream, StartCalled()).Times(0);
+ EXPECT_CALL(mock->graph_input, Start(_)).Times(0);
+ EXPECT_CALL(mock->rendering_stream, Stop).Times(0);
+ }
+ }
+
+ // Verifies and clears expectations on all mocks.
+ void VerifyAndClearAllExpectations() {
+ for (auto& mix_member_mock : mix_track_mocks_) {
+ Mock::VerifyAndClearExpectations(&mix_member_mock.graph_input);
+ Mock::VerifyAndClearExpectations(&mix_member_mock.rendering_stream);
+ Mock::VerifyAndClearExpectations(&mix_member_mock.source_callback);
+ }
+ Mock::VerifyAndClearExpectations(&mock_mixing_graph_output_stream_);
+ Mock::VerifyAndClearExpectations(this);
+ }
+
+ // Called when device change callback of a MixTrack is called.
+ MOCK_METHOD1(OnDeviceChangeForMixMember,
+ void(const media::AudioParameters& params));
+
+ // Fast-forward to the point when delayed switch to unmixed playback must have
+ // happened (if it was scheduled).
+ void FastForwardToUnmixedPlayback() {
+ task_environment_.FastForwardBy(
+ OutputDeviceMixerImpl::kSwitchToUnmixedPlaybackDelay * 2);
+ }
+
+ raw_ptr<MockMixingGraph> mock_mixing_graph_ = nullptr;
+ StrictMock<MockAudioOutputStream> mock_mixing_graph_output_stream_;
+
+ const media::AudioParameters mixer_output_params_{
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 5};
+
+ private:
+ AudioOutputStream* CreateOutputStream(const std::string& expected_device_id,
+ const std::string& device_id,
+ const media::AudioParameters& params) {
+ EXPECT_EQ(device_id, expected_device_id);
+ if (!MockCreateOutputStream(params))
+ return nullptr; // Fail stream creation.
+ if (params.Equals(mixer_output_params_))
+ return &mock_mixing_graph_output_stream_;
+ return &(FindMixTrackMock(params)->rendering_stream);
+ }
+
+ // Passed into OutputMixerImpl as a callback producing MixingGraph.
+ std::unique_ptr<MixingGraph> CreateMockMixingGraph(
+ const media::AudioParameters& output_params,
+ MixingGraph::OnMoreDataCallback on_more_data_cb,
+ MixingGraph::OnErrorCallback on_error_cb) {
+ auto mock_mixing_graph = std::make_unique<StrictMock<MockMixingGraph>>(
+ base::BindRepeating(
+ &OutputDeviceMixerImplTestBase::CreateMockGraphInput,
+ base::Unretained(this)),
+ std::move(on_more_data_cb), std::move(on_error_cb));
+ mock_mixing_graph_ = mock_mixing_graph.get();
+ return mock_mixing_graph;
+ }
+
+ // Passed into MockMixingGraph as a callback producing MixingGraph::Input
+ // instances.
+ std::unique_ptr<MixingGraph::Input> CreateMockGraphInput(
+ const media::AudioParameters& params) {
+ return std::make_unique<FakeMixingGraphInput>(
+ params, &(FindMixTrackMock(params)->graph_input));
+ }
+
+ // Finds the mocks for MixableOutputStream created with given |params|.
+ MixTrackMock* FindMixTrackMock(const media::AudioParameters& params) {
+ for (auto& track_mock : mix_track_mocks_) {
+ if (track_mock.params.Equals(params))
+ return &track_mock;
+ }
+ DCHECK(false);
+ return nullptr;
+ }
+
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME};
+
+ // A set of mocks for the data associated with MixableOutputStream; each mock
+ // is identfied by its MixTrackMock::|params|.frames_per_buffer().
+ // To create mixable_stream output streams_under_test the tests call
+ // OutputDeviceMixerImpl::MakeMixableStream with MixTrackMock::|params|
+ // parameters, thus building an association between a MixableOutputStream and
+ // MixTrackMock.
+ std::array<MixTrackMock, 3> mix_track_mocks_{
+ MixTrackMock(10), MixTrackMock(20), MixTrackMock(30)};
+
+ // How many elements of |mix_track_mocks_| are already in use.
+ size_t mix_track_mocks_in_use_count_ = 0;
+
+ // Helps to correctly set expectations for |mock_mixing_graph_output_stream_|.
+ bool mixing_graph_output_stream_not_running_ = true;
+};
+
+class OutputDeviceMixerImplTest : public OutputDeviceMixerImplTestBase,
+ public testing::TestWithParam<int> {};
+
+class OutputDeviceMixerImplTestWithDefault
+ : public OutputDeviceMixerImplTestBase,
+ public testing::TestWithParam<std::string> {};
+
+TEST_P(OutputDeviceMixerImplTestWithDefault, OneUmixedStream_CreateClose) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest(GetParam());
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+
+ // Physical output streams are created only on Open().
+ EXPECT_CALL(*this, MockCreateOutputStream(_)).Times(0);
+
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Open())
+ .Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Open()).Times(0);
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Close())
+ .Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Close()).Times(0);
+
+ stream_under_test.mixable_stream->Close();
+}
+
+TEST_F(OutputDeviceMixerImplTest, OneUmixedStream_PhysicalStreamCreateFailed) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+
+ // Fail physical stream creation for the mix member. Open() fails, physical
+ // stream for independent rendering is not created.
+ EXPECT_CALL(*this, MockCreateOutputStream(AudioParamsEq(
+ stream_under_test.mix_track_mock->params)))
+ .WillOnce(Return(false));
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Open())
+ .Times(0);
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Close())
+ .Times(0);
+
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Open()).Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Close()).Times(0);
+
+ // Open() will work, but stream creation will fail on start and will result in
+ // OnError().
+ EXPECT_TRUE(stream_under_test.mixable_stream->Open());
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_))
+ .Times(1);
+
+ stream_under_test.mixable_stream->Start(
+ &stream_under_test.mix_track_mock->source_callback);
+
+ stream_under_test.mixable_stream->Stop();
+
+ stream_under_test.mixable_stream->Close();
+}
+
+TEST_F(OutputDeviceMixerImplTest, OneUmixedStream_PhysicalStreamOpenFailed) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+
+ // Fail opening physical stream for the mix track. Open() fails, physical
+ // stream for independent rendering is not created.
+ EXPECT_CALL(*this, MockCreateOutputStream(AudioParamsEq(
+ stream_under_test.mix_track_mock->params)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Open())
+ .WillOnce(Return(false));
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Close());
+
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Open()).Times(0);
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Close()).Times(0);
+
+ EXPECT_TRUE(stream_under_test.mixable_stream->Open());
+
+ // Open() will work, but stream creation will fail on start and will result in
+ // OnError().
+ EXPECT_TRUE(stream_under_test.mixable_stream->Open());
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_))
+ .Times(1);
+
+ stream_under_test.mixable_stream->Start(
+ &stream_under_test.mix_track_mock->source_callback);
+
+ stream_under_test.mixable_stream->Stop();
+
+ stream_under_test.mixable_stream->Close();
+}
+
+TEST_P(OutputDeviceMixerImplTestWithDefault, OneUmixedStream_CreateOpenClose) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest(GetParam());
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+}
+
+TEST_F(OutputDeviceMixerImplTest, TwoUmixedStream_CreateOpenClose) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+ StreamUnderTest stream_under_test1 = CreateNextStreamUnderTest(mixer.get());
+ StreamUnderTest stream_under_test2 = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test1);
+ OpenAndVerifyStreamUnderTest(stream_under_test2);
+ CloseAndVerifyStreamUnderTest(stream_under_test2);
+ CloseAndVerifyStreamUnderTest(stream_under_test1);
+}
+
+TEST_F(OutputDeviceMixerImplTest,
+ TwoUmixedStream_SecondOpenFailureDoesNotAffectMixerStream) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+ StreamUnderTest stream_under_test1 = CreateNextStreamUnderTest(mixer.get());
+ StreamUnderTest stream_under_test2 = CreateNextStreamUnderTest(mixer.get());
+
+ OpenAndVerifyStreamUnderTest(stream_under_test1);
+ StartAndVerifyStreamUnderTest(stream_under_test1, PlaybackMode::kIndependent);
+
+ // Failing to open stream_under_test2 does not affect stream_under_test2.
+ EXPECT_CALL(*this, MockCreateOutputStream(AudioParamsEq(
+ stream_under_test2.mix_track_mock->params)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(stream_under_test2.mix_track_mock->rendering_stream, Open())
+ .WillOnce(Return(false));
+ EXPECT_CALL(stream_under_test2.mix_track_mock->rendering_stream, Close());
+ EXPECT_CALL(stream_under_test2.mix_track_mock->source_callback, OnError(_))
+ .Times(1);
+
+ EXPECT_TRUE(stream_under_test2.mixable_stream->Open());
+
+ stream_under_test2.mixable_stream->Start(
+ &stream_under_test2.mix_track_mock->source_callback);
+
+ VerifyAndClearAllExpectations();
+
+ stream_under_test2.mixable_stream->Stop();
+ stream_under_test2.mixable_stream->Close();
+ VerifyAndClearAllExpectations();
+
+ StopAndVerifyStreamUnderTest(stream_under_test1, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test1);
+}
+
+TEST_F(OutputDeviceMixerImplTest, OneUmixedStream_SetVolumeIsPropagated) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+
+ double volume1 = 0.1;
+ double volume2 = 0.2;
+ double volume3 = 0.3;
+ double volume4 = 0.3;
+ double volume_result = 0;
+
+ // Volume is propagated before MixableOutputStream::Open().
+ stream_under_test.mixable_stream->SetVolume(volume1);
+ stream_under_test.mixable_stream->GetVolume(&volume_result);
+ EXPECT_EQ(volume_result, volume1);
+ EXPECT_EQ(stream_under_test.mix_track_mock->graph_input.GetVolume(), volume1);
+
+ stream_under_test.mixable_stream->SetVolume(volume2);
+ stream_under_test.mixable_stream->GetVolume(&volume_result);
+ EXPECT_EQ(volume_result, volume2);
+ EXPECT_EQ(stream_under_test.mix_track_mock->graph_input.GetVolume(), volume2);
+
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+
+ // Volume is propagated after MixableOutputStream::Open().
+ stream_under_test.mixable_stream->GetVolume(&volume_result);
+ EXPECT_EQ(volume_result, volume2);
+ EXPECT_EQ(stream_under_test.mix_track_mock->graph_input.GetVolume(), volume2);
+
+ StartAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+
+ // Volume is applied to the independent rendering stream of the MixTrack.
+ EXPECT_EQ(stream_under_test.mix_track_mock->rendering_stream.GetVolume(),
+ volume2);
+
+ // Now when the stream is open, the volume is propagated to both the mixer
+ // input and the independent rendering tream of the MixTrack.
+ stream_under_test.mixable_stream->SetVolume(volume3);
+ stream_under_test.mixable_stream->GetVolume(&volume_result);
+ EXPECT_EQ(volume_result, volume3);
+ EXPECT_EQ(stream_under_test.mix_track_mock->graph_input.GetVolume(), volume3);
+ EXPECT_EQ(stream_under_test.mix_track_mock->rendering_stream.GetVolume(),
+ volume3);
+
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+
+ stream_under_test.mixable_stream->SetVolume(volume4);
+ stream_under_test.mixable_stream->GetVolume(&volume_result);
+ EXPECT_EQ(volume_result, volume4);
+ EXPECT_EQ(stream_under_test.mix_track_mock->graph_input.GetVolume(), volume4);
+ EXPECT_EQ(stream_under_test.mix_track_mock->rendering_stream.GetVolume(),
+ volume4);
+
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+}
+
+TEST_F(OutputDeviceMixerImplTest,
+ OneUmixedStream_CreateOpenPlayOnErrorStopClose) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+
+ {
+ InSequence s;
+
+ StartAndVerifyStreamUnderTest(stream_under_test,
+ PlaybackMode::kIndependent);
+
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback,
+ OnMoreData(_, _, _, _))
+ .Times(1);
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_))
+ .Times(1);
+
+ stream_under_test.mix_track_mock->rendering_stream.SimulateOnMoreData();
+ stream_under_test.mix_track_mock->rendering_stream.SimulateError();
+
+ VerifyAndClearAllExpectations();
+
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ }
+
+ // Make sure it works after restart as well.
+ {
+ InSequence s;
+
+ StartAndVerifyStreamUnderTest(stream_under_test,
+ PlaybackMode::kIndependent);
+
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback,
+ OnMoreData(_, _, _, _))
+ .Times(1);
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_))
+ .Times(1);
+
+ stream_under_test.mix_track_mock->rendering_stream.SimulateOnMoreData();
+ stream_under_test.mix_track_mock->rendering_stream.SimulateError();
+
+ VerifyAndClearAllExpectations();
+
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ }
+
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+}
+
+TEST_P(OutputDeviceMixerImplTest, NStreamsOpen_StartStopListeningHasNoEffect) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+ std::vector<StreamUnderTest> streams_under_test;
+ std::set<MixTrackMock*> playing_stream_mocks;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ }
+
+ // The mixer may have streams open, but they are not playing, so
+ // Start/StopListening has no effect.
+ MockListener listener;
+ mixer->StartListening(&listener);
+ mixer->StopListening(&listener);
+ FastForwardToUnmixedPlayback();
+ for (auto& stream_under_test : streams_under_test) {
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+}
+
+TEST_P(OutputDeviceMixerImplTest, NStreamsPlaying_StartStopTwoListeners) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+ if (!stream_count)
+ return; // Not interesting.
+ std::vector<StreamUnderTest> streams_under_test;
+ std::set<MixTrackMock*> playing_stream_mocks;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kIndependent);
+ playing_stream_mocks.insert((&streams_under_test.back())->mix_track_mock);
+ }
+
+ MockListener listener1;
+ MockListener listener2;
+
+ // We are playing at least one stream.
+ // Expect switch to mixing when the first listener comes.
+ ExpectIndependentPlaybackStopped(playing_stream_mocks);
+ ExpectMixingStarted(playing_stream_mocks);
+ mixer->StartListening(&listener1);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ // Nothing should change when the second listener comes.
+ ExpectNoPlaybackModeChange(playing_stream_mocks);
+ mixer->StartListening(&listener2);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ // First listener leaves: we still should be mixing.
+ ExpectNoPlaybackModeChange(playing_stream_mocks);
+ mixer->StopListening(&listener1);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ // Second listener leaves: switching to unmixed playback is delayed, so we do
+ // not expect it to happen immediately.
+ ExpectNoPlaybackModeChange(playing_stream_mocks);
+ mixer->StopListening(&listener2);
+ VerifyAndClearAllExpectations();
+
+ // Expect switching to unmixed playback after we fast-forward to the future.
+ ExpectMixingStopped(playing_stream_mocks);
+ ExpectIndependentPlaybackStarted(playing_stream_mocks);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+}
+
+TEST_P(OutputDeviceMixerImplTest,
+ NStreamsPlaying_StopStartListening_DoesNotStopMixing) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+ if (!stream_count)
+ return; // Not interesting.
+ std::vector<StreamUnderTest> streams_under_test;
+ std::set<MixTrackMock*> playing_stream_mocks;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kIndependent);
+ playing_stream_mocks.insert((&streams_under_test.back())->mix_track_mock);
+ }
+
+ MockListener listener;
+
+ // We are playing at least one stream.
+ // Expect switch to mixing when the listener comes.
+ ExpectIndependentPlaybackStopped(playing_stream_mocks);
+ ExpectMixingStarted(playing_stream_mocks);
+ mixer->StartListening(&listener);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ // If the listener stops listening and then starts again immediately, we do
+ // not switch to unmixed playback even after the timeout.
+ ExpectNoPlaybackModeChange(playing_stream_mocks);
+ mixer->StopListening(&listener);
+ mixer->StartListening(&listener);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ // Stop listening and expect the switch to unmixed playback upon the timeout.
+ ExpectMixingStopped(playing_stream_mocks);
+ ExpectIndependentPlaybackStarted(playing_stream_mocks);
+ mixer->StopListening(&listener);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+}
+
+TEST_P(OutputDeviceMixerImplTest,
+ StartStopNStreamsWhileListening_MixedPlaybackUntilListenerGone) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+ if (!stream_count)
+ return; // Not interesting.
+
+ MockListener listener;
+ mixer->StartListening(&listener);
+
+ std::vector<StreamUnderTest> streams_under_test;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kMixing);
+ }
+
+ // Stopping all playback does not stop rendering of the mixing graph.
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+ }
+
+ // Restarting playback.
+ for (auto& stream_under_test : streams_under_test) {
+ StartAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+ }
+
+ // Stopping and closing all the streams does not stop rendering of the mixing
+ // graph.
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+
+ FastForwardToUnmixedPlayback();
+ VerifyAndClearAllExpectations();
+
+ // Now when we stop the listener, rendering of the mixing graph should
+ // stop immediately. Mixing graph output stream will be closed.
+ ExpectMixingGraphOutputStreamStopped();
+ mixer->StopListening(&listener);
+ VerifyAndClearAllExpectations();
+}
+
+TEST_P(OutputDeviceMixerImplTest, StartStopNStreamsWhileListening_DeleteMixer) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener;
+ mixer->StartListening(&listener);
+ VerifyAndClearAllExpectations();
+
+ int stream_count = GetParam();
+ std::vector<StreamUnderTest> streams_under_test;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kMixing);
+ }
+
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+
+ if (stream_count)
+ ExpectMixingGraphOutputStreamStopped();
+ mixer->StopListening(&listener);
+ mixer = nullptr;
+ // Mixer output stream must be closed immediately.
+ VerifyAndClearAllExpectations();
+}
+
+TEST_P(OutputDeviceMixerImplTest, NStreamsMixing_OnMixingStreamError) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+ if (!stream_count)
+ return; // Not interesting.
+
+ MockListener listener;
+ mixer->StartListening(&listener);
+
+ std::vector<StreamUnderTest> streams_under_test;
+ std::set<MixTrackMock*> playing_stream_mocks;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kMixing);
+ playing_stream_mocks.insert((&streams_under_test.back())->mix_track_mock);
+ }
+
+ for (auto& stream_under_test : streams_under_test)
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_));
+
+ ExpectMixingStopped(playing_stream_mocks);
+ mock_mixing_graph_output_stream_.SimulateError();
+ VerifyAndClearAllExpectations();
+
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ }
+
+ mixer->StopListening(&listener);
+ for (auto& stream_under_test : streams_under_test) {
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+ mixer.reset();
+ VerifyAndClearAllExpectations();
+}
+
+TEST_F(OutputDeviceMixerImplTest, OnMixingStreamError_Recovers) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener;
+ mixer->StartListening(&listener);
+
+ std::vector<StreamUnderTest> streams_under_test;
+ std::set<MixTrackMock*> playing_stream_mocks;
+ for (int i = 0; i < 2; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kMixing);
+ playing_stream_mocks.insert((&streams_under_test.back())->mix_track_mock);
+ }
+
+ for (auto& stream_under_test : streams_under_test)
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_));
+
+ ExpectMixingStopped(playing_stream_mocks);
+ mock_mixing_graph_output_stream_.SimulateError();
+ VerifyAndClearAllExpectations();
+
+ // Opening and starting a new stream: mixing should retry and start
+ // successfully.
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+
+ // Mixing should restart now.
+ ExpectMixingStarted(playing_stream_mocks);
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kMixing);
+
+ for (auto& stream_under_test : streams_under_test) {
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+ }
+
+ // No playback, the listener is gone - we should stop mixing.
+ ExpectMixingGraphOutputStreamStopped();
+ mixer->StopListening(&listener);
+ VerifyAndClearAllExpectations();
+
+ for (auto& stream_under_test : streams_under_test) {
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+ }
+}
+
+TEST_P(OutputDeviceMixerImplTest, NStreamsPlayingUmixed_DeviceChange) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+
+ std::vector<StreamUnderTest> streams_under_test;
+
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ if (i) { // Leave one stream just open.
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kIndependent);
+ }
+ }
+
+ for (int i = 0; i < stream_count; ++i) {
+ if (i) {
+ EXPECT_CALL(streams_under_test[i].mix_track_mock->rendering_stream, Stop);
+ EXPECT_CALL(streams_under_test[i].mix_track_mock->rendering_stream,
+ Close);
+ }
+ EXPECT_CALL(*this, OnDeviceChangeForMixMember(AudioParamsEq(
+ streams_under_test[i].mix_track_mock->params)));
+ }
+
+ mixer->ProcessDeviceChange();
+ VerifyAndClearAllExpectations();
+
+ // Stop() and Close() operations on streams are no-op now.
+ for (int i = 0; i < stream_count; ++i) {
+ if (i) {
+ streams_under_test[i].mixable_stream->Stop();
+ }
+ streams_under_test[i].mixable_stream->Close();
+ }
+}
+
+TEST_P(OutputDeviceMixerImplTest, NStreamsPlayingMixed_DeviceChange) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ int stream_count = GetParam();
+
+ MockListener listener;
+ mixer->StartListening(&listener);
+
+ std::vector<StreamUnderTest> streams_under_test;
+ for (int i = 0; i < stream_count; ++i) {
+ streams_under_test.push_back(CreateNextStreamUnderTest(mixer.get()));
+ OpenAndVerifyStreamUnderTest(streams_under_test.back());
+ if (i) { // Leave one stream just open.
+ StartAndVerifyStreamUnderTest(streams_under_test.back(),
+ PlaybackMode::kMixing);
+ }
+ }
+
+ for (int i = 0; i < stream_count; ++i) {
+ if (i) {
+ EXPECT_CALL(streams_under_test[i].mix_track_mock->graph_input, Stop);
+ }
+ EXPECT_CALL(*this, OnDeviceChangeForMixMember(AudioParamsEq(
+ streams_under_test[i].mix_track_mock->params)));
+ }
+
+ if (stream_count > 1) // Since we do not start the first stream.
+ ExpectMixingGraphOutputStreamStopped();
+
+ mixer->ProcessDeviceChange();
+ VerifyAndClearAllExpectations();
+
+ // Stop() and Close() operations on streams are no-op now.
+ for (int i = 0; i < stream_count; ++i) {
+ if (i) {
+ streams_under_test[i].mixable_stream->Stop();
+ }
+ streams_under_test[i].mixable_stream->Close();
+ }
+}
+
+TEST_F(OutputDeviceMixerImplTest, OnMoreDataDeliversCallbacks) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener1;
+ MockListener listener2;
+
+ mixer->StartListening(&listener1);
+
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+ StartAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+
+ EXPECT_CALL(listener1, OnPlayoutData(_, _, _)).Times(1);
+ mock_mixing_graph_->SimulateOnMoreData();
+ VerifyAndClearAllExpectations();
+
+ mixer->StartListening(&listener2);
+
+ EXPECT_CALL(listener1, OnPlayoutData(_, _, _)).Times(1);
+ EXPECT_CALL(listener2, OnPlayoutData(_, _, _)).Times(1);
+ mock_mixing_graph_->SimulateOnMoreData();
+ VerifyAndClearAllExpectations();
+
+ mixer->StopListening(&listener1);
+
+ EXPECT_CALL(listener2, OnPlayoutData(_, _, _)).Times(1);
+ mock_mixing_graph_->SimulateOnMoreData();
+ VerifyAndClearAllExpectations();
+
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kMixing);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+
+ ExpectMixingGraphOutputStreamStopped();
+ mixer->StopListening(&listener2);
+}
+
+TEST_F(OutputDeviceMixerImplTest,
+ MixingStreamCreationFailureHandled_ListenerPresent) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener;
+
+ mixer->StartListening(&listener);
+
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_));
+
+ stream_under_test.mixable_stream->Start(
+ &stream_under_test.mix_track_mock->source_callback);
+
+ VerifyAndClearAllExpectations();
+
+ // Since mixing has not started, the mixer considers it as independent
+ // playback and will stop the independent rendering stream. It's ok:
+ // media::AudioOutputStream can be closed multiple times.
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+
+ mixer->StopListening(&listener);
+}
+
+TEST_F(OutputDeviceMixerImplTest,
+ MixingStreamOpenFailureHandled_ListenerPresent) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener;
+
+ mixer->StartListening(&listener);
+
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Open()).WillOnce(Return(false));
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Close());
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_));
+
+ stream_under_test.mixable_stream->Start(
+ &stream_under_test.mix_track_mock->source_callback);
+
+ VerifyAndClearAllExpectations();
+
+ // Since mixing has not started, the mixer considers it as independent
+ // playback and will stop the independent rendering stream. It's ok:
+ // media::AudioOutputStream can be closed multiple times.
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+
+ mixer->StopListening(&listener);
+}
+
+TEST_F(OutputDeviceMixerImplTest,
+ MixingStreamOpenFailureHandled_WhenStartListening) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener;
+
+ StreamUnderTest stream_under_test = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test);
+ StartAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Open()).WillOnce(Return(false));
+ EXPECT_CALL(mock_mixing_graph_output_stream_, Close());
+ EXPECT_CALL(stream_under_test.mix_track_mock->rendering_stream, Stop);
+ EXPECT_CALL(stream_under_test.mix_track_mock->source_callback, OnError(_));
+
+ mixer->StartListening(&listener);
+ VerifyAndClearAllExpectations();
+
+ // Since mixing has not started, the mixer considers it as independent
+ // playback and will stop the independent rendering stream. It's ok:
+ // media::AudioOutputStream can be closed multiple times.
+ StopAndVerifyStreamUnderTest(stream_under_test, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test);
+
+ mixer->StopListening(&listener);
+}
+
+TEST_F(OutputDeviceMixerImplTest,
+ MixingStreamCreationFailureHandled_NextMixingSuccessful) {
+ std::unique_ptr<OutputDeviceMixer> mixer = CreateMixerUnderTest();
+
+ MockListener listener;
+
+ mixer->StartListening(&listener);
+
+ StreamUnderTest stream_under_test1 = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test1);
+
+ EXPECT_CALL(*this,
+ MockCreateOutputStream(AudioParamsEq(mixer_output_params_)))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(stream_under_test1.mix_track_mock->source_callback, OnError(_));
+
+ stream_under_test1.mixable_stream->Start(
+ &stream_under_test1.mix_track_mock->source_callback);
+
+ VerifyAndClearAllExpectations();
+
+ // Since mixing has not started, the mixer considers it as independent
+ // playback and will stop the independent rendering stream. It's ok:
+ // media::AudioOutputStream can be closed multiple times.
+ StopAndVerifyStreamUnderTest(stream_under_test1, PlaybackMode::kIndependent);
+ CloseAndVerifyStreamUnderTest(stream_under_test1);
+
+ // This time mixing should be successful.
+ StreamUnderTest stream_under_test2 = CreateNextStreamUnderTest(mixer.get());
+ OpenAndVerifyStreamUnderTest(stream_under_test2);
+ StartAndVerifyStreamUnderTest(stream_under_test2, PlaybackMode::kMixing);
+ StopAndVerifyStreamUnderTest(stream_under_test2, PlaybackMode::kMixing);
+ CloseAndVerifyStreamUnderTest(stream_under_test2);
+
+ ExpectMixingGraphOutputStreamStopped();
+ mixer->StopListening(&listener);
+}
+
+INSTANTIATE_TEST_SUITE_P(,
+ OutputDeviceMixerImplTest,
+ testing::Values(0, 1, 2, 3));
+
+INSTANTIATE_TEST_SUITE_P(,
+ OutputDeviceMixerImplTestWithDefault,
+ testing::Values(kDeviceId, ""));
+
+} // namespace
+
+} // namespace audio
diff --git a/chromium/services/audio/output_device_mixer_manager.cc b/chromium/services/audio/output_device_mixer_manager.cc
new file mode 100644
index 00000000000..68c18abab91
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer_manager.cc
@@ -0,0 +1,316 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/output_device_mixer_manager.h"
+
+#include "base/check.h"
+#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
+#include "base/trace_event/trace_event.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_manager.h"
+#include "media/base/audio_latency.h"
+#include "services/audio/device_listener_output_stream.h"
+#include "services/audio/output_device_mixer.h"
+
+namespace {
+
+const char kNormalizedDefaultDeviceId[] = "";
+
+// Helper function which returns a consistent representation of the default
+// device ID.
+std::string NormalizeIfDefault(const std::string& device_id) {
+ return media::AudioDeviceDescription::IsDefaultDevice(device_id)
+ ? kNormalizedDefaultDeviceId
+ : device_id;
+}
+
+} // namespace
+
+namespace media {
+
+// Helper class to get access to the protected AudioManager API.
+class AudioManagerPowerUser {
+ public:
+ explicit AudioManagerPowerUser(AudioManager* audio_manager)
+ : audio_manager_(audio_manager) {}
+ std::string GetDefaultOutputDeviceID() {
+ std::string device_id = audio_manager_->GetDefaultOutputDeviceID();
+ return device_id.empty() ? kNormalizedDefaultDeviceId : device_id;
+ }
+ AudioParameters GetOutputStreamParameters(const std::string& device_id) {
+ return media::AudioDeviceDescription::IsDefaultDevice(device_id)
+ ? audio_manager_->GetDefaultOutputStreamParameters()
+ : audio_manager_->GetOutputStreamParameters(device_id);
+ }
+
+ private:
+ const raw_ptr<AudioManager> audio_manager_;
+};
+
+} // namespace media
+
+namespace audio {
+
+OutputDeviceMixerManager::OutputDeviceMixerManager(
+ media::AudioManager* audio_manager,
+ OutputDeviceMixer::CreateCallback create_mixer_callback)
+ : audio_manager_(audio_manager),
+ current_default_device_id_(media::AudioManagerPowerUser(audio_manager_)
+ .GetDefaultOutputDeviceID()),
+ create_mixer_callback_(std::move(create_mixer_callback)),
+ device_change_weak_ptr_factory_(this) {
+ // This should be a static_assert, but there is no compile time way to run
+ // AudioDeviceDescription::IsDefaultDevice().
+ DCHECK(media::AudioDeviceDescription::IsDefaultDevice(
+ kNormalizedDefaultDeviceId));
+}
+
+OutputDeviceMixerManager::~OutputDeviceMixerManager() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+}
+
+media::AudioOutputStream* OutputDeviceMixerManager::MakeOutputStream(
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ base::OnceClosure close_stream_on_device_change) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (params.format() != media::AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+ DLOG(WARNING) << "Making unmixable output stream";
+
+ return CreateDeviceListenerStream(std::move(close_stream_on_device_change),
+ device_id, params);
+ }
+
+ std::string mixer_device_id = ToMixerDeviceId(device_id);
+
+ OutputDeviceMixer* mixer = FindMixer(mixer_device_id);
+
+ if (!mixer)
+ mixer = AddMixer(mixer_device_id);
+
+ // Add mixer can still fail.
+ if (!mixer)
+ return nullptr;
+
+ return mixer->MakeMixableStream(params,
+ std::move(close_stream_on_device_change));
+}
+
+void OutputDeviceMixerManager::OnDeviceChange() {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "OutputDeviceMixerManager::OnDeviceChange");
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ current_default_device_id_ =
+ media::AudioManagerPowerUser(audio_manager_).GetDefaultOutputDeviceID();
+
+ // Invalidate WeakPtrs, cancelling any pending device change callbacks
+ // generated by the same device change event.
+ device_change_weak_ptr_factory_.InvalidateWeakPtrs();
+
+ OutputDeviceMixers old_mixers;
+ output_device_mixers_.swap(old_mixers);
+
+ // Do not call StopListening(), as |old_mixers| are being destroyed anyways.
+ for (auto&& mixer : old_mixers)
+ mixer->ProcessDeviceChange();
+}
+
+void OutputDeviceMixerManager::StartNewListener(
+ ReferenceOutput::Listener* listener,
+ const std::string& device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(IsNormalizedIfDefault(device_id));
+
+ DCHECK(!listener_registration_.contains(listener));
+ listener_registration_[listener] = device_id;
+
+ OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(device_id));
+
+ if (!mixer)
+ return;
+
+ mixer->StartListening(listener);
+}
+
+void OutputDeviceMixerManager::StartListening(
+ ReferenceOutput::Listener* listener,
+ const std::string& output_device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ std::string device_id = NormalizeIfDefault(output_device_id);
+
+ if (!listener_registration_.contains(listener)) {
+ StartNewListener(listener, device_id);
+ return;
+ }
+
+ std::string registered_device_id = listener_registration_.at(listener);
+
+ if (ToMixerDeviceId(registered_device_id) != ToMixerDeviceId(device_id)) {
+ // |listener| is listening to a completely different mixer.
+ StopListening(listener);
+ StartNewListener(listener, device_id);
+ return;
+ }
+
+ // |listener| is listening to the right mixer, but we might need to update
+ // its registration (e.g. when switching between
+ // |current_default_device_id_| and kNormalizedDefaultId).
+ if (registered_device_id != device_id)
+ listener_registration_[listener] = device_id;
+}
+
+void OutputDeviceMixerManager::StopListening(
+ ReferenceOutput::Listener* listener) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ const std::string device_id = listener_registration_.at(listener);
+ listener_registration_.erase(listener);
+
+ OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(device_id));
+
+ // The mixer was never created, because there was no playback to that device
+ // (possibly after a device device change). Listening never started, so there
+ // is nothing to stop.
+ if (!mixer)
+ return;
+
+ mixer->StopListening(listener);
+}
+
+std::string OutputDeviceMixerManager::ToMixerDeviceId(
+ const std::string& device_id) {
+ if (media::AudioDeviceDescription::IsDefaultDevice(device_id))
+ return kNormalizedDefaultDeviceId;
+
+ return device_id == current_default_device_id_ ? kNormalizedDefaultDeviceId
+ : device_id;
+}
+
+OutputDeviceMixer* OutputDeviceMixerManager::FindMixer(
+ const std::string& device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(IsValidMixerId(device_id));
+
+ for (const auto& mixer : output_device_mixers_) {
+ if (mixer->device_id() == device_id)
+ return mixer.get();
+ }
+
+ return nullptr;
+}
+
+OutputDeviceMixer* OutputDeviceMixerManager::AddMixer(
+ const std::string& device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(IsValidMixerId(device_id));
+
+ DCHECK(!FindMixer(device_id));
+
+ media::AudioParameters output_params =
+ media::AudioManagerPowerUser(audio_manager_)
+ .GetOutputStreamParameters(device_id);
+
+ if (!output_params.IsValid()) {
+ LOG(ERROR) << "Adding OutputDeviceMixer failed: invalid output parameters";
+ return nullptr;
+ }
+
+ output_params.set_frames_per_buffer(media::AudioLatency::GetRtcBufferSize(
+ output_params.sample_rate(), output_params.frames_per_buffer()));
+
+ // base::Unretained(this) is safe here, because |output_device_mixers_|
+ // are owned by |this|.
+ std::unique_ptr<OutputDeviceMixer> output_device_mixer =
+ create_mixer_callback_.Run(
+ device_id, output_params,
+ base::BindRepeating(&OutputDeviceMixerManager::CreateMixerOwnedStream,
+ base::Unretained(this)),
+ audio_manager_->GetTaskRunner());
+
+ // The |device_id| might no longer be valid, e.g. if a device was unplugged.
+ if (!output_device_mixer) {
+ LOG(ERROR) << "Adding OutputDeviceMixer failed: creation error";
+ return nullptr;
+ }
+
+ auto* mixer = output_device_mixer.get();
+ output_device_mixers_.push_back(std::move(output_device_mixer));
+
+ AttachListenersById(device_id, mixer);
+
+ // We only create a single "default" mixer for both kNormalizedDefaultDeviceId
+ // and |current_default_device_id_|. If we just created this "default" mixer,
+ // also attach any listeners matching a physical |current_default_device_id_|.
+ if (device_id == kNormalizedDefaultDeviceId &&
+ current_default_device_id_ != kNormalizedDefaultDeviceId) {
+ AttachListenersById(current_default_device_id_, mixer);
+ }
+
+ return mixer;
+}
+
+void OutputDeviceMixerManager::AttachListenersById(const std::string& device_id,
+ OutputDeviceMixer* mixer) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(IsNormalizedIfDefault(device_id));
+ DCHECK(mixer);
+
+ for (auto&& listener_device_kvp : listener_registration_) {
+ if (listener_device_kvp.second == device_id)
+ mixer->StartListening(listener_device_kvp.first);
+ }
+}
+
+base::OnceClosure OutputDeviceMixerManager::GetOnDeviceChangeCallback() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ return base::BindOnce(&OutputDeviceMixerManager::OnDeviceChange,
+ device_change_weak_ptr_factory_.GetWeakPtr());
+}
+
+media::AudioOutputStream* OutputDeviceMixerManager::CreateMixerOwnedStream(
+ const std::string& device_id,
+ const media::AudioParameters& params) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ return CreateDeviceListenerStream(GetOnDeviceChangeCallback(), device_id,
+ params);
+}
+
+media::AudioOutputStream* OutputDeviceMixerManager::CreateDeviceListenerStream(
+ base::OnceClosure on_device_change_callback,
+ const std::string& device_id,
+ const media::AudioParameters& params) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ media::AudioOutputStream* stream =
+ audio_manager_->MakeAudioOutputStreamProxy(params, device_id);
+ if (!stream) {
+ LOG(ERROR) << "Stream proxy limit reached";
+ return nullptr;
+ }
+
+ // If this stream is created via CreateMixerOwnedStream(),
+ // |on_device_change_callback| will call OnDeviceChange(), cancel pending
+ // calls to OnDeviceChange(), and release all mixer owned streams.
+ //
+ // If we are directly creating this stream, |on_device_change_callback| will
+ // synchronously close the returned stream.
+ return new DeviceListenerOutputStream(audio_manager_, stream,
+ std::move(on_device_change_callback));
+}
+
+bool OutputDeviceMixerManager::IsValidMixerId(const std::string& device_id) {
+ return device_id == kNormalizedDefaultDeviceId ||
+ device_id != current_default_device_id_;
+}
+
+bool OutputDeviceMixerManager::IsNormalizedIfDefault(
+ const std::string& device_id) {
+ return device_id == kNormalizedDefaultDeviceId ||
+ !media::AudioDeviceDescription::IsDefaultDevice(device_id);
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/output_device_mixer_manager.h b/chromium/services/audio/output_device_mixer_manager.h
new file mode 100644
index 00000000000..38f24eef3c4
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer_manager.h
@@ -0,0 +1,117 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_MANAGER_H_
+#define SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_MANAGER_H_
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "media/base/audio_parameters.h"
+#include "services/audio/device_output_listener.h"
+#include "services/audio/output_device_mixer.h"
+#include "services/audio/reference_output.h"
+
+namespace media {
+class AudioManager;
+class AudioOutputStream;
+} // namespace media
+
+namespace audio {
+
+// Creates OutputDeviceMixers as needed, when playback is requested through
+// MakeOutputStream(). OutputDeviceMixers are destroyed on device change, or
+// when the Audio service shuts down, but are not cleaned up otherwise.
+// Listening to a device has no effect, until that device's OutputDeviceMixer is
+// created and playback has started.
+class OutputDeviceMixerManager : public DeviceOutputListener {
+ public:
+ OutputDeviceMixerManager(
+ media::AudioManager* audio_manager,
+ OutputDeviceMixer::CreateCallback create_mixer_callback);
+ OutputDeviceMixerManager(const OutputDeviceMixerManager&) = delete;
+ OutputDeviceMixerManager& operator=(const OutputDeviceMixerManager&) = delete;
+ ~OutputDeviceMixerManager() override;
+
+ // Makes an output stream for the given output device.
+ // The returned stream must be closed synchronously from
+ // |close_stream_on_device_change|.
+ media::AudioOutputStream* MakeOutputStream(
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ base::OnceClosure close_stream_on_device_change);
+
+ // DeviceOutputListener implementation
+ void StartListening(ReferenceOutput::Listener* listener,
+ const std::string& device_id) final;
+ void StopListening(ReferenceOutput::Listener* listener) final;
+
+ private:
+ friend class OutputDeviceMixerManagerTest;
+
+ using OutputDeviceMixers = std::vector<std::unique_ptr<OutputDeviceMixer>>;
+ using ListenerToDeviceMap =
+ base::flat_map<base::raw_ptr<ReferenceOutput::Listener>, std::string>;
+
+ // Forwards device change notifications to OutputDeviceMixers.
+ void OnDeviceChange();
+
+ // Helper function which merges "default IDs" (as defined by
+ // AudioDeviceDescription::IsDefaultId()) and physical IDs matching
+ // GetCurrentDefaultPhysicalDeviceIdOrEmpty() into the same normalized default
+ // ID. This guarantees we create a single "default ID" OutputDeviceMixer.
+ std::string ToMixerDeviceId(const std::string& device_id);
+
+ // Returns a callback that call OnDeviceChange(), and that can be cancelled
+ // through invalidating |device_change_weak_ptr_factory_|.
+ // This is split out into its own method to simplify UTs.
+ base::OnceClosure GetOnDeviceChangeCallback();
+
+ media::AudioOutputStream* CreateMixerOwnedStream(
+ const std::string& device_id,
+ const media::AudioParameters& params);
+
+ media::AudioOutputStream* CreateDeviceListenerStream(
+ base::OnceClosure on_device_change_callback,
+ const std::string& device_id,
+ const media::AudioParameters& params);
+
+ void AttachListenersById(const std::string& device_id,
+ OutputDeviceMixer* mixer);
+
+ // Returns a mixer if it exists, or nullptr otherwise.
+ OutputDeviceMixer* FindMixer(const std::string& physical_device_id);
+
+ // Creates and returns a new mixer, or nullptr if the creation failed.
+ OutputDeviceMixer* AddMixer(const std::string& physical_device_id);
+
+ void StartNewListener(ReferenceOutput::Listener* listener,
+ const std::string& device_id);
+
+ bool IsValidMixerId(const std::string& device_id);
+ bool IsNormalizedIfDefault(const std::string& device_id);
+
+ SEQUENCE_CHECKER(owning_sequence_);
+ const raw_ptr<media::AudioManager> audio_manager_;
+
+ // Physical device ID of the current default device, or kNormalizedDefaultId
+ // if not supported by the platform.
+ std::string current_default_device_id_;
+
+ OutputDeviceMixer::CreateCallback create_mixer_callback_;
+ OutputDeviceMixers output_device_mixers_;
+ ListenerToDeviceMap listener_registration_;
+ base::WeakPtrFactory<OutputDeviceMixerManager> device_change_weak_ptr_factory_
+ GUARDED_BY_CONTEXT(owning_sequence_);
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_MANAGER_H_
diff --git a/chromium/services/audio/output_device_mixer_manager_unittest.cc b/chromium/services/audio/output_device_mixer_manager_unittest.cc
new file mode 100644
index 00000000000..906edddb22b
--- /dev/null
+++ b/chromium/services/audio/output_device_mixer_manager_unittest.cc
@@ -0,0 +1,1201 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/output_device_mixer_manager.h"
+
+#include "base/test/bind.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/task_environment.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/mock_audio_manager.h"
+#include "media/audio/test_audio_thread.h"
+#include "media/base/audio_parameters.h"
+#include "services/audio/output_device_mixer.h"
+#include "services/audio/reference_output.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using ::testing::_;
+using ::testing::ByMove;
+using ::testing::Eq;
+using ::testing::InSequence;
+using ::testing::NiceMock;
+using ::testing::Ref;
+using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::StrictMock;
+
+using media::AudioOutputStream;
+using media::AudioParameters;
+
+using base::test::RunOnceClosure;
+
+namespace audio {
+namespace {
+
+// Matches non-null device change callbacks.
+MATCHER(ValidDeviceChangeCallback, "") {
+ return !arg.is_null();
+}
+
+// Matches an expected media::AudioParameters.
+MATCHER_P(ExactParams, expected, "") {
+ return expected.Equals(arg);
+}
+
+// Matches media::AudioParameters that are equal in all aspects,
+// except for sample_per_buffer()
+MATCHER_P(CompatibleParams, expected, "") {
+ return expected.format() == arg.format() &&
+ expected.channel_layout() == arg.channel_layout() &&
+ expected.channels() == arg.channels() &&
+ expected.effects() == arg.effects() &&
+ expected.mic_positions() == arg.mic_positions() &&
+ expected.latency_tag() == arg.latency_tag();
+}
+
+const std::string kFakeDeviceId = "0x1234";
+const std::string kOtherFakeDeviceId = "0x9876";
+const std::string kEmptyDeviceId = std::string();
+const std::string kNormalizedDefaultDeviceId = kEmptyDeviceId;
+const auto* kDefaultDeviceId = media::AudioDeviceDescription::kDefaultDeviceId;
+
+class MockAudioOutputStream : public AudioOutputStream {
+ public:
+ MockAudioOutputStream() = default;
+ ~MockAudioOutputStream() override = default;
+
+ MOCK_METHOD1(Start, void(AudioOutputStream::AudioSourceCallback*));
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD0(Open, bool());
+ MOCK_METHOD1(SetVolume, void(double volume));
+ MOCK_METHOD1(GetVolume, void(double* volume));
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(Flush, void());
+};
+
+class LocalMockAudioManager : public media::MockAudioManager {
+ public:
+ LocalMockAudioManager()
+ : media::MockAudioManager(
+ std::make_unique<media::TestAudioThread>(false)) {}
+ ~LocalMockAudioManager() override = default;
+
+ MOCK_METHOD(std::string, GetDefaultOutputDeviceID, (), (override));
+ MOCK_METHOD(AudioParameters,
+ GetOutputStreamParameters,
+ (const std::string&),
+ (override));
+ MOCK_METHOD(AudioParameters,
+ GetDefaultOutputStreamParameters,
+ (),
+ (override));
+
+ MOCK_METHOD(AudioOutputStream*,
+ MakeAudioOutputStreamProxy,
+ (const media::AudioParameters&, const std::string&),
+ (override));
+};
+
+class MockListener : public audio::ReferenceOutput::Listener {
+ public:
+ MockListener() = default;
+ ~MockListener() override = default;
+
+ MOCK_METHOD(void,
+ OnPlayoutData,
+ (const media::AudioBus&, int, base::TimeDelta),
+ (override));
+};
+
+class MockOutputDeviceMixer : public audio::OutputDeviceMixer {
+ public:
+ explicit MockOutputDeviceMixer(const std::string& device_id)
+ : OutputDeviceMixer(device_id) {}
+ ~MockOutputDeviceMixer() override = default;
+
+ MOCK_METHOD(media::AudioOutputStream*,
+ MakeMixableStream,
+ (const AudioParameters&, base::OnceClosure),
+ (override));
+ MOCK_METHOD(void, ProcessDeviceChange, (), (override));
+
+ MOCK_METHOD(void, StartListening, (Listener*), (override));
+ MOCK_METHOD(void, StopListening, (Listener*), (override));
+};
+} // namespace
+
+class OutputDeviceMixerManagerTest
+ : public ::testing::TestWithParam<std::string> {
+ public:
+ OutputDeviceMixerManagerTest()
+ : current_default_physical_device_id_(kFakeDeviceId),
+ default_params_(AudioParameters::Format::AUDIO_PCM_LOW_LATENCY,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
+ /*sample_rate=*/8000,
+ /*frames_per_buffer=*/800),
+ output_mixer_manager_(
+ &audio_manager_,
+ base::BindRepeating(
+ &OutputDeviceMixerManagerTest::CreateOutputDeviceMixerCalled,
+ base::Unretained(this))) {
+ EXPECT_CALL(audio_manager_, GetOutputStreamParameters(_))
+ .WillRepeatedly(Return(default_params_));
+
+ EXPECT_CALL(audio_manager_, GetDefaultOutputStreamParameters())
+ .WillRepeatedly(Return(default_params_));
+
+ EXPECT_CALL(audio_manager_, GetDefaultOutputDeviceID()).WillRepeatedly([&] {
+ return audio_manager_supports_default_physical_id_
+ ? current_default_physical_device_id_
+ : kEmptyDeviceId;
+ });
+
+ // Force |output_mixer_manager_| to pick up the latest default device ID
+ // from AudioManager::GetDefaultOutputDeviceID().
+ output_mixer_manager_.OnDeviceChange();
+ }
+
+ ~OutputDeviceMixerManagerTest() override { audio_manager_.Shutdown(); }
+
+ MOCK_METHOD(std::unique_ptr<OutputDeviceMixer>,
+ CreateOutputDeviceMixerCalled,
+ (const std::string&,
+ const media::AudioParameters&,
+ OutputDeviceMixer::CreateStreamCallback,
+ scoped_refptr<base::SingleThreadTaskRunner>));
+
+ protected:
+ std::string current_default_physical_device() {
+ return current_default_physical_device_id_;
+ }
+
+ void SetAudioManagerGetDefaultOutputDeviceIdSupport(bool support) {
+ bool needs_device_change =
+ audio_manager_supports_default_physical_id_ != support;
+ audio_manager_supports_default_physical_id_ = support;
+
+ // Force |output_mixer_manager_| to pick up the latest default device ID.
+ if (needs_device_change)
+ output_mixer_manager_.OnDeviceChange();
+ }
+
+ MockOutputDeviceMixer* SetUpMockMixerCreation(
+ std::string device_id = kNormalizedDefaultDeviceId) {
+ auto mock_output_mixer =
+ std::make_unique<NiceMock<MockOutputDeviceMixer>>(device_id);
+ MockOutputDeviceMixer* mixer = mock_output_mixer.get();
+
+ EXPECT_CALL(*this, CreateOutputDeviceMixerCalled(
+ device_id, CompatibleParams(default_params_), _, _))
+ .WillOnce(Return(ByMove(std::move(mock_output_mixer))));
+
+ return mixer;
+ }
+
+ // Sets up a mock OutputDeviceMixer for creation, which will only return
+ // nullptr when creating streams.
+ MockOutputDeviceMixer* SetUpMockMixer_NoStreams(
+ std::string device_id = kNormalizedDefaultDeviceId) {
+ MockOutputDeviceMixer* output_mixer = SetUpMockMixerCreation(device_id);
+
+ EXPECT_CALL(*output_mixer, MakeMixableStream(_, _))
+ .WillRepeatedly(Return(nullptr));
+
+ return output_mixer;
+ }
+
+ std::unique_ptr<NiceMock<MockListener>> GetListener_MixerExpectsStartStop(
+ MockOutputDeviceMixer* mixer) {
+ return GetListenerWithStartStopExpectations(mixer, 1, 1);
+ }
+
+ std::unique_ptr<NiceMock<MockListener>> GetListener_MixerExpectsStart(
+ MockOutputDeviceMixer* mixer) {
+ return GetListenerWithStartStopExpectations(mixer, 1, 0);
+ }
+
+ std::unique_ptr<NiceMock<MockListener>> GetListener_MixerExpectsNoCalls(
+ MockOutputDeviceMixer* mixer) {
+ return GetListenerWithStartStopExpectations(mixer, 0, 0);
+ }
+
+ void ForceOutputMixerCreation(const std::string& device_id) {
+ output_mixer_manager_.MakeOutputStream(device_id, default_params_,
+ GetNoopDeviceChangeCallback());
+ }
+
+ void SimulateDeviceChange(
+ absl::optional<std::string> new_default_physical_device = absl::nullopt) {
+ if (new_default_physical_device)
+ current_default_physical_device_id_ = *new_default_physical_device;
+
+ output_mixer_manager_.OnDeviceChange();
+ }
+
+ void ExpectNoMixerCreated() {
+ EXPECT_CALL(*this, CreateOutputDeviceMixerCalled(_, _, _, _)).Times(0);
+ }
+
+ base::OnceClosure GetOnDeviceChangeCallback() {
+ return output_mixer_manager_.GetOnDeviceChangeCallback();
+ }
+
+ // Syntactic sugar, to differentiate from base::OnceClosure in tests.
+ base::OnceClosure GetNoopDeviceChangeCallback() { return base::DoNothing(); }
+
+ bool audio_manager_supports_default_physical_id_ = true;
+
+ // Simulate the value that would be returned by
+ // AudioManager::GetDefaultOutputDeviceId() if it is supported.
+ std::string current_default_physical_device_id_;
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ AudioParameters default_params_;
+ NiceMock<LocalMockAudioManager> audio_manager_;
+ OutputDeviceMixerManager output_mixer_manager_;
+
+ private:
+ std::unique_ptr<NiceMock<MockListener>> GetListenerWithStartStopExpectations(
+ MockOutputDeviceMixer* mixer,
+ int starts,
+ int stops) {
+ auto listener = std::make_unique<NiceMock<MockListener>>();
+
+ auto* listener_ptr = listener.get();
+
+ EXPECT_CALL(*mixer, StartListening(listener_ptr)).Times(starts);
+ EXPECT_CALL(*mixer, StopListening(listener_ptr)).Times(stops);
+
+ return listener;
+ }
+};
+
+// Makes sure we can create an output stream for the default output device.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_ForDefaultDevice) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream));
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kDefaultDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_EQ(&mock_stream, out_stream);
+}
+
+// Makes sure we can create a default output stream when AudioManager doesn't
+// support getting the current default ID.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_ForDefaultDevice_NoGetDefaultOuputDeviceIdSupport) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream));
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kDefaultDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_EQ(&mock_stream, out_stream);
+}
+
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_ForDefaultDevice_EmptyDeviceId) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream));
+
+ // kEmptyDeviceId should be treated the same as kDefaultDeviceId.
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kEmptyDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_EQ(&mock_stream, out_stream);
+}
+
+// Makes sure we can create an output stream for a device ID that happens to be
+// the current default.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_ForSpecificDeviceId_IdIsDefault) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(true);
+
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream));
+
+ // Getting a stream for current_default_physical_device() should create
+ // the |default_mixer| instead of a mixer for that physical ID.
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ current_default_physical_device(), default_params_,
+ GetNoopDeviceChangeCallback());
+
+ EXPECT_EQ(&mock_stream, out_stream);
+}
+
+// Makes sure we can create an output stream for a device ID when
+// AudioManager::GetDefaultOutputDeviceId() is unsupported.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_ForSpecificDeviceId_NoGetDefaultOuputDeviceIdSupport) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ // A mixer for the physical device ID should be created, instead of the
+ // default mixer.
+ MockOutputDeviceMixer* physical_device_mixer =
+ SetUpMockMixerCreation(current_default_physical_device());
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(*physical_device_mixer,
+ MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream));
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ current_default_physical_device(), default_params_,
+ GetNoopDeviceChangeCallback());
+
+ EXPECT_EQ(&mock_stream, out_stream);
+}
+
+// Makes sure we can create an output stream a device ID for a device that is
+// not the default device.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_ForSpecificDeviceId_IdIsNotDefaultOutput) {
+ ASSERT_NE(kOtherFakeDeviceId, current_default_physical_device());
+
+ MockOutputDeviceMixer* mock_mixer =
+ SetUpMockMixerCreation(kOtherFakeDeviceId);
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(*mock_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream));
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kOtherFakeDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_EQ(&mock_stream, out_stream);
+}
+
+// Makes sure we get the correct output parameters from the AudioManager when
+// creating streams.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_GetsDeviceOrDefaultParams) {
+ // Reset default test setup expectations.
+ testing::Mock::VerifyAndClearExpectations(&audio_manager_);
+
+ SetUpMockMixerCreation();
+
+ EXPECT_CALL(audio_manager_, GetOutputStreamParameters(_)).Times(0);
+ EXPECT_CALL(audio_manager_, GetDefaultOutputStreamParameters())
+ .WillOnce(Return(default_params_));
+
+ output_mixer_manager_.MakeOutputStream(kDefaultDeviceId, default_params_,
+ GetNoopDeviceChangeCallback());
+
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(&audio_manager_);
+
+ SetUpMockMixerCreation(kOtherFakeDeviceId);
+
+ EXPECT_CALL(audio_manager_, GetDefaultOutputStreamParameters()).Times(0);
+ EXPECT_CALL(audio_manager_, GetOutputStreamParameters(kOtherFakeDeviceId))
+ .WillOnce(Return(default_params_));
+
+ output_mixer_manager_.MakeOutputStream(kOtherFakeDeviceId, default_params_,
+ GetNoopDeviceChangeCallback());
+}
+
+// Makes sure we still get an unmixable stream when requesting bitstream
+// formats.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_WithBitstreamFormat) {
+ ExpectNoMixerCreated();
+
+ MockAudioOutputStream mock_stream;
+ EXPECT_CALL(audio_manager_, MakeAudioOutputStreamProxy(_, _))
+ .WillOnce(Return(&mock_stream));
+
+ AudioParameters bitstream_params{AudioParameters::Format::AUDIO_BITSTREAM_AC3,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
+ /*sample_rate=*/8000,
+ /*frames_per_buffer=*/800};
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kOtherFakeDeviceId, bitstream_params, GetNoopDeviceChangeCallback());
+
+ EXPECT_TRUE(out_stream);
+
+ // Test cleanup.
+ out_stream->Close();
+}
+
+// Makes sure we handle running out of stream proxies.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_MaxProxies) {
+ ExpectNoMixerCreated();
+
+ EXPECT_CALL(audio_manager_, MakeAudioOutputStreamProxy(_, _))
+ .WillOnce(Return(nullptr));
+
+ // We use bitstream parameters to simplify hitting a portion of the code that
+ // creates an AudioOutputStream directly.
+ AudioParameters bitstream_params{AudioParameters::Format::AUDIO_BITSTREAM_AC3,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
+ /*sample_rate=*/8000,
+ /*frames_per_buffer=*/800};
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kOtherFakeDeviceId, bitstream_params, GetNoopDeviceChangeCallback());
+
+ EXPECT_FALSE(out_stream);
+}
+
+// Makes sure we handle failing to create a mixer.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_MixerCreationFails) {
+ EXPECT_CALL(*this, CreateOutputDeviceMixerCalled(
+ kNormalizedDefaultDeviceId,
+ CompatibleParams(default_params_), _, _))
+ .WillOnce(Return(ByMove(nullptr)));
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kDefaultDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_FALSE(out_stream);
+}
+
+// Makes sure we handle the case when the output mixer returns a nullptr when
+// creating a stream.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_MixerReturnsNull) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(nullptr));
+
+ AudioOutputStream* out_stream = output_mixer_manager_.MakeOutputStream(
+ kDefaultDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_FALSE(out_stream);
+}
+
+// Makes sure creating multiple output streams for the same device ID re-uses
+// the same OutputDeviceMixer.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_OneMixerPerId) {
+ MockOutputDeviceMixer* physical_id_mixer =
+ SetUpMockMixerCreation(kOtherFakeDeviceId);
+
+ MockAudioOutputStream mock_stream_a;
+ MockAudioOutputStream mock_stream_b;
+ EXPECT_CALL(*physical_id_mixer,
+ MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream_b))
+ .WillOnce(Return(&mock_stream_a));
+
+ // This call should create an OutputDeviceMixer.
+ AudioOutputStream* out_stream_a = output_mixer_manager_.MakeOutputStream(
+ kOtherFakeDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ // This call should re-use the OutputDeviceMixer.
+ AudioOutputStream* out_stream_b = output_mixer_manager_.MakeOutputStream(
+ kOtherFakeDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_NE(out_stream_a, out_stream_b);
+}
+
+// Makes sure creating an output stream for the "default ID" or the
+// "current default device" is equivalent, and the mixer are shared.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_DefaultIdAndCurrentDefaultShareOneMixer) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ MockAudioOutputStream mock_stream_a;
+ MockAudioOutputStream mock_stream_b;
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream_b))
+ .WillOnce(Return(&mock_stream_a));
+
+ // This call should create an OutputDeviceMixer.
+ AudioOutputStream* out_stream_a = output_mixer_manager_.MakeOutputStream(
+ current_default_physical_device(), default_params_,
+ GetNoopDeviceChangeCallback());
+
+ // This call should re-use the same OutputDeviceMixer.
+ AudioOutputStream* out_stream_b = output_mixer_manager_.MakeOutputStream(
+ kDefaultDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_NE(out_stream_a, out_stream_b);
+}
+
+// Makes sure we create one output mixer per device ID.
+TEST_F(OutputDeviceMixerManagerTest, MakeOutputStream_TwoDevicesTwoMixers) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ InSequence s;
+ MockOutputDeviceMixer* mock_mixer_a = SetUpMockMixerCreation(kFakeDeviceId);
+
+ MockAudioOutputStream mock_stream_a;
+ EXPECT_CALL(*mock_mixer_a, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream_a));
+
+ MockOutputDeviceMixer* mock_mixer_b =
+ SetUpMockMixerCreation(kOtherFakeDeviceId);
+
+ MockAudioOutputStream mock_stream_b;
+ EXPECT_CALL(*mock_mixer_b, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&mock_stream_b));
+
+ // Create the first OutputDeviceMixer.
+ AudioOutputStream* out_stream_a = output_mixer_manager_.MakeOutputStream(
+ kFakeDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ // Create a second OutputDeviceMixer.
+ AudioOutputStream* out_stream_b = output_mixer_manager_.MakeOutputStream(
+ kOtherFakeDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_NE(out_stream_a, out_stream_b);
+}
+
+// Makes sure the default mixer is separate from other mixers.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_DefaultMixerDistinctFromOtherMixers) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ InSequence s;
+ MockOutputDeviceMixer* fake_device_mixer =
+ SetUpMockMixerCreation(kFakeDeviceId);
+
+ MockAudioOutputStream fake_stream;
+ EXPECT_CALL(*fake_device_mixer,
+ MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&fake_stream));
+
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixerCreation();
+
+ MockAudioOutputStream default_stream;
+ EXPECT_CALL(*default_mixer, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&default_stream));
+
+ // Create the first OutputDeviceMixer.
+ AudioOutputStream* out_stream_a = output_mixer_manager_.MakeOutputStream(
+ kFakeDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ // Create a second OutputDeviceMixer.
+ AudioOutputStream* out_stream_b = output_mixer_manager_.MakeOutputStream(
+ kDefaultDeviceId, default_params_, GetNoopDeviceChangeCallback());
+
+ EXPECT_NE(out_stream_a, out_stream_b);
+}
+
+// Makes sure we get the latest default device ID each time we create a stream
+// for the default device ID.
+TEST_F(OutputDeviceMixerManagerTest,
+ MakeOutputStream_CurrentDefaultIsUpdatedAfterDeviceChange) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(true);
+
+ MockOutputDeviceMixer* default_mixer_a = SetUpMockMixerCreation();
+
+ MockAudioOutputStream default_stream_a;
+ EXPECT_CALL(*default_mixer_a, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&default_stream_a));
+
+ // Force the creation of |default_mixer_a|.
+ AudioOutputStream* out_stream_a = output_mixer_manager_.MakeOutputStream(
+ current_default_physical_device(), default_params_,
+ GetNoopDeviceChangeCallback());
+
+ // Update the current default physical device.
+ ASSERT_NE(current_default_physical_device(), kOtherFakeDeviceId);
+ SimulateDeviceChange(/*new_default_physical_device=*/kOtherFakeDeviceId);
+ ASSERT_EQ(current_default_physical_device(), kOtherFakeDeviceId);
+
+ testing::Mock::VerifyAndClearExpectations(this);
+
+ MockOutputDeviceMixer* default_mixer_b = SetUpMockMixerCreation();
+
+ MockAudioOutputStream default_stream_b;
+ EXPECT_CALL(*default_mixer_b, MakeMixableStream(ExactParams(default_params_),
+ ValidDeviceChangeCallback()))
+ .WillOnce(Return(&default_stream_b));
+
+ // Force the creation of |default_mixer_b|, with a new
+ // current_default_physical_device().
+ AudioOutputStream* out_stream_b = output_mixer_manager_.MakeOutputStream(
+ current_default_physical_device(), default_params_,
+ GetNoopDeviceChangeCallback());
+
+ EXPECT_NE(out_stream_a, out_stream_b);
+}
+
+// Makes sure OutputDeviceMixers are notified of device changes.
+TEST_F(OutputDeviceMixerManagerTest,
+ OnDeviceChange_MixersReceiveDeviceChanges) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ // We don't care about the streams these devices will create.
+ InSequence s;
+ MockOutputDeviceMixer* pre_mock_mixer_a =
+ SetUpMockMixer_NoStreams(kFakeDeviceId);
+ MockOutputDeviceMixer* pre_mock_mixer_b =
+ SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+ MockOutputDeviceMixer* pre_mock_mixer_c =
+ SetUpMockMixer_NoStreams(kNormalizedDefaultDeviceId);
+
+ EXPECT_CALL(*pre_mock_mixer_a, ProcessDeviceChange()).Times(1);
+ EXPECT_CALL(*pre_mock_mixer_b, ProcessDeviceChange()).Times(1);
+ EXPECT_CALL(*pre_mock_mixer_c, ProcessDeviceChange()).Times(1);
+
+ // Create the OutputDeviceMixers.
+ output_mixer_manager_.MakeOutputStream(kFakeDeviceId, default_params_,
+ GetNoopDeviceChangeCallback());
+
+ output_mixer_manager_.MakeOutputStream(kOtherFakeDeviceId, default_params_,
+ GetNoopDeviceChangeCallback());
+
+ output_mixer_manager_.MakeOutputStream(kDefaultDeviceId, default_params_,
+ GetNoopDeviceChangeCallback());
+
+ // Trigger the calls to ProcessDeviceChange()
+ SimulateDeviceChange();
+}
+
+// Makes sure OnDeviceChange() is only called once per device change.
+TEST_F(OutputDeviceMixerManagerTest, OnDeviceChange_OncePerDeviceChange) {
+ // Setup a mixer that expects exactly 1 device change.
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+ EXPECT_CALL(*default_mixer, ProcessDeviceChange()).Times(1);
+
+ // Create the mixer.
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ auto first_device_change_callback = GetOnDeviceChangeCallback();
+ auto second_device_change_callback = GetOnDeviceChangeCallback();
+
+ // |default_mixer| be notified of the device change.
+ std::move(first_device_change_callback).Run();
+ testing::Mock::VerifyAndClearExpectations(default_mixer);
+
+ // Setup a new mixer.
+ testing::Mock::VerifyAndClearExpectations(this);
+ MockOutputDeviceMixer* new_default_mixer = SetUpMockMixer_NoStreams();
+
+ // Make sure old callbacks don't trigger new device change events.
+ EXPECT_CALL(*new_default_mixer, ProcessDeviceChange()).Times(0);
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ std::move(second_device_change_callback).Run();
+
+ testing::Mock::VerifyAndClearExpectations(new_default_mixer);
+
+ // Make sure the new mixer gets notified of changes through this new
+ // callback.
+ EXPECT_CALL(*new_default_mixer, ProcessDeviceChange()).Times(1);
+ GetOnDeviceChangeCallback().Run();
+}
+
+// Attach/detach listeners with no mixer.
+TEST_F(OutputDeviceMixerManagerTest, DeviceOutputListener_StartStop) {
+ ExpectNoMixerCreated();
+
+ StrictMock<MockListener> listener;
+
+ // Attach/detach multiple listeners to/from multiple devices.
+ output_mixer_manager_.StartListening(&listener, kFakeDeviceId);
+ output_mixer_manager_.StopListening(&listener);
+}
+
+// Attach/detach listeners to multiple devices with no mixers.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartStop_MultipleDevice) {
+ ExpectNoMixerCreated();
+
+ StrictMock<MockListener> listener_a;
+ StrictMock<MockListener> listener_b;
+
+ output_mixer_manager_.StartListening(&listener_a, kFakeDeviceId);
+ output_mixer_manager_.StartListening(&listener_b, kOtherFakeDeviceId);
+
+ output_mixer_manager_.StopListening(&listener_a);
+ output_mixer_manager_.StopListening(&listener_b);
+}
+
+// Attach/detach multiple listeners to a single device with no mixer.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartStop_MultipleListener) {
+ ExpectNoMixerCreated();
+
+ StrictMock<MockListener> listener_a;
+ StrictMock<MockListener> listener_b;
+
+ output_mixer_manager_.StartListening(&listener_a, kFakeDeviceId);
+ output_mixer_manager_.StartListening(&listener_b, kFakeDeviceId);
+
+ output_mixer_manager_.StopListening(&listener_a);
+ output_mixer_manager_.StopListening(&listener_b);
+}
+
+// Attach/detach to the default device.
+TEST_F(OutputDeviceMixerManagerTest, DeviceOutputListener_StartStop_DefaultId) {
+ ExpectNoMixerCreated();
+
+ StrictMock<MockListener> listener;
+
+ output_mixer_manager_.StartListening(&listener, kDefaultDeviceId);
+ output_mixer_manager_.StopListening(&listener);
+}
+
+// Listeners are attached as they are added.
+TEST_F(OutputDeviceMixerManagerTest, DeviceOutputListener_CreateStartStop) {
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+
+ auto listener = GetListener_MixerExpectsStartStop(mixer);
+
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+ output_mixer_manager_.StartListening(listener.get(), kOtherFakeDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Listeners are attached on mixer creation.
+TEST_F(OutputDeviceMixerManagerTest, DeviceOutputListener_StartCreateStop) {
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+
+ auto listener = GetListener_MixerExpectsStartStop(mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kOtherFakeDeviceId);
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Removed listeners are not attached.
+TEST_F(OutputDeviceMixerManagerTest, DeviceOutputListener_StartStopCreate) {
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+
+ auto listener = GetListener_MixerExpectsNoCalls(mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kOtherFakeDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+}
+
+// Listeners are attached as they are added.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_CreateStartStop_NoGetDefaultOuputDeviceIdSupport) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kFakeDeviceId);
+
+ auto listener = GetListener_MixerExpectsStartStop(mixer);
+
+ ForceOutputMixerCreation(kFakeDeviceId);
+ output_mixer_manager_.StartListening(listener.get(), kFakeDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Listeners are attached on mixer creation.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartCreateStop_NoGetDefaultOuputDeviceIdSupport) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kFakeDeviceId);
+
+ auto listener = GetListener_MixerExpectsStartStop(mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kFakeDeviceId);
+ ForceOutputMixerCreation(kFakeDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Removed listeners are not attached.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartStopCreate_NoGetDefaultOuputDeviceIdSupport) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kFakeDeviceId);
+
+ auto listener = GetListener_MixerExpectsNoCalls(mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kFakeDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+ ForceOutputMixerCreation(kFakeDeviceId);
+}
+
+// Removed listeners are not attached, and remaining listeners are.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartStopCreate_TwoListeners) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStart(default_mixer);
+ auto removed_listener = GetListener_MixerExpectsNoCalls(default_mixer);
+
+ output_mixer_manager_.StartListening(listener.get(),
+ current_default_physical_device());
+ output_mixer_manager_.StartListening(removed_listener.get(),
+ current_default_physical_device());
+ output_mixer_manager_.StopListening(removed_listener.get());
+ ForceOutputMixerCreation(current_default_physical_device());
+}
+
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_CreateStartStop_DefaultId) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartCreateStop_DefaultId) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_StartCreateStop_DefaultId_EmptyDeviceId) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+
+ // kEmptyDeviceId should be treated the same as kDefaultDeviceId.
+ output_mixer_manager_.StartListening(listener.get(), kEmptyDeviceId);
+ ForceOutputMixerCreation(kEmptyDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Makes sure default-listeners are attached to the default-mixer when it is
+// created via current_default_physical_device().
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_DefaultIdListenersAttachToCurrentDefaultMixer) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+ ForceOutputMixerCreation(current_default_physical_device());
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Makes sure current_default_physical_device() listeners are attached when the
+// default-mixer is created.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_CurrentDefaultListenersAttachToDefaultIdMixer) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+
+ output_mixer_manager_.StartListening(listener.get(),
+ current_default_physical_device());
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Makes sure the presence of listeners does not force device recreation
+// on device change.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_NoCreateAfterDeviceChange_WithListeners) {
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+
+ // |mixer| should never get a call to StopListening(|listener|).
+ auto listener = GetListener_MixerExpectsStart(mixer);
+
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+ output_mixer_manager_.StartListening(listener.get(), kOtherFakeDeviceId);
+
+ SimulateDeviceChange();
+
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Makes sure listeners are re-attached when mixers are recreated.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_ListenersReattachedAfterDeviceChange) {
+ MockOutputDeviceMixer* mixer = SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+
+ // |mixer| should never get a call to StopListening(|listener|).
+ auto listener = GetListener_MixerExpectsStart(mixer);
+
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+ output_mixer_manager_.StartListening(listener.get(), kOtherFakeDeviceId);
+
+ SimulateDeviceChange();
+
+ // Clear expectations so we can set up new ones.
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(listener.get());
+
+ // The same |listener| should be started when |new_mixer| is created.
+ MockOutputDeviceMixer* new_mixer =
+ SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+ EXPECT_CALL(*new_mixer, StartListening(listener.get())).Times(1);
+
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+}
+
+// Makes sure the default listeners are re-attached when mixers are
+// re-created.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_DefaultIdListenersReattachedAfterDeviceChange) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(true);
+
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ auto listener = GetListener_MixerExpectsStart(default_mixer);
+
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+
+ // |listener| will be started when |default_mixer| is created.
+ ForceOutputMixerCreation(current_default_physical_device());
+
+ // Make sure the AudioManager::GetDefaultOutputDeviceId() returns a new value.
+ ASSERT_NE(current_default_physical_device(), kOtherFakeDeviceId);
+ SimulateDeviceChange(/*new_default_physical_device=*/kOtherFakeDeviceId);
+
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(listener.get());
+
+ // |listener| should be attached to |new_default_mixer| when it is created.
+ MockOutputDeviceMixer* new_default_mixer = SetUpMockMixer_NoStreams();
+ EXPECT_CALL(*new_default_mixer, StartListening(listener.get())).Times(1);
+
+ ASSERT_EQ(kOtherFakeDeviceId, current_default_physical_device());
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+}
+
+// Makes sure the default listeners are not attached to non-default listeners,
+// if support for AudioManager::GetDefaultOutputDeviceId() changes.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_CurrentDefaultListenersNotReattached) {
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(true);
+
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ // |default_mixer| should never get a call to StopListening(|listener|).
+ auto listener = GetListener_MixerExpectsStart(default_mixer);
+
+ output_mixer_manager_.StartListening(listener.get(),
+ current_default_physical_device());
+
+ // |listener| should be attached to |mixer|.
+ ForceOutputMixerCreation(kDefaultDeviceId);
+
+ SetAudioManagerGetDefaultOutputDeviceIdSupport(false);
+ SimulateDeviceChange();
+
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(listener.get());
+
+ // Now that AudioManager::GetDefaultOutputDeviceId() only returns
+ // kEmptyDeviceId, |listener| should not be attached to |new_default_mixer|.
+ MockOutputDeviceMixer* new_default_mixer = SetUpMockMixer_NoStreams();
+ EXPECT_CALL(*new_default_mixer, StartListening(listener.get())).Times(0);
+
+ ForceOutputMixerCreation(kDefaultDeviceId);
+
+ testing::Mock::VerifyAndClearExpectations(this);
+ testing::Mock::VerifyAndClearExpectations(listener.get());
+
+ // |listener| should still be attached to |new_physical_mixer| when it's
+ // created after a device change.
+ MockOutputDeviceMixer* new_physical_mixer =
+ SetUpMockMixer_NoStreams(current_default_physical_device());
+ EXPECT_CALL(*new_physical_mixer, StartListening(listener.get())).Times(1);
+
+ // |listener| should be attached to |new_physical_mixer|.
+ ForceOutputMixerCreation(current_default_physical_device());
+}
+
+// Makes sure both "default listeners" and "current_default_physical_device()
+// listeners" get attached to the same current_default_physical_device() mixer.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_CurrentDefaultMixerCreation_ListenersAttached) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ // Create listeners for kDefaultDeviceId and
+ // current_default_physical_device(), BOTH listening to |default_mixer|.
+ auto default_listener = GetListener_MixerExpectsStart(default_mixer);
+ auto current_default_physical_listener =
+ GetListener_MixerExpectsStart(default_mixer);
+
+ // Create another listener, NOT listening to |default_mixer|.
+ ASSERT_NE(kOtherFakeDeviceId, current_default_physical_device());
+ auto other_listener = GetListener_MixerExpectsNoCalls(default_mixer);
+
+ // Start all listeners.
+ output_mixer_manager_.StartListening(default_listener.get(),
+ kDefaultDeviceId);
+ output_mixer_manager_.StartListening(current_default_physical_listener.get(),
+ current_default_physical_device());
+ output_mixer_manager_.StartListening(other_listener.get(),
+ kOtherFakeDeviceId);
+
+ // |default_listener| and |current_default_physical_listener| should be
+ // attached to |default_mixer|.
+ ForceOutputMixerCreation(current_default_physical_device());
+}
+
+// Makes sure both "default listeners" and "current_default_physical_device()
+// listeners" get attached to the same default mixer.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_DefaultIdMixerCreation_ListenersAttached) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+
+ // Create listeners for kDefaultDeviceId and
+ // current_default_physical_device(), BOTH listening to |default_mixer|.
+ auto default_listener = GetListener_MixerExpectsStart(default_mixer);
+ auto current_default_physical_listener =
+ GetListener_MixerExpectsStart(default_mixer);
+
+ // Create another listener, NOT listening to |default_mixer|.
+ ASSERT_NE(kOtherFakeDeviceId, current_default_physical_device());
+ auto other_listener = GetListener_MixerExpectsNoCalls(default_mixer);
+
+ // Start all listeners.
+ output_mixer_manager_.StartListening(default_listener.get(),
+ kDefaultDeviceId);
+ output_mixer_manager_.StartListening(current_default_physical_listener.get(),
+ current_default_physical_device());
+ output_mixer_manager_.StartListening(other_listener.get(),
+ kOtherFakeDeviceId);
+
+ // |default_listener| and |current_default_physical_listener| should be
+ // attached to |default_mixer|.
+ ForceOutputMixerCreation(kDefaultDeviceId);
+}
+
+// Makes sure both "default listeners" and "current_default_physical_device()
+// listeners" don't get attached to non-default mixers.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_OtherDeviceMixerCreation_ListenersNotAttached) {
+ MockOutputDeviceMixer* other_mixer =
+ SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+
+ // Create listeners for kDefaultDeviceId and
+ // current_default_physical_device(), BOTH NOT listening to |other_mixer|.
+ auto default_listener = GetListener_MixerExpectsNoCalls(other_mixer);
+ auto current_default_physical_listener =
+ GetListener_MixerExpectsNoCalls(other_mixer);
+
+ // Create another listener, listening to |other_mixer|.
+ ASSERT_NE(kOtherFakeDeviceId, current_default_physical_device());
+ auto other_listener = GetListener_MixerExpectsStart(other_mixer);
+
+ // Start all listeners.
+ output_mixer_manager_.StartListening(default_listener.get(),
+ kDefaultDeviceId);
+ output_mixer_manager_.StartListening(current_default_physical_listener.get(),
+ current_default_physical_device());
+ output_mixer_manager_.StartListening(other_listener.get(),
+ kOtherFakeDeviceId);
+
+ // Only |other_listener| should be attached to |other_mixer|.
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+}
+
+// Makes sure we can call StartListening multiple times with the same listener,
+// when the different device IDs map to the same mixer.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_MultipleStarts_EquivalentIds) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+ ForceOutputMixerCreation(kDefaultDeviceId);
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+
+ // Start listener.
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+
+ // Verify starting with the same ID.
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+
+ // Verify starting with equivalent IDs.
+ output_mixer_manager_.StartListening(listener.get(), kEmptyDeviceId);
+ output_mixer_manager_.StartListening(listener.get(),
+ current_default_physical_device());
+
+ // Return to the original ID.
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+
+ output_mixer_manager_.StopListening(listener.get());
+}
+
+// Makes sure we can call StartListening multiple times with the same listener,
+// with different device IDs.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_MultipleStarts_DifferentIds) {
+ MockOutputDeviceMixer* default_mixer;
+ MockOutputDeviceMixer* other_mixer;
+ {
+ InSequence s;
+ default_mixer = SetUpMockMixer_NoStreams(kNormalizedDefaultDeviceId);
+ other_mixer = SetUpMockMixer_NoStreams(kOtherFakeDeviceId);
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ ForceOutputMixerCreation(kOtherFakeDeviceId);
+ }
+
+ auto listener = GetListener_MixerExpectsStartStop(default_mixer);
+ EXPECT_CALL(*other_mixer, StartListening(listener.get())).Times(1);
+ EXPECT_CALL(*other_mixer, StopListening(listener.get())).Times(0);
+
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+
+ // This call should stop |default_mixer|.
+ output_mixer_manager_.StartListening(listener.get(), kOtherFakeDeviceId);
+}
+
+// Makes sure listeners are properly updated internally when going from a
+// default to a specific device.
+TEST_F(OutputDeviceMixerManagerTest,
+ DeviceOutputListener_MultipleStarts_DefaultToSpecific) {
+ MockOutputDeviceMixer* default_mixer = SetUpMockMixer_NoStreams();
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ testing::Mock::VerifyAndClearExpectations(this);
+
+ auto listener = GetListener_MixerExpectsStart(default_mixer);
+ output_mixer_manager_.StartListening(listener.get(), kDefaultDeviceId);
+
+ // Switch |listener| to listen to the current default device.
+ ASSERT_EQ(current_default_physical_device(), kFakeDeviceId);
+ output_mixer_manager_.StartListening(listener.get(), kFakeDeviceId);
+
+ // Change the default device.
+ ASSERT_NE(current_default_physical_device(), kOtherFakeDeviceId);
+ SimulateDeviceChange(/*new_default_physical_device=*/kOtherFakeDeviceId);
+
+ // The default mixer should not receive any start/stop calls with listener.
+ MockOutputDeviceMixer* new_default_mixer = SetUpMockMixer_NoStreams();
+ EXPECT_CALL(*new_default_mixer, StartListening(listener.get())).Times(0);
+ EXPECT_CALL(*new_default_mixer, StopListening(listener.get())).Times(0);
+ ForceOutputMixerCreation(kDefaultDeviceId);
+ testing::Mock::VerifyAndClearExpectations(this);
+
+ // The kFakeDeviceId mixer should be started with listener.
+ MockOutputDeviceMixer* physical_mixer =
+ SetUpMockMixer_NoStreams(kFakeDeviceId);
+ EXPECT_CALL(*physical_mixer, StartListening(listener.get())).Times(1);
+ EXPECT_CALL(*physical_mixer, StopListening(listener.get())).Times(0);
+ ForceOutputMixerCreation(kFakeDeviceId);
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/output_stream.cc b/chromium/services/audio/output_stream.cc
index 1ee556b880f..e41fbd329cd 100644
--- a/chromium/services/audio/output_stream.cc
+++ b/chromium/services/audio/output_stream.cc
@@ -33,6 +33,8 @@ std::string GetCtorLogString(media::AudioManager* audio_manager,
OutputStream::OutputStream(
CreatedCallback created_callback,
DeleteCallback delete_callback,
+ ManagedDeviceOutputStreamCreateCallback
+ managed_device_output_stream_create_callback,
mojo::PendingReceiver<media::mojom::AudioOutputStream> stream_receiver,
mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
observer,
@@ -60,7 +62,8 @@ OutputStream::OutputStream(
activity_monitor,
params,
output_device_id,
- &reader_),
+ &reader_,
+ std::move(managed_device_output_stream_create_callback)),
loopback_group_id_(loopback_group_id) {
DCHECK(receiver_.is_bound());
DCHECK(created_callback);
diff --git a/chromium/services/audio/output_stream.h b/chromium/services/audio/output_stream.h
index b13c3bb1309..3c888474952 100644
--- a/chromium/services/audio/output_stream.h
+++ b/chromium/services/audio/output_stream.h
@@ -9,7 +9,7 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
@@ -48,10 +48,14 @@ class OutputStream final : public media::mojom::AudioOutputStream,
using DeleteCallback = base::OnceCallback<void(OutputStream*)>;
using CreatedCallback =
base::OnceCallback<void(media::mojom::ReadWriteAudioDataPipePtr)>;
+ using ManagedDeviceOutputStreamCreateCallback =
+ OutputController::ManagedDeviceOutputStreamCreateCallback;
OutputStream(
CreatedCallback created_callback,
DeleteCallback delete_callback,
+ ManagedDeviceOutputStreamCreateCallback
+ managed_device_output_stream_create_callback,
mojo::PendingReceiver<media::mojom::AudioOutputStream> stream_receiver,
mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
observer,
@@ -101,7 +105,7 @@ class OutputStream final : public media::mojom::AudioOutputStream,
mojo::Receiver<AudioOutputStream> receiver_;
mojo::AssociatedRemote<media::mojom::AudioOutputStreamObserver> observer_;
const mojo::SharedRemote<media::mojom::AudioLog> log_;
- LoopbackCoordinator* const coordinator_;
+ const raw_ptr<LoopbackCoordinator> coordinator_;
SyncReader reader_;
OutputController controller_;
diff --git a/chromium/services/audio/output_stream_unittest.cc b/chromium/services/audio/output_stream_unittest.cc
index 904339ed575..faed4570af7 100644
--- a/chromium/services/audio/output_stream_unittest.cc
+++ b/chromium/services/audio/output_stream_unittest.cc
@@ -44,6 +44,9 @@ class MockStream : public media::AudioOutputStream {
public:
MockStream() {}
+ MockStream(const MockStream&) = delete;
+ MockStream& operator=(const MockStream&) = delete;
+
MOCK_METHOD0(Open, bool());
MOCK_METHOD1(Start, void(AudioSourceCallback* callback));
MOCK_METHOD0(Stop, void());
@@ -51,9 +54,6 @@ class MockStream : public media::AudioOutputStream {
MOCK_METHOD1(GetVolume, void(double* volume));
MOCK_METHOD0(Close, void());
MOCK_METHOD0(Flush, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockStream);
};
const uint32_t kPlatformErrorDisconnectReason = static_cast<uint32_t>(
@@ -66,6 +66,9 @@ class MockObserver : public media::mojom::AudioOutputStreamObserver {
public:
MockObserver() = default;
+ MockObserver(const MockObserver&) = delete;
+ MockObserver& operator=(const MockObserver&) = delete;
+
mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
MakeRemote() {
DCHECK(!receiver_.is_bound());
@@ -89,14 +92,15 @@ class MockObserver : public media::mojom::AudioOutputStreamObserver {
private:
mojo::AssociatedReceiver<media::mojom::AudioOutputStreamObserver> receiver_{
this};
-
- DISALLOW_COPY_AND_ASSIGN(MockObserver);
};
class MockCreatedCallback {
public:
MockCreatedCallback() {}
+ MockCreatedCallback(const MockCreatedCallback&) = delete;
+ MockCreatedCallback& operator=(const MockCreatedCallback&) = delete;
+
MOCK_METHOD1(Created, void(bool /*valid*/));
void OnCreated(media::mojom::ReadWriteAudioDataPipePtr ptr) {
@@ -107,9 +111,6 @@ class MockCreatedCallback {
return base::BindOnce(&MockCreatedCallback::OnCreated,
base::Unretained(this));
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCreatedCallback);
};
} // namespace
diff --git a/chromium/services/audio/owning_audio_manager_accessor.cc b/chromium/services/audio/owning_audio_manager_accessor.cc
index 9b1c69fc2d9..f2b8cc72c48 100644
--- a/chromium/services/audio/owning_audio_manager_accessor.cc
+++ b/chromium/services/audio/owning_audio_manager_accessor.cc
@@ -8,12 +8,11 @@
#include <utility>
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/time/default_tick_clock.h"
#include "media/audio/audio_features.h"
@@ -145,8 +144,9 @@ media::AudioManager* OwningAudioManagerAccessor::GetAudioManager() {
DCHECK(audio_manager_factory_cb_);
DCHECK(log_factory_);
base::TimeTicks creation_start_time = base::TimeTicks::Now();
- audio_manager_ = std::move(audio_manager_factory_cb_)
- .Run(std::make_unique<MainThread>(), log_factory_);
+ audio_manager_ =
+ std::move(audio_manager_factory_cb_)
+ .Run(std::make_unique<MainThread>(), log_factory_.get());
DCHECK(audio_manager_);
UMA_HISTOGRAM_TIMES("Media.AudioService.AudioManagerStartupTime",
base::TimeTicks::Now() - creation_start_time);
diff --git a/chromium/services/audio/owning_audio_manager_accessor.h b/chromium/services/audio/owning_audio_manager_accessor.h
index 08829380fb3..988353c768b 100644
--- a/chromium/services/audio/owning_audio_manager_accessor.h
+++ b/chromium/services/audio/owning_audio_manager_accessor.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "services/audio/service.h"
@@ -55,7 +55,7 @@ class OwningAudioManagerAccessor : public Service::AudioManagerAccessor {
#endif
AudioManagerFactoryCallback audio_manager_factory_cb_;
std::unique_ptr<media::AudioManager> audio_manager_;
- media::AudioLogFactory* log_factory_ = nullptr; // not owned.
+ raw_ptr<media::AudioLogFactory> log_factory_ = nullptr; // not owned.
THREAD_CHECKER(thread_checker_);
};
diff --git a/chromium/services/audio/public/cpp/BUILD.gn b/chromium/services/audio/public/cpp/BUILD.gn
index 3dbf5a8b237..f1faf296177 100644
--- a/chromium/services/audio/public/cpp/BUILD.gn
+++ b/chromium/services/audio/public/cpp/BUILD.gn
@@ -20,8 +20,6 @@ source_set("cpp") {
"sounds/audio_stream_handler.h",
"sounds/sounds_manager.cc",
"sounds/sounds_manager.h",
- "sounds/test_data.cc",
- "sounds/test_data.h",
]
configs += [ "//build/config/compiler:wexit_time_destructors" ]
@@ -42,11 +40,14 @@ source_set("test_support") {
"fake_stream_factory.h",
"fake_system_info.cc",
"fake_system_info.h",
+ "sounds/test_data.cc",
+ "sounds/test_data.h",
]
deps = [ "//testing/gmock" ]
public_deps = [
+ ":cpp",
"//base",
"//media",
"//services/audio",
diff --git a/chromium/services/audio/public/cpp/debug_recording_session.h b/chromium/services/audio/public/cpp/debug_recording_session.h
index 975f10cfd56..2ccbff8c582 100644
--- a/chromium/services/audio/public/cpp/debug_recording_session.h
+++ b/chromium/services/audio/public/cpp/debug_recording_session.h
@@ -57,13 +57,15 @@ class DebugRecordingSession : public media::AudioDebugRecordingSession {
DebugRecordingSession(
const base::FilePath& file_name_base,
mojo::PendingRemote<mojom::DebugRecording> debug_recording);
+
+ DebugRecordingSession(const DebugRecordingSession&) = delete;
+ DebugRecordingSession& operator=(const DebugRecordingSession&) = delete;
+
~DebugRecordingSession() override;
private:
std::unique_ptr<DebugRecordingFileProvider> file_provider_;
mojo::Remote<mojom::DebugRecording> debug_recording_;
-
- DISALLOW_COPY_AND_ASSIGN(DebugRecordingSession);
};
} // namespace audio
diff --git a/chromium/services/audio/public/cpp/fake_system_info.h b/chromium/services/audio/public/cpp/fake_system_info.h
index e3c24e7d7d0..1b57919fe90 100644
--- a/chromium/services/audio/public/cpp/fake_system_info.h
+++ b/chromium/services/audio/public/cpp/fake_system_info.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/message_pipe.h"
diff --git a/chromium/services/audio/public/cpp/input_ipc.h b/chromium/services/audio/public/cpp/input_ipc.h
index 458f8b3da77..0eddc3bcd19 100644
--- a/chromium/services/audio/public/cpp/input_ipc.h
+++ b/chromium/services/audio/public/cpp/input_ipc.h
@@ -9,7 +9,7 @@
#include <string>
#include "base/callback_helpers.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "media/audio/audio_input_ipc.h"
@@ -60,7 +60,7 @@ class InputIPC : public media::AudioInputIPC,
mojo::Remote<media::mojom::AudioInputStream> stream_;
mojo::Receiver<AudioInputStreamClient> stream_client_receiver_{this};
- media::AudioInputIPCDelegate* delegate_ = nullptr;
+ raw_ptr<media::AudioInputIPCDelegate> delegate_ = nullptr;
std::string device_id_;
absl::optional<base::UnguessableToken> stream_id_;
diff --git a/chromium/services/audio/public/cpp/output_device.h b/chromium/services/audio/public/cpp/output_device.h
index eb809657183..2672e7f1008 100644
--- a/chromium/services/audio/public/cpp/output_device.h
+++ b/chromium/services/audio/public/cpp/output_device.h
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include "base/memory/raw_ptr.h"
#include "media/base/audio_renderer_sink.h"
#include "media/mojo/mojom/audio_output_stream.mojom.h"
#include "media/mojo/mojom/audio_stream_factory.mojom.h"
@@ -50,7 +51,7 @@ class OutputDevice {
std::unique_ptr<media::AudioOutputDeviceThreadCallback> audio_callback_;
std::unique_ptr<media::AudioDeviceThread> audio_thread_;
media::AudioParameters audio_parameters_;
- media::AudioRendererSink::RenderCallback* render_callback_;
+ raw_ptr<media::AudioRendererSink::RenderCallback> render_callback_;
mojo::Remote<media::mojom::AudioOutputStream> stream_;
mojo::Remote<media::mojom::AudioStreamFactory> stream_factory_;
diff --git a/chromium/services/audio/public/cpp/sounds/audio_stream_handler.cc b/chromium/services/audio/public/cpp/sounds/audio_stream_handler.cc
index e8e9f529c15..0d56efa01b8 100644
--- a/chromium/services/audio/public/cpp/sounds/audio_stream_handler.cc
+++ b/chromium/services/audio/public/cpp/sounds/audio_stream_handler.cc
@@ -12,10 +12,9 @@
#include "base/bind.h"
#include "base/cancelable_callback.h"
#include "base/logging.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "media/audio/wav_audio_handler.h"
#include "media/base/channel_layout.h"
diff --git a/chromium/services/audio/public/cpp/sounds/audio_stream_handler.h b/chromium/services/audio/public/cpp/sounds/audio_stream_handler.h
index c401dfbbce7..c4b7f5f68ae 100644
--- a/chromium/services/audio/public/cpp/sounds/audio_stream_handler.h
+++ b/chromium/services/audio/public/cpp/sounds/audio_stream_handler.h
@@ -9,7 +9,6 @@
#include <memory>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc b/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc
index 44cf4c32e97..cc93ed9f26e 100644
--- a/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc
+++ b/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc
@@ -12,7 +12,7 @@
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/audio/audio_io.h"
diff --git a/chromium/services/audio/public/cpp/sounds/sounds_manager.h b/chromium/services/audio/public/cpp/sounds/sounds_manager.h
index 65ad12f7062..c21ec8e5732 100644
--- a/chromium/services/audio/public/cpp/sounds/sounds_manager.h
+++ b/chromium/services/audio/public/cpp/sounds/sounds_manager.h
@@ -6,7 +6,6 @@
#define SERVICES_AUDIO_PUBLIC_CPP_SOUNDS_SOUNDS_MANAGER_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
@@ -33,6 +32,9 @@ class SoundsManager {
// Returns a pointer to a singleton instance of the SoundsManager.
static SoundsManager* Get();
+ SoundsManager(const SoundsManager&) = delete;
+ SoundsManager& operator=(const SoundsManager&) = delete;
+
// Initializes sounds manager for testing. The |manager| will be owned
// by the internal pointer and will be deleted by Shutdown().
static void InitializeForTesting(SoundsManager* manager);
@@ -60,9 +62,6 @@ class SoundsManager {
virtual ~SoundsManager();
SEQUENCE_CHECKER(sequence_checker_);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SoundsManager);
};
} // namespace audio
diff --git a/chromium/services/audio/public/cpp/sounds/test_data.h b/chromium/services/audio/public/cpp/sounds/test_data.h
index cd6fc355539..f22e6024a9b 100644
--- a/chromium/services/audio/public/cpp/sounds/test_data.h
+++ b/chromium/services/audio/public/cpp/sounds/test_data.h
@@ -11,8 +11,9 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/cxx17_backports.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "media/base/audio_renderer_sink.h"
#include "services/audio/public/cpp/sounds/audio_stream_handler.h"
@@ -54,7 +55,7 @@ class TestObserver : public AudioStreamHandler::TestObserver {
int num_stop_requests_;
int cursor_;
int is_playing;
- media::AudioRendererSink::RenderCallback* callback_;
+ raw_ptr<media::AudioRendererSink::RenderCallback> callback_;
std::unique_ptr<media::AudioBus> bus_;
};
diff --git a/chromium/services/audio/public/mojom/BUILD.gn b/chromium/services/audio/public/mojom/BUILD.gn
index 869517c3979..c877f96059d 100644
--- a/chromium/services/audio/public/mojom/BUILD.gn
+++ b/chromium/services/audio/public/mojom/BUILD.gn
@@ -18,6 +18,7 @@ mojom("mojom") {
public_deps = [
"//media/mojo/mojom",
"//mojo/public/mojom/base",
+ "//sandbox/policy/mojom",
]
cpp_typemaps = [
diff --git a/chromium/services/audio/public/mojom/audio_service.mojom b/chromium/services/audio/public/mojom/audio_service.mojom
index 2c1f4cd2f1f..65f5a369a07 100644
--- a/chromium/services/audio/public/mojom/audio_service.mojom
+++ b/chromium/services/audio/public/mojom/audio_service.mojom
@@ -5,6 +5,7 @@
module audio.mojom;
import "media/mojo/mojom/audio_stream_factory.mojom";
+import "sandbox/policy/mojom/sandbox.mojom";
import "services/audio/public/mojom/debug_recording.mojom";
import "services/audio/public/mojom/device_notifications.mojom";
import "services/audio/public/mojom/log_factory_manager.mojom";
@@ -12,7 +13,9 @@ import "services/audio/public/mojom/system_info.mojom";
import "services/audio/public/mojom/testing_api.mojom";
// The main interface to the Audio service. This is a privileged interface and
-// must only be bound by trusted processes, e.g. a browser process.
+// must only be bound by trusted processes, e.g. a browser process. Note that
+// the sandbox can be disabled (to kNoSandbox) by policy.
+[ServiceSandbox=sandbox.mojom.Sandbox.kAudio]
interface AudioService {
// Binds a SystemInfo interface receiver.
BindSystemInfo(pending_receiver<SystemInfo> receiver);
@@ -33,4 +36,3 @@ interface AudioService {
// environments.
BindTestingApi(pending_receiver<TestingApi> receiver);
};
-
diff --git a/chromium/services/audio/reference_output.h b/chromium/services/audio/reference_output.h
new file mode 100644
index 00000000000..7808a1c9a87
--- /dev/null
+++ b/chromium/services/audio/reference_output.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_REFERENCE_OUTPUT_H_
+#define SERVICES_AUDIO_REFERENCE_OUTPUT_H_
+
+#include "base/time/time.h"
+
+namespace media {
+class AudioBus;
+} // namespace media
+
+namespace audio {
+class ReferenceOutput {
+ public:
+ class Listener {
+ public:
+ // Provides read-only access to the auio played by ReferenceOutput.
+ // Must execute quickly, as it will typically be called on a realtime
+ // thread; otherwise, audio glitches may occur.
+ virtual void OnPlayoutData(const media::AudioBus& audio_bus,
+ int sample_rate,
+ base::TimeDelta audio_delay) = 0;
+
+ protected:
+ virtual ~Listener() = default;
+ };
+
+ // Starts/Stops listening to the reference output.
+ virtual void StartListening(Listener* listener) = 0;
+ virtual void StopListening(Listener* listener) = 0;
+
+ protected:
+ virtual ~ReferenceOutput() = default;
+};
+} // namespace audio
+
+#endif // SERVICES_AUDIO_REFERENCE_OUTPUT_H_
diff --git a/chromium/services/audio/service.cc b/chromium/services/audio/service.cc
index 8366982e609..52caf1e16b3 100644
--- a/chromium/services/audio/service.cc
+++ b/chromium/services/audio/service.cc
@@ -9,11 +9,10 @@
#include "base/bind.h"
#include "base/check_op.h"
-#include "base/deferred_sequenced_task_runner.h"
-#include "base/macros.h"
#include "base/no_destructor.h"
-#include "base/single_thread_task_runner.h"
#include "base/system/system_monitor.h"
+#include "base/task/deferred_sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "media/audio/audio_manager.h"
diff --git a/chromium/services/audio/service.h b/chromium/services/audio/service.h
index 598ee2f6cef..2af08620011 100644
--- a/chromium/services/audio/service.h
+++ b/chromium/services/audio/service.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "media/mojo/mojom/audio_stream_factory.mojom.h"
diff --git a/chromium/services/audio/service_metrics.h b/chromium/services/audio/service_metrics.h
index 5955f07b9a6..66915fcadc5 100644
--- a/chromium/services/audio/service_metrics.h
+++ b/chromium/services/audio/service_metrics.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_AUDIO_SERVICE_METRICS_H_
#define SERVICES_AUDIO_SERVICE_METRICS_H_
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
namespace base {
@@ -29,7 +29,7 @@ class ServiceMetrics {
private:
void LogHasNoConnectionsDuration();
- const base::TickClock* clock_;
+ raw_ptr<const base::TickClock> clock_;
base::TimeTicks has_connections_start_;
base::TimeTicks has_no_connections_start_;
};
diff --git a/chromium/services/audio/snooper_node.h b/chromium/services/audio/snooper_node.h
index 5b8a2fd39df..1dcef273b62 100644
--- a/chromium/services/audio/snooper_node.h
+++ b/chromium/services/audio/snooper_node.h
@@ -8,7 +8,6 @@
#include <limits>
#include <memory>
-#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "media/base/audio_parameters.h"
diff --git a/chromium/services/audio/stream_factory.cc b/chromium/services/audio/stream_factory.cc
index 0a4810f980f..c84a403722a 100644
--- a/chromium/services/audio/stream_factory.cc
+++ b/chromium/services/audio/stream_factory.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/trace_event/trace_event.h"
#include "base/unguessable_token.h"
#include "build/chromecast_buildflags.h"
@@ -17,10 +18,35 @@
#include "services/audio/output_stream.h"
#include "services/audio/user_input_monitor.h"
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+#include "services/audio/output_device_mixer.h"
+#endif
+
namespace audio {
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+const base::Feature kMixingForChromeWideAec{"MixingForChromeWideAec",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+namespace {
+
+std::unique_ptr<OutputDeviceMixerManager> MaybeCreateOutputDeviceMixerManager(
+ media::AudioManager* audio_manager) {
+ if (!base::FeatureList::IsEnabled(kMixingForChromeWideAec))
+ return nullptr;
+
+ return std::make_unique<OutputDeviceMixerManager>(
+ audio_manager, base::BindRepeating(&OutputDeviceMixer::Create));
+}
+
+} // namespace
+#endif
+
StreamFactory::StreamFactory(media::AudioManager* audio_manager)
: audio_manager_(audio_manager),
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ output_device_mixer_manager_(
+ MaybeCreateOutputDeviceMixerManager(audio_manager)),
+#endif
loopback_worker_thread_("Loopback Worker") {
}
@@ -59,8 +85,13 @@ void StreamFactory::CreateInputStream(
std::move(stream_receiver), std::move(client), std::move(observer),
std::move(pending_log), audio_manager_,
UserInputMonitor::Create(std::move(key_press_count_buffer)),
- &stream_count_metric_reporter_, device_id, params, shared_memory_count,
- enable_agc));
+ &stream_count_metric_reporter_,
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ output_device_mixer_manager_.get(),
+#else
+ nullptr,
+#endif
+ device_id, params, shared_memory_count, enable_agc));
}
void StreamFactory::AssociateInputAndOutputForAec(
@@ -106,8 +137,22 @@ void StreamFactory::CreateOutputStream(
output_device_id;
#endif
+ // base::Unretained() is safe since |this| owns both |output_mixer_manager_|
+ // and |output_streams_|, and ensures the correct order of destruction.
+ OutputStream::ManagedDeviceOutputStreamCreateCallback
+ managed_device_output_stream_create_callback;
+
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ if (output_device_mixer_manager_) {
+ managed_device_output_stream_create_callback = base::BindRepeating(
+ &OutputDeviceMixerManager::MakeOutputStream,
+ base::Unretained(output_device_mixer_manager_.get()));
+ }
+#endif
+
output_streams_.insert(std::make_unique<OutputStream>(
std::move(created_callback), std::move(deleter_callback),
+ std::move(managed_device_output_stream_create_callback),
std::move(stream_receiver), std::move(observer), std::move(log),
audio_manager_, &stream_count_metric_reporter_, device_id_or_group_id,
params, &coordinator_, group_id));
@@ -118,7 +163,7 @@ void StreamFactory::BindMuter(
const base::UnguessableToken& group_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("audio", "BindMuter", this, "group id",
- group_id.GetLowForSerialization());
+ group_id);
// Find the existing LocalMuter for this group, or create one on-demand.
auto it = std::find_if(muters_.begin(), muters_.end(),
@@ -150,9 +195,8 @@ void StreamFactory::CreateLoopbackStream(
CreateLoopbackStreamCallback created_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
TRACE_EVENT_NESTABLE_ASYNC_INSTANT2("audio", "CreateLoopbackStream", this,
- "group id",
- group_id.GetLowForSerialization(),
- "params", params.AsHumanReadableString());
+ "group id", group_id, "params",
+ params.AsHumanReadableString());
// All LoopbackStreams share a single realtime worker thread. This is because
// the execution timing of scheduled tasks must be precise, and top priority
diff --git a/chromium/services/audio/stream_factory.h b/chromium/services/audio/stream_factory.h
index 40ff7861587..234af1020d4 100644
--- a/chromium/services/audio/stream_factory.h
+++ b/chromium/services/audio/stream_factory.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/threading/thread.h"
@@ -20,9 +19,14 @@
#include "media/mojo/mojom/audio_output_stream.mojom.h"
#include "media/mojo/mojom/audio_stream_factory.mojom.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/audio/buildflags.h"
#include "services/audio/concurrent_stream_metric_reporter.h"
#include "services/audio/loopback_coordinator.h"
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+#include "services/audio/output_device_mixer_manager.h"
+#endif
+
namespace base {
class UnguessableToken;
}
@@ -112,6 +116,9 @@ class StreamFactory final : public media::mojom::AudioStreamFactory {
ConcurrentStreamMetricReporter stream_count_metric_reporter_;
// Order of the following members is important for a clean shutdown.
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
+ const std::unique_ptr<OutputDeviceMixerManager> output_device_mixer_manager_;
+#endif
LoopbackCoordinator coordinator_;
std::vector<std::unique_ptr<LocalMuter>> muters_;
base::Thread loopback_worker_thread_;
diff --git a/chromium/services/audio/sync_mixing_graph_input.cc b/chromium/services/audio/sync_mixing_graph_input.cc
new file mode 100644
index 00000000000..25c660b9430
--- /dev/null
+++ b/chromium/services/audio/sync_mixing_graph_input.cc
@@ -0,0 +1,95 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/sync_mixing_graph_input.h"
+
+#include "base/trace_event/trace_event.h"
+#include "media/base/audio_pull_fifo.h"
+#include "media/base/audio_timestamp_helper.h"
+
+namespace audio {
+
+SyncMixingGraphInput::SyncMixingGraphInput(MixingGraph* graph,
+ const media::AudioParameters& params)
+ : graph_(graph), params_(params) {
+ DCHECK(graph);
+ CHECK(params_.IsValid());
+}
+
+SyncMixingGraphInput::~SyncMixingGraphInput() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+}
+
+// Either calls Render() directly to produce the requested input audio, or - in
+// the case of a frames per buffer mismatch - pulls audio from the |fifo_| which
+// in turn calls Render() as needed.
+double SyncMixingGraphInput::ProvideInput(media::AudioBus* audio_bus,
+ uint32_t frames_delayed) {
+ DCHECK_EQ(audio_bus->channels(), params_.channels());
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "SyncMixingGraphInput::ProvideInput", "frames_delayed",
+ frames_delayed, "bus frames", audio_bus->frames());
+
+ if (!fifo_ && audio_bus->frames() != params_.frames_per_buffer()) {
+ fifo_ = std::make_unique<media::AudioPullFifo>(
+ params_.channels(), params_.frames_per_buffer(),
+ base::BindRepeating(&SyncMixingGraphInput::Render,
+ base::Unretained(this)));
+ }
+
+ // Used by Render() for delay calculation.
+ converter_render_frame_delay_ = frames_delayed;
+ if (fifo_)
+ fifo_->Consume(audio_bus, audio_bus->frames());
+ else
+ Render(0, audio_bus);
+ converter_render_frame_delay_ = 0;
+
+ return volume_;
+}
+
+const media::AudioParameters& SyncMixingGraphInput::GetParams() const {
+ return params_;
+}
+
+void SyncMixingGraphInput::SetVolume(double volume) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ volume_ = volume;
+}
+
+void SyncMixingGraphInput::Start(
+ media::AudioOutputStream::AudioSourceCallback* source_callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(!fifo_);
+ DCHECK(!source_callback_);
+ source_callback_ = source_callback;
+ graph_->AddInput(this);
+}
+
+void SyncMixingGraphInput::Stop() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ graph_->RemoveInput(this);
+ if (fifo_)
+ fifo_.reset();
+ source_callback_ = nullptr;
+}
+
+void SyncMixingGraphInput::Render(int fifo_frame_delay,
+ media::AudioBus* audio_bus) {
+ DCHECK(source_callback_);
+ TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "SyncMixingGraphInput::Render", "this",
+ static_cast<void*>(this));
+
+ base::TimeDelta delay = media::AudioTimestampHelper::FramesToTime(
+ converter_render_frame_delay_ + fifo_frame_delay, params_.sample_rate());
+ source_callback_->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus);
+
+ TRACE_EVENT_END2(TRACE_DISABLED_BY_DEFAULT("audio"),
+ "SyncMixingGraphInput::Render", "total frames delay",
+ converter_render_frame_delay_ + fifo_frame_delay,
+ "bus frames", audio_bus->frames());
+}
+
+} // namespace audio
diff --git a/chromium/services/audio/sync_mixing_graph_input.h b/chromium/services/audio/sync_mixing_graph_input.h
new file mode 100644
index 00000000000..1a93394076d
--- /dev/null
+++ b/chromium/services/audio/sync_mixing_graph_input.h
@@ -0,0 +1,77 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_SYNC_MIXING_GRAPH_INPUT_H_
+#define SERVICES_AUDIO_SYNC_MIXING_GRAPH_INPUT_H_
+
+#include <atomic>
+#include <memory>
+
+#include "base/memory/raw_ptr.h"
+#include "base/sequence_checker.h"
+#include "media/audio/audio_io.h"
+#include "media/base/audio_converter.h"
+#include "media/base/audio_parameters.h"
+#include "services/audio/mixing_graph.h"
+
+namespace media {
+class AudioPullFifo;
+}
+
+namespace audio {
+
+// Input to the mixing graph.
+class SyncMixingGraphInput final : public MixingGraph::Input {
+ public:
+ const double kDefaultVolume = 1.0;
+
+ SyncMixingGraphInput(MixingGraph* graph,
+ const media::AudioParameters& params);
+ ~SyncMixingGraphInput() final;
+
+ // media::AudioConverter::InputCallback.
+ double ProvideInput(media::AudioBus* audio_bus,
+ uint32_t frames_delayed) final;
+
+ const media::AudioParameters& GetParams() const final;
+
+ // Sets a new volume to be applied to the input during mixing.
+ void SetVolume(double volume) final;
+
+ // Adds the input to the mixing graph. The mixing graph will repeatedly pull
+ // data from |callback|.
+ void Start(media::AudioOutputStream::AudioSourceCallback* callback) final;
+
+ // Removes the input from the mixing graph. The mixing graph will stop pulling
+ // data from the input.
+ void Stop() final;
+
+ private:
+ void Render(int fifo_frame_delay, media::AudioBus* audio_bus);
+
+ // Pointer to the mixing graph to which the input belongs.
+ const raw_ptr<MixingGraph> graph_;
+
+ // Channel layout, sample rate and number of frames of the input.
+ const media::AudioParameters params_;
+
+ // Volume of the input.
+ std::atomic<double> volume_{kDefaultVolume};
+
+ // Callback providing audio to the mixing graph when requested.
+ raw_ptr<media::AudioOutputStream::AudioSourceCallback> source_callback_ =
+ nullptr;
+
+ // Handles buffering when there is a mismatch in number of frames between the
+ // input and the output of the mixing graph. Created on-demand.
+ std::unique_ptr<media::AudioPullFifo> fifo_;
+
+ // Used for calculating the playback delay.
+ int converter_render_frame_delay_ = 0;
+ SEQUENCE_CHECKER(owning_sequence_);
+};
+
+} // namespace audio
+
+#endif // SERVICES_AUDIO_SYNC_MIXING_GRAPH_INPUT_H_
diff --git a/chromium/services/audio/sync_reader.cc b/chromium/services/audio/sync_reader.cc
index 9a9903532bc..acc5a8a6588 100644
--- a/chromium/services/audio/sync_reader.cc
+++ b/chromium/services/audio/sync_reader.cc
@@ -12,7 +12,7 @@
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
@@ -22,19 +22,68 @@
#include "media/base/audio_parameters.h"
#include "media/base/media_switches.h"
+using media::AudioLatency;
+
namespace {
// Used to log if any audio glitches have been detected during an audio session.
// Elements in this enum should not be added, deleted or rearranged.
-enum AudioGlitchResult {
- AUDIO_RENDERER_NO_AUDIO_GLITCHES = 0,
- AUDIO_RENDERER_AUDIO_GLITCHES = 1,
- AUDIO_RENDERER_AUDIO_GLITCHES_MAX = AUDIO_RENDERER_AUDIO_GLITCHES
+enum class AudioGlitchResult {
+ kNoGlitches = 0,
+ kGlitches = 1,
+ kMaxValue = kGlitches
};
-void LogAudioGlitchResult(AudioGlitchResult result) {
- UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererAudioGlitches", result,
- AUDIO_RENDERER_AUDIO_GLITCHES_MAX + 1);
+void LogPerLatencyGlitchUma(AudioLatency::LatencyType latency,
+ int renderer_missed_callback_count,
+ int renderer_callback_count) {
+ DCHECK_LE(renderer_missed_callback_count, renderer_callback_count);
+
+ auto LatencyToString = [](AudioLatency::LatencyType latency) {
+ switch (latency) {
+ case AudioLatency::LATENCY_EXACT_MS:
+ return "LatencyExactMs";
+ case AudioLatency::LATENCY_INTERACTIVE:
+ return "LatencyInteractive";
+ case AudioLatency::LATENCY_RTC:
+ return "LatencyRtc";
+ case AudioLatency::LATENCY_PLAYBACK:
+ return "LatencyPlayback";
+ default:
+ return "LatencyUnknown";
+ }
+ };
+
+ const std::string suffix = LatencyToString(latency);
+
+ base::UmaHistogramEnumeration("Media.AudioRendererAudioGlitches2." + suffix,
+ (renderer_missed_callback_count > 0)
+ ? AudioGlitchResult::kGlitches
+ : AudioGlitchResult::kNoGlitches);
+
+ const int kPermilleScaling = 1000;
+ // 10%: if we have more that 10% of callbacks having issues, the details are
+ // not very interesting any more, so we just log all those cases together to
+ // have a better resolution for lower values.
+ const int kHistogramRange = kPermilleScaling / 10;
+
+ // 30 s for 10 ms buffers (RTC streams)/ 1 minute for 20 ms buffers (media
+ // playback).
+ const int kShortStreamMaxCallbackCount = 3000;
+
+ if (renderer_callback_count <= 0)
+ return;
+
+ int missed_permille = std::ceil(
+ kPermilleScaling * static_cast<double>(renderer_missed_callback_count) /
+ renderer_callback_count);
+
+ base::UmaHistogramCustomCounts(
+ ((renderer_callback_count < kShortStreamMaxCallbackCount)
+ ? "Media.AudioRendererMissedDeadline2.Short."
+ : "Media.AudioRendererMissedDeadline2.Long.") +
+ suffix,
+ std::min(missed_permille, kHistogramRange), 0, kHistogramRange + 1, 100);
}
} // namespace
@@ -55,6 +104,7 @@ SyncReader::SyncReader(
const media::AudioParameters& params,
base::CancelableSyncSocket* foreign_socket)
: log_callback_(std::move(log_callback)),
+ latency_tag_(params.latency_tag()),
mute_audio_for_testing_(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMuteAudio)),
had_socket_error_(false),
@@ -114,22 +164,22 @@ SyncReader::~SyncReader() {
if (!renderer_callback_count_)
return;
- // Recording the percentage of deadline misses gives us a rough overview of
- // how many users might be running into audio glitches.
+ base::UmaHistogramEnumeration("Media.AudioRendererAudioGlitches",
+ (renderer_missed_callback_count_ > 0)
+ ? AudioGlitchResult::kGlitches
+ : AudioGlitchResult::kNoGlitches);
int percentage_missed =
100.0 * renderer_missed_callback_count_ / renderer_callback_count_;
- UMA_HISTOGRAM_PERCENTAGE("Media.AudioRendererMissedDeadline",
- percentage_missed);
+
+ base::UmaHistogramPercentage("Media.AudioRendererMissedDeadline",
+ percentage_missed);
+
+ LogPerLatencyGlitchUma(latency_tag_, renderer_missed_callback_count_,
+ renderer_callback_count_);
TRACE_EVENT_INSTANT1("audio", "~SyncReader", TRACE_EVENT_SCOPE_THREAD,
"Missed callback percentage", percentage_missed);
- // Add more detailed information regarding detected audio glitches where
- // a non-zero value of |renderer_missed_callback_count_| is added to the
- // AUDIO_RENDERER_AUDIO_GLITCHES bin.
- renderer_missed_callback_count_ > 0
- ? LogAudioGlitchResult(AUDIO_RENDERER_AUDIO_GLITCHES)
- : LogAudioGlitchResult(AUDIO_RENDERER_NO_AUDIO_GLITCHES);
log_callback_.Run(base::StringPrintf(
"ASR: number of detected audio glitches: %" PRIuS " out of %" PRIuS,
renderer_missed_callback_count_, renderer_callback_count_));
@@ -291,9 +341,9 @@ bool SyncReader::WaitUntilDataIsReady() {
TRACE_EVENT_SCOPE_THREAD);
base::TimeDelta time_since_start = base::TimeTicks::Now() - start_time;
- UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady",
- time_since_start, base::Milliseconds(1),
- base::Milliseconds(1000), 50);
+ base::UmaHistogramCustomTimes("Media.AudioOutputControllerDataNotReady",
+ time_since_start, base::Milliseconds(1),
+ base::Milliseconds(1000), 50);
return false;
}
diff --git a/chromium/services/audio/sync_reader.h b/chromium/services/audio/sync_reader.h
index 5fdcc4a554f..626c28adb39 100644
--- a/chromium/services/audio/sync_reader.h
+++ b/chromium/services/audio/sync_reader.h
@@ -12,13 +12,13 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/process/process.h"
#include "base/sync_socket.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/audio_bus.h"
+#include "media/base/audio_latency.h"
#include "services/audio/output_controller.h"
#if defined(OS_POSIX)
@@ -74,6 +74,8 @@ class SyncReader : public OutputController::SyncReader {
base::UnsafeSharedMemoryRegion shared_memory_region_;
base::WritableSharedMemoryMapping shared_memory_mapping_;
+ const media::AudioLatency::LatencyType latency_tag_;
+
// Mutes all incoming samples. This is used to prevent audible sound
// during automated testing.
const bool mute_audio_for_testing_;
diff --git a/chromium/services/audio/system_info.h b/chromium/services/audio/system_info.h
index c65f07bbc42..1d2294add4b 100644
--- a/chromium/services/audio/system_info.h
+++ b/chromium/services/audio/system_info.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "media/audio/audio_system_helper.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc
index 2544b50a3d6..56ccee5d776 100644
--- a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc
+++ b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc
@@ -65,14 +65,15 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
-#include "base/macros.h"
+#include "base/ignore_result.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/numerics/safe_math.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/timer/timer.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -234,6 +235,9 @@ class CertNetFetcherURLLoader::RequestCore
base::WaitableEvent::InitialState::NOT_SIGNALED),
task_runner_(std::move(task_runner)) {}
+ RequestCore(const RequestCore&) = delete;
+ RequestCore& operator=(const RequestCore&) = delete;
+
void AttachedToJob(Job* job) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK(!job_);
@@ -292,7 +296,7 @@ class CertNetFetcherURLLoader::RequestCore
void CancelJobOnTaskRunner();
// A non-owned pointer to the job that is executing the request.
- Job* job_ = nullptr;
+ raw_ptr<Job> job_ = nullptr;
// May be written to from network thread, or from the caller thread only when
// there is no work that will be done on the network thread (e.g. when the
@@ -306,13 +310,14 @@ class CertNetFetcherURLLoader::RequestCore
// The task runner of the creation thread.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestCore);
};
struct CertNetFetcherURLLoader::RequestParams {
RequestParams();
+ RequestParams(const RequestParams&) = delete;
+ RequestParams& operator=(const RequestParams&) = delete;
+
bool operator<(const RequestParams& other) const;
GURL url;
@@ -323,9 +328,6 @@ struct CertNetFetcherURLLoader::RequestParams {
base::TimeDelta timeout;
// IMPORTANT: When adding fields to this structure, update operator<().
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RequestParams);
};
CertNetFetcherURLLoader::RequestParams::RequestParams()
@@ -411,7 +413,7 @@ class Job {
// Non-owned pointer to the AsyncCertNetFetcherURLLoader that created this
// job.
- CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader* parent_;
+ raw_ptr<CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader> parent_;
};
} // namespace
@@ -440,7 +442,7 @@ void CertNetFetcherURLLoader::RequestCore::CancelJob() {
void CertNetFetcherURLLoader::RequestCore::CancelJobOnTaskRunner() {
if (job_) {
- auto* job = job_;
+ auto* job = job_.get();
job_ = nullptr;
job->DetachRequest(this);
}
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 494c04efdc9..143bf9eeb3a 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
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
+#include "base/memory/raw_ptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
@@ -235,7 +236,7 @@ class SecureDnsInterceptor : public net::URLRequestInterceptor {
return nullptr;
}
- bool* invoked_interceptor_;
+ raw_ptr<bool> invoked_interceptor_;
};
class CertNetFetcherURLLoaderTestWithSecureDnsInterceptor
diff --git a/chromium/services/cert_verifier/cert_verifier_service_unittest.cc b/chromium/services/cert_verifier/cert_verifier_service_unittest.cc
index 3dc41989d3b..419ddf0306c 100644
--- a/chromium/services/cert_verifier/cert_verifier_service_unittest.cc
+++ b/chromium/services/cert_verifier/cert_verifier_service_unittest.cc
@@ -13,6 +13,7 @@
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
@@ -52,7 +53,7 @@ class DummyCertVerifier : public net::CertVerifier {
std::move(cancel_cb).Run();
}
- net::CertVerifyResult* verify_result;
+ raw_ptr<net::CertVerifyResult> verify_result;
net::CompletionOnceCallback callback;
base::OnceClosure cancel_cb;
@@ -186,7 +187,7 @@ class CertVerifierServiceTest : public PlatformTest {
CertVerifierServiceTest()
: dummy_cv_(new DummyCertVerifier),
cv_service_(new internal::CertVerifierServiceImpl(
- base::WrapUnique(dummy_cv_),
+ base::WrapUnique(dummy_cv_.get()),
cv_service_remote_.BindNewPipeAndPassReceiver(),
/*cert_net_fetcher=*/nullptr)) {}
@@ -263,8 +264,8 @@ class CertVerifierServiceTest : public PlatformTest {
base::test::TaskEnvironment task_environment_;
mojo::Remote<mojom::CertVerifierService> cv_service_remote_;
- DummyCertVerifier* dummy_cv_;
- internal::CertVerifierServiceImpl* cv_service_;
+ raw_ptr<DummyCertVerifier> dummy_cv_;
+ raw_ptr<internal::CertVerifierServiceImpl> cv_service_;
};
} // namespace
diff --git a/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc b/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc
index e2ebd509232..1660abc743c 100644
--- a/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc
+++ b/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc
@@ -7,7 +7,7 @@
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
diff --git a/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc b/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc
index abe6fb78cda..9801a44e1bf 100644
--- a/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc
+++ b/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc
@@ -5,7 +5,7 @@
#include <memory>
#include "base/files/file_util.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
diff --git a/chromium/services/cert_verifier/public/mojom/trial_comparison_cert_verifier.mojom b/chromium/services/cert_verifier/public/mojom/trial_comparison_cert_verifier.mojom
index 14d2e7f481d..3a0bf23b8d0 100644
--- a/chromium/services/cert_verifier/public/mojom/trial_comparison_cert_verifier.mojom
+++ b/chromium/services/cert_verifier/public/mojom/trial_comparison_cert_verifier.mojom
@@ -65,7 +65,7 @@ struct CertVerifierDebugInfo {
kUnknown = 0,
kDomainCache = 1,
kSimple = 2,
- kMruCache = 3,
+ kLruCache = 3,
};
[EnableIf=is_mac]
MacTrustImplType mac_trust_impl;
diff --git a/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.cc b/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.cc
index bfa4952469d..93c07e9b14c 100644
--- a/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.cc
+++ b/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.cc
@@ -37,9 +37,9 @@ TrustImplTypeToMojom(net::TrustStoreMac::TrustImplType input) {
case net::TrustStoreMac::TrustImplType::kSimple:
return cert_verifier::mojom::CertVerifierDebugInfo::MacTrustImplType::
kSimple;
- case net::TrustStoreMac::TrustImplType::kMruCache:
+ case net::TrustStoreMac::TrustImplType::kLruCache:
return cert_verifier::mojom::CertVerifierDebugInfo::MacTrustImplType::
- kMruCache;
+ kLruCache;
}
}
#endif
diff --git a/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.h b/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.h
index cd6fc5d9da3..f46bd8d3718 100644
--- a/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.h
+++ b/chromium/services/cert_verifier/trial_comparison_cert_verifier_mojo.h
@@ -9,7 +9,6 @@
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chromium/services/data_decoder/BUILD.gn b/chromium/services/data_decoder/BUILD.gn
index d3cdd331fee..aef7f57d826 100644
--- a/chromium/services/data_decoder/BUILD.gn
+++ b/chromium/services/data_decoder/BUILD.gn
@@ -13,8 +13,6 @@ source_set("lib") {
"gzipper.h",
"json_parser_impl.cc",
"json_parser_impl.h",
- "web_bundle_builder.cc",
- "web_bundle_builder.h",
"web_bundler.cc",
"web_bundler.h",
"xml_parser.cc",
@@ -65,7 +63,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_builder_unittest.cc",
"xml_parser_unittest.cc",
]
@@ -101,14 +98,29 @@ source_set("tests") {
}
}
-fuzzer_test("xml_parser_fuzzer") {
- sources = [ "xml_parser_fuzzer.cc" ]
- deps = [
+# This is a separate target because //third_party/libxml:libxml_utils
+# wants to limit its visibility to a select number of target, but the
+# "fuzzer_test" template expands on iOS to many targets that need to
+# have the "deps" information propagated in order to support "fat"
+# binaries.
+source_set("xml_parser_fuzzer_deps") {
+ visibility = [
+ ":run_xml_parser_fuzzer",
+ ":xml_parser_fuzzer",
+ ":xml_parser_fuzzer_arch_executable",
+ ":xml_parser_fuzzer_arch_executable_sources",
+ ]
+ public_deps = [
":lib",
"//base",
"//third_party/libxml:libxml_utils",
"//third_party/libxml:xml_reader",
]
+}
+
+fuzzer_test("xml_parser_fuzzer") {
+ sources = [ "xml_parser_fuzzer.cc" ]
+ deps = [ ":xml_parser_fuzzer_deps" ]
dict = "//third_party/libxml/fuzz/xml.dict"
seed_corpus = "//third_party/libxml/fuzz/seed_corpus"
}
diff --git a/chromium/services/data_decoder/ble_scan_parser_impl.h b/chromium/services/data_decoder/ble_scan_parser_impl.h
index ea9ffff6940..1b5d7fe2ebd 100644
--- a/chromium/services/data_decoder/ble_scan_parser_impl.h
+++ b/chromium/services/data_decoder/ble_scan_parser_impl.h
@@ -10,7 +10,6 @@
#include <vector>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "device/bluetooth/public/mojom/uuid.mojom.h"
#include "services/data_decoder/public/mojom/ble_scan_parser.mojom.h"
diff --git a/chromium/services/data_decoder/data_decoder_service.cc b/chromium/services/data_decoder/data_decoder_service.cc
index 09e29196b9e..c57170651f7 100644
--- a/chromium/services/data_decoder/data_decoder_service.cc
+++ b/chromium/services/data_decoder/data_decoder_service.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
diff --git a/chromium/services/data_decoder/data_decoder_service.h b/chromium/services/data_decoder/data_decoder_service.h
index 0650f942413..c0a7600fda7 100644
--- a/chromium/services/data_decoder/data_decoder_service.h
+++ b/chromium/services/data_decoder/data_decoder_service.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DATA_DECODER_DATA_DECODER_SERVICE_H_
#define SERVICES_DATA_DECODER_DATA_DECODER_SERVICE_H_
-#include "base/macros.h"
#include "build/chromeos_buildflags.h"
#include "components/web_package/mojom/web_bundle_parser.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/services/data_decoder/image_decoder_impl.h b/chromium/services/data_decoder/image_decoder_impl.h
index 2357adf0a4d..1db85fcb46d 100644
--- a/chromium/services/data_decoder/image_decoder_impl.h
+++ b/chromium/services/data_decoder/image_decoder_impl.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include "base/macros.h"
#include "services/data_decoder/public/mojom/image_decoder.mojom.h"
#include "ui/gfx/geometry/size.h"
diff --git a/chromium/services/data_decoder/image_decoder_impl_unittest.cc b/chromium/services/data_decoder/image_decoder_impl_unittest.cc
index 9127d4c2b85..30109661201 100644
--- a/chromium/services/data_decoder/image_decoder_impl_unittest.cc
+++ b/chromium/services/data_decoder/image_decoder_impl_unittest.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/cxx17_backports.h"
#include "base/lazy_instance.h"
+#include "base/memory/raw_ptr.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "gin/array_buffer.h"
@@ -32,11 +33,11 @@ const int64_t kTestMaxImageSize = 128 * 1024;
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if defined(USE_V8_CONTEXT_SNAPSHOT)
-constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
- gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext;
+constexpr gin::V8SnapshotFileType kSnapshotType =
+ gin::V8SnapshotFileType::kWithAdditionalContext;
#else
-constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
- gin::V8Initializer::V8SnapshotFileType::kDefault;
+constexpr gin::V8SnapshotFileType kSnapshotType =
+ gin::V8SnapshotFileType::kDefault;
#endif
#endif
@@ -75,7 +76,7 @@ class Request {
bitmap_ = result_image;
}
- ImageDecoderImpl* decoder_;
+ raw_ptr<ImageDecoderImpl> decoder_;
SkBitmap bitmap_;
};
@@ -112,7 +113,9 @@ class ImageDecoderImplTest : public testing::Test {
ImageDecoderImpl* decoder() { return &decoder_; }
private:
- base::test::SingleThreadTaskEnvironment task_environment_;
+ // V8 is generally multi threaded and may use tasks for arbitrary reasons,
+ // such as GC and off-thread compilation.
+ base::test::TaskEnvironment task_environment_;
ImageDecoderImpl decoder_;
};
diff --git a/chromium/services/data_decoder/json_parser_impl.h b/chromium/services/data_decoder/json_parser_impl.h
index 4bf8c9f96d2..addc46ceee2 100644
--- a/chromium/services/data_decoder/json_parser_impl.h
+++ b/chromium/services/data_decoder/json_parser_impl.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/macros.h"
#include "services/data_decoder/public/mojom/json_parser.mojom.h"
namespace data_decoder {
diff --git a/chromium/services/data_decoder/public/cpp/data_decoder.cc b/chromium/services/data_decoder/public/cpp/data_decoder.cc
index f0a6cf78f11..14401021107 100644
--- a/chromium/services/data_decoder/public/cpp/data_decoder.cc
+++ b/chromium/services/data_decoder/public/cpp/data_decoder.cc
@@ -46,6 +46,9 @@ class ValueParseRequest : public base::RefCounted<ValueParseRequest<T, V>> {
explicit ValueParseRequest(DataDecoder::ResultCallback<V> callback)
: callback_(std::move(callback)) {}
+ ValueParseRequest(const ValueParseRequest&) = delete;
+ ValueParseRequest& operator=(const ValueParseRequest&) = delete;
+
mojo::Remote<T>& remote() { return remote_; }
DataDecoder::ResultCallback<V>& callback() { return callback_; }
@@ -102,8 +105,6 @@ class ValueParseRequest : public base::RefCounted<ValueParseRequest<T, V>> {
mojo::Remote<T> remote_;
DataDecoder::ResultCallback<V> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(ValueParseRequest);
};
#if defined(OS_IOS)
diff --git a/chromium/services/data_decoder/public/cpp/data_decoder.h b/chromium/services/data_decoder/public/cpp/data_decoder.h
index dc85410ca59..c585f56a2fa 100644
--- a/chromium/services/data_decoder/public/cpp/data_decoder.h
+++ b/chromium/services/data_decoder/public/cpp/data_decoder.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/values.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/data_decoder/public/cpp/decode_image.cc b/chromium/services/data_decoder/public/cpp/decode_image.cc
index f9354606b0f..8657fc4b6b5 100644
--- a/chromium/services/data_decoder/public/cpp/decode_image.cc
+++ b/chromium/services/data_decoder/public/cpp/decode_image.cc
@@ -53,7 +53,7 @@ void OnDecodeImages(mojo::Remote<mojom::ImageDecoder> decoder,
}
void DecodeImageUsingServiceProcess(DataDecoder* data_decoder,
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
mojom::ImageCodec codec,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
@@ -82,7 +82,7 @@ void DecodeImageUsingServiceProcess(DataDecoder* data_decoder,
} // namespace
-void DecodeImageIsolated(const std::vector<uint8_t>& encoded_bytes,
+void DecodeImageIsolated(base::span<const uint8_t> encoded_bytes,
mojom::ImageCodec codec,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
@@ -105,7 +105,7 @@ void DecodeImageIsolated(const std::vector<uint8_t>& encoded_bytes,
}
void DecodeImage(DataDecoder* data_decoder,
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
mojom::ImageCodec codec,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
@@ -118,7 +118,7 @@ void DecodeImage(DataDecoder* data_decoder,
}
void DecodeAnimationIsolated(
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
mojom::ImageDecoder::DecodeAnimationCallback callback) {
@@ -137,7 +137,7 @@ void DecodeAnimationIsolated(
}
void DecodeAnimation(DataDecoder* data_decoder,
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
mojom::ImageDecoder::DecodeAnimationCallback callback) {
diff --git a/chromium/services/data_decoder/public/cpp/decode_image.h b/chromium/services/data_decoder/public/cpp/decode_image.h
index 05a9f7f1924..df235f248f8 100644
--- a/chromium/services/data_decoder/public/cpp/decode_image.h
+++ b/chromium/services/data_decoder/public/cpp/decode_image.h
@@ -7,8 +7,7 @@
#include <stdint.h>
-#include <vector>
-
+#include "base/containers/span.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/data_decoder/public/mojom/data_decoder_service.mojom.h"
@@ -36,13 +35,14 @@ using DecodeImageCallback =
// size if there's no precise match). Passing gfx::Size() as
// |desired_image_frame_size| is also supported and will result in chosing the
// smallest available size.
+//
// Upon completion, |callback| is invoked on the calling thread TaskRunner with
// an SkBitmap argument. The SkBitmap will be null on failure and non-null on
// success.
//
// This always uses an isolated instance of the Data Decoder service. To use a
// shared instance, call the signature below which takes a DataDecoder.
-void DecodeImageIsolated(const std::vector<uint8_t>& encoded_bytes,
+void DecodeImageIsolated(base::span<const uint8_t> encoded_bytes,
mojom::ImageCodec codec,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
@@ -53,7 +53,7 @@ void DecodeImageIsolated(const std::vector<uint8_t>& encoded_bytes,
// with other operations. |callback| will only be invoked if |data_decoder| is
// still alive by the time the decode operation is complete.
void DecodeImage(DataDecoder* data_decoder,
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
mojom::ImageCodec codec,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
@@ -67,7 +67,7 @@ void DecodeImage(DataDecoder* data_decoder,
// This always uses an isolated instance of the Data Decoder service. To use a
// shared instance, call the signature below which takes a DataDecoder.
void DecodeAnimationIsolated(
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
mojom::ImageDecoder::DecodeAnimationCallback callback);
@@ -76,7 +76,7 @@ void DecodeAnimationIsolated(
// with other operations. |callback| will only be invoked if |data_decoder| is
// still alive by the time the decode operation is complete.
void DecodeAnimation(DataDecoder* data_decoder,
- const std::vector<uint8_t>& encoded_bytes,
+ base::span<const uint8_t> encoded_bytes,
bool shrink_to_fit,
uint64_t max_size_in_bytes,
mojom::ImageDecoder::DecodeAnimationCallback callback);
diff --git a/chromium/services/data_decoder/public/cpp/json_sanitizer.h b/chromium/services/data_decoder/public/cpp/json_sanitizer.h
index 2fc92a19505..af9bfc94a5e 100644
--- a/chromium/services/data_decoder/public/cpp/json_sanitizer.h
+++ b/chromium/services/data_decoder/public/cpp/json_sanitizer.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace data_decoder {
@@ -33,14 +32,14 @@ class JsonSanitizer {
absl::optional<std::string> error;
};
+ JsonSanitizer(const JsonSanitizer&) = delete;
+ JsonSanitizer& operator=(const JsonSanitizer&) = delete;
+
// Starts sanitizing the passed in unsafe JSON string. The passed |callback|
// will be called with the result of the sanitization or an error message, but
// not before the method returns.
using Callback = base::OnceCallback<void(Result)>;
static void Sanitize(const std::string& json, Callback callback);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(JsonSanitizer);
};
} // namespace data_decoder
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 7a0721bc326..442768fd746 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
@@ -9,7 +9,6 @@
#include "base/callback_helpers.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
@@ -43,6 +42,9 @@ class MockFactory final : public web_package::mojom::WebBundleParserFactory {
mojo::PendingReceiver<web_package::mojom::WebBundleParser> receiver)
: receiver_(this, std::move(receiver)) {}
+ MockParser(const MockParser&) = delete;
+ MockParser& operator=(const MockParser&) = delete;
+
bool IsParseMetadataCalled() { return !metadata_callback_.is_null(); }
bool IsParseResponseCalled() { return !response_callback_.is_null(); }
@@ -62,11 +64,13 @@ class MockFactory final : public web_package::mojom::WebBundleParserFactory {
ParseMetadataCallback metadata_callback_;
ParseResponseCallback response_callback_;
mojo::Receiver<web_package::mojom::WebBundleParser> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(MockParser);
};
MockFactory() {}
+
+ MockFactory(const MockFactory&) = delete;
+ MockFactory& operator=(const MockFactory&) = delete;
+
void AddReceiver(
mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>
receiver) {
@@ -94,8 +98,6 @@ class MockFactory final : public web_package::mojom::WebBundleParserFactory {
std::unique_ptr<MockParser> parser_;
mojo::ReceiverSet<web_package::mojom::WebBundleParserFactory> receivers_;
-
- DISALLOW_COPY_AND_ASSIGN(MockFactory);
};
class MockDataSource final : public web_package::mojom::BundleDataSource {
@@ -104,13 +106,14 @@ class MockDataSource final : public web_package::mojom::BundleDataSource {
mojo::PendingReceiver<web_package::mojom::BundleDataSource> receiver)
: receiver_(this, std::move(receiver)) {}
+ MockDataSource(const MockDataSource&) = delete;
+ MockDataSource& operator=(const MockDataSource&) = delete;
+
private:
// Implements web_package::mojom::BundledDataSource.
void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {}
mojo::Receiver<web_package::mojom::BundleDataSource> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDataSource);
};
} // namespace
@@ -137,7 +140,7 @@ class SafeWebBundleParserTest : public testing::Test {
TEST_F(SafeWebBundleParserTest, ParseGoldenFile) {
SafeWebBundleParser parser;
base::File test_file =
- OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
+ OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello_b2.wbn")));
ASSERT_EQ(base::File::FILE_OK, parser.OpenFile(std::move(test_file)));
web_package::mojom::BundleMetadataPtr metadata_result;
@@ -236,7 +239,7 @@ TEST_F(SafeWebBundleParserTest, UseMockFactory) {
EXPECT_FALSE(raw_factory->GetCreatedParser());
base::File test_file =
- OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
+ OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello_b2.wbn")));
ASSERT_EQ(base::File::FILE_OK, parser.OpenFile(std::move(test_file)));
ASSERT_TRUE(raw_factory->GetCreatedParser());
EXPECT_FALSE(raw_factory->GetCreatedParser()->IsParseMetadataCalled());
diff --git a/chromium/services/data_decoder/public/cpp/safe_xml_parser.cc b/chromium/services/data_decoder/public/cpp/safe_xml_parser.cc
index 6c5902c252b..cdca29b5871 100644
--- a/chromium/services/data_decoder/public/cpp/safe_xml_parser.cc
+++ b/chromium/services/data_decoder/public/cpp/safe_xml_parser.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h b/chromium/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h
index c59166d73b4..06107edbca2 100644
--- a/chromium/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h
+++ b/chromium/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h
@@ -5,10 +5,9 @@
#ifndef SERVICES_DATA_DECODER_PUBLIC_CPP_TEST_SUPPORT_IN_PROCESS_DATA_DECODER_H_
#define SERVICES_DATA_DECODER_PUBLIC_CPP_TEST_SUPPORT_IN_PROCESS_DATA_DECODER_H_
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/data_decoder/data_decoder_service.h"
#include "services/data_decoder/public/cpp/service_provider.h"
diff --git a/chromium/services/data_decoder/public/mojom/BUILD.gn b/chromium/services/data_decoder/public/mojom/BUILD.gn
index 2bd526669fa..663666bc4ac 100644
--- a/chromium/services/data_decoder/public/mojom/BUILD.gn
+++ b/chromium/services/data_decoder/public/mojom/BUILD.gn
@@ -25,7 +25,7 @@ mojom("mojom") {
"//url/mojom:url_mojom_gurl",
]
- if (is_chromeos_ash) {
+ if (is_chromeos_ash || is_chromeos_lacros) {
sources += [ "ble_scan_parser.mojom" ]
public_deps += [ "//device/bluetooth/public/mojom" ]
}
diff --git a/chromium/services/data_decoder/web_bundle_builder.cc b/chromium/services/data_decoder/web_bundle_builder.cc
deleted file mode 100644
index 63cb7bbe364..00000000000
--- a/chromium/services/data_decoder/web_bundle_builder.cc
+++ /dev/null
@@ -1,153 +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/web_bundle_builder.h"
-
-#include "base/big_endian.h"
-#include "components/cbor/writer.h"
-
-namespace data_decoder {
-
-namespace {
-
-// TODO(myrzakereyms): replace this method with cbor::writer::GetNumUintBytes.
-uint64_t GetNumUintBytes(uint64_t value) {
- if (value < 24) {
- return 0;
- } else if (value <= 0xFF) {
- return 1;
- } else if (value <= 0xFFFF) {
- return 2;
- } else if (value <= 0xFFFFFFFF) {
- return 4;
- }
- return 8;
-}
-
-uint64_t GetEncodedByteSizeOfString(uint64_t size) {
- return 1 + GetNumUintBytes(size);
-}
-
-uint64_t GetEncodedByteSizeOfHeaders(const WebBundleBuilder::Headers& headers) {
- uint64_t byte_size = 1 + GetNumUintBytes(headers.size());
- for (const auto& header : headers) {
- byte_size +=
- GetEncodedByteSizeOfString(header.first.size()) + header.first.size() +
- GetEncodedByteSizeOfString(header.second.size()) + header.second.size();
- }
- return byte_size;
-}
-
-uint64_t GetEncodedByteSizeOfResponse(const WebBundleBuilder::Headers& headers,
- uint64_t body_size) {
- uint64_t encoded_header_map_size = GetEncodedByteSizeOfHeaders(headers);
- return 1 /* size of header of array(2) */ +
- GetEncodedByteSizeOfString(encoded_header_map_size) +
- encoded_header_map_size + GetEncodedByteSizeOfString(body_size) +
- body_size;
-}
-
-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));
-}
-
-std::vector<uint8_t> Encode(const cbor::Value& value) {
- return *cbor::Writer::Write(value);
-}
-
-int64_t EncodedLength(const cbor::Value& value) {
- return Encode(value).size();
-}
-} // namespace
-
-WebBundleBuilder::WebBundleBuilder(const std::string& fallback_url)
- : fallback_url_(fallback_url) {}
-
-WebBundleBuilder::~WebBundleBuilder() = default;
-
-void WebBundleBuilder::SetExchanges(
- std::vector<mojom::SerializedResourceInfoPtr> resources,
- std::vector<absl::optional<mojo_base::BigBuffer>> bodies) {
- CHECK_EQ(resources.size(), bodies.size());
- int64_t responses_offset = 1 + GetNumUintBytes(resources.size());
- for (size_t i = 0; i < resources.size(); ++i) {
- const auto& info = resources[i];
- const auto& body = bodies[i];
- Headers headers = {{":status", "200"}, {"content-type", info->mime_type}};
- uint64_t response_length =
- GetEncodedByteSizeOfResponse(headers, body ? body->size() : 0);
- ResponseLocation location = {responses_offset,
- static_cast<int64_t>(response_length)};
- responses_offset += response_length;
- cbor::Value::ArrayValue response_array;
- response_array.emplace_back(Encode(CreateHeaderMap(headers)));
- response_array.emplace_back(CreateByteString(
- body ? base::StringPiece(reinterpret_cast<const char*>(body->data()),
- body->size())
- : ""));
- cbor::Value response(response_array);
- responses_.emplace_back(std::move(response));
- GURL url = info->url;
- GURL::Replacements replacements;
- replacements.ClearRef();
- url = url.ReplaceComponents(replacements);
- AddIndexEntry(url.spec(), "", {location});
- }
-}
-
-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(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));
-}
-
-std::vector<uint8_t> WebBundleBuilder::CreateBundle(
- std::vector<mojom::SerializedResourceInfoPtr> resources,
- std::vector<absl::optional<mojo_base::BigBuffer>> bodies) {
- SetExchanges(std::move(resources), std::move(bodies));
- AddSection("index", cbor::Value(index_));
- AddSection("responses", cbor::Value(responses_));
- return CreateTopLevel();
-}
-
-std::vector<uint8_t> 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(fallback_url_));
- toplevel_array.emplace_back(Encode(cbor::Value(section_lengths_)));
- toplevel_array.emplace_back(sections_);
- // Put a dummy 8-byte bytestring.
- toplevel_array.emplace_back(cbor::Value::BinaryValue(8, 0));
-
- std::vector<uint8_t> bundle = Encode(cbor::Value(toplevel_array));
- char encoded[8];
- base::WriteBigEndian(encoded, static_cast<uint64_t>(bundle.size()));
- // Overwrite the dummy bytestring with the actual size.
- memcpy(bundle.data() + bundle.size() - 8, encoded, 8);
-
- return bundle;
-}
-} // namespace data_decoder
diff --git a/chromium/services/data_decoder/web_bundle_builder.h b/chromium/services/data_decoder/web_bundle_builder.h
deleted file mode 100644
index af461d77edd..00000000000
--- a/chromium/services/data_decoder/web_bundle_builder.h
+++ /dev/null
@@ -1,56 +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_WEB_BUNDLE_BUILDER_H_
-#define SERVICES_DATA_DECODER_WEB_BUNDLE_BUILDER_H_
-
-#include <vector>
-
-#include "base/files/file.h"
-#include "base/strings/string_piece.h"
-#include "components/cbor/values.h"
-#include "mojo/public/cpp/base/big_buffer.h"
-#include "services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace data_decoder {
-
-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;
- };
-
- explicit WebBundleBuilder(const std::string& fallback_url);
- ~WebBundleBuilder();
-
- WebBundleBuilder(const WebBundleBuilder&) = delete;
- WebBundleBuilder& operator=(const WebBundleBuilder&) = delete;
-
- std::vector<uint8_t> CreateBundle(
- std::vector<mojom::SerializedResourceInfoPtr> resources,
- std::vector<absl::optional<mojo_base::BigBuffer>> bodies);
-
- private:
- void SetExchanges(std::vector<mojom::SerializedResourceInfoPtr> resources,
- std::vector<absl::optional<mojo_base::BigBuffer>> bodies);
- void AddIndexEntry(base::StringPiece url,
- base::StringPiece variants_value,
- std::vector<ResponseLocation> response_locations);
- void AddSection(base::StringPiece name, cbor::Value section);
- void WriteBundleLength(uint8_t bundle_length);
- std::vector<uint8_t> CreateTopLevel();
-
- std::string fallback_url_;
- cbor::Value::ArrayValue section_lengths_;
- cbor::Value::ArrayValue sections_;
- cbor::Value::MapValue index_;
- cbor::Value::ArrayValue responses_;
-};
-} // namespace data_decoder
-
-#endif // SERVICES_DATA_DECODER_WEB_BUNDLE_BUILDER_H_
diff --git a/chromium/services/data_decoder/web_bundle_builder_unittest.cc b/chromium/services/data_decoder/web_bundle_builder_unittest.cc
deleted file mode 100644
index 734511b6672..00000000000
--- a/chromium/services/data_decoder/web_bundle_builder_unittest.cc
+++ /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.
-
-#include "services/data_decoder/web_bundle_builder.h"
-
-#include "base/big_endian.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/test/task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace data_decoder {
-
-namespace {
-
-std::string kFallbackUrl = "https://test.example.org/";
-
-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("components/test/data/web_package")));
-
- std::string contents;
- EXPECT_TRUE(base::ReadFileToString(test_data_dir.Append(path), &contents));
- return contents;
-}
-
-std::vector<uint8_t> GetStringAsBytes(base::StringPiece contents) {
- auto bytes = base::as_bytes(base::make_span(contents));
- return std::vector<uint8_t>(bytes.begin(), bytes.end());
-}
-
-} // namespace
-
-class WebBundleBuilderTest : public testing::Test {
- private:
- base::test::TaskEnvironment task_environment_;
-};
-
-TEST_F(WebBundleBuilderTest, CorrectWebBundleSizeIsWritten) {
- WebBundleBuilder builder(kFallbackUrl);
- std::vector<mojom::SerializedResourceInfoPtr> exchanges;
- mojom::SerializedResourceInfoPtr ptr = mojom::SerializedResourceInfo::New(
- GURL("https://test.example.org/index.html"), "text/html", 0);
- exchanges.emplace_back(std::move(ptr));
- std::vector<absl::optional<mojo_base::BigBuffer>> bodies;
- bodies.emplace_back();
- std::vector<uint8_t> bundle =
- builder.CreateBundle(std::move(exchanges), std::move(bodies));
- char written_size[8];
- memcpy(written_size, bundle.data() + bundle.size() - 8, 8);
- uint64_t written_size_int;
- base::ReadBigEndian(written_size, &written_size_int);
- EXPECT_EQ(bundle.size(), written_size_int);
-}
-
-TEST_F(WebBundleBuilderTest, ByteByByteComparison) {
- WebBundleBuilder builder(kFallbackUrl);
- std::vector<mojom::SerializedResourceInfoPtr> exchanges;
- std::vector<absl::optional<mojo_base::BigBuffer>> bodies;
- exchanges.emplace_back(mojom::SerializedResourceInfo::New(
- GURL("https://test.example.org/"), "text/html; charset=UTF-8", 46));
- bodies.emplace_back(absl::optional<mojo_base::BigBuffer>(
- GetStringAsBytes("<a href='index.html'>click for web bundles</a>")));
- exchanges.emplace_back(mojom::SerializedResourceInfo::New(
- GURL("https://test.example.org/index.html"), "text/html; charset=UTF-8",
- 25));
- bodies.emplace_back(absl::optional<mojo_base::BigBuffer>(
- GetStringAsBytes("<p>Hello Web Bundles!</p>")));
- std::vector<uint8_t> bundle =
- builder.CreateBundle(std::move(exchanges), std::move(bodies));
- std::vector<uint8_t> expected_bundle = GetStringAsBytes(
- GetTestFileContents(base::FilePath(FILE_PATH_LITERAL("simple.wbn"))));
- EXPECT_EQ(bundle, expected_bundle);
-}
-
-} // namespace data_decoder
diff --git a/chromium/services/data_decoder/web_bundler.cc b/chromium/services/data_decoder/web_bundler.cc
index 0d715a14643..5d0578933ef 100644
--- a/chromium/services/data_decoder/web_bundler.cc
+++ b/chromium/services/data_decoder/web_bundler.cc
@@ -7,7 +7,7 @@
#include "base/big_endian.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
-#include "web_bundle_builder.h"
+#include "components/web_package/web_bundle_builder.h"
namespace data_decoder {
@@ -93,7 +93,6 @@ void WebBundler::WriteWebBundleIndex() {
GURL::Replacements replacements;
replacements.ClearRef();
url = url.ReplaceComponents(replacements);
- WebBundleBuilder builder(url.spec());
std::set<GURL> url_set;
CHECK_EQ(resources_.size(), bodies_.size());
std::vector<mojom::SerializedResourceInfoPtr> resources;
@@ -113,8 +112,28 @@ void WebBundler::WriteWebBundleIndex() {
}
}
}
- std::vector<uint8_t> bundle =
- builder.CreateBundle(std::move(resources), std::move(bodies));
+
+ CHECK_EQ(resources.size(), bodies.size());
+ web_package::WebBundleBuilder builder(url.spec(), "",
+ web_package::BundleVersion::kB2);
+ for (size_t i = 0; i < resources.size(); ++i) {
+ const auto& info = resources[i];
+ const auto& body = bodies[i];
+ web_package::WebBundleBuilder::Headers headers = {
+ {":status", "200"}, {"content-type", info->mime_type}};
+ web_package::WebBundleBuilder::ResponseLocation response_location =
+ builder.AddResponse(
+ headers, body ? base::StringPiece(
+ reinterpret_cast<const char*>(body->data()),
+ body->size())
+ : "");
+ GURL url = info->url;
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url = url.ReplaceComponents(replacements);
+ builder.AddIndexEntry(url.spec(), "", {response_location});
+ }
+ std::vector<uint8_t> bundle = builder.CreateBundle();
int written_size = file_.WriteAtCurrentPos(
reinterpret_cast<const char*>(bundle.data()), bundle.size());
DCHECK_EQ(static_cast<int>(bundle.size()), written_size);
diff --git a/chromium/services/data_decoder/xml_parser.h b/chromium/services/data_decoder/xml_parser.h
index c73ed545eff..6b0476c2c96 100644
--- a/chromium/services/data_decoder/xml_parser.h
+++ b/chromium/services/data_decoder/xml_parser.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "services/data_decoder/public/mojom/xml_parser.mojom.h"
namespace data_decoder {
diff --git a/chromium/services/device/BUILD.gn b/chromium/services/device/BUILD.gn
index 9b9852a432a..2149bd7bd1a 100644
--- a/chromium/services/device/BUILD.gn
+++ b/chromium/services/device/BUILD.gn
@@ -87,6 +87,10 @@ source_set("lib") {
"//chromeos/lacros",
]
}
+
+ if (is_serial_enabled_platform) {
+ defines = [ "IS_SERIAL_ENABLED_PLATFORM" ]
+ }
}
# NOTE: We use a separate component target to support global binder overrides,
diff --git a/chromium/services/device/battery/OWNERS b/chromium/services/device/battery/OWNERS
deleted file mode 100644
index 56c64582cfe..00000000000
--- a/chromium/services/device/battery/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-blundell@chromium.org
-timvolodine@chromium.org
diff --git a/chromium/services/device/battery/battery_monitor_impl.h b/chromium/services/device/battery/battery_monitor_impl.h
index 57efb2d55bd..7621cdc048f 100644
--- a/chromium/services/device/battery/battery_monitor_impl.h
+++ b/chromium/services/device/battery/battery_monitor_impl.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_BATTERY_BATTERY_MONITOR_IMPL_H_
#define SERVICES_DEVICE_BATTERY_BATTERY_MONITOR_IMPL_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/device/battery/battery_status_service.h"
diff --git a/chromium/services/device/battery/battery_monitor_impl_unittest.cc b/chromium/services/device/battery/battery_monitor_impl_unittest.cc
index 279774b78fe..0abacb6050e 100644
--- a/chromium/services/device/battery/battery_monitor_impl_unittest.cc
+++ b/chromium/services/device/battery/battery_monitor_impl_unittest.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -120,7 +120,7 @@ class BatteryMonitorImplTest : public DeviceServiceTestBase {
mojo::Remote<mojom::BatteryMonitor> battery_monitor_;
private:
- FakeBatteryStatusManager* battery_manager_;
+ raw_ptr<FakeBatteryStatusManager> battery_manager_;
};
TEST_F(BatteryMonitorImplTest, BatteryManagerDefaultValues) {
diff --git a/chromium/services/device/battery/battery_status_manager_chromeos.cc b/chromium/services/device/battery/battery_status_manager_chromeos.cc
index 21aefcf8b6a..2e764ae8756 100644
--- a/chromium/services/device/battery/battery_status_manager_chromeos.cc
+++ b/chromium/services/device/battery/battery_status_manager_chromeos.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
@@ -23,6 +22,9 @@ class PowerManagerObserver
const BatteryStatusService::BatteryUpdateCallback& callback)
: callback_(callback), currently_listening_(false) {}
+ PowerManagerObserver(const PowerManagerObserver&) = delete;
+ PowerManagerObserver& operator=(const PowerManagerObserver&) = delete;
+
// Starts listening for updates.
void Start() {
if (currently_listening_)
@@ -115,8 +117,6 @@ class PowerManagerObserver
BatteryStatusService::BatteryUpdateCallback callback_;
bool currently_listening_;
-
- DISALLOW_COPY_AND_ASSIGN(PowerManagerObserver);
};
class BatteryStatusManagerChromeOS
diff --git a/chromium/services/device/battery/battery_status_manager_default.cc b/chromium/services/device/battery/battery_status_manager_default.cc
index fe24b5a396a..dd9709e0818 100644
--- a/chromium/services/device/battery/battery_status_manager_default.cc
+++ b/chromium/services/device/battery/battery_status_manager_default.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/notreached.h"
namespace device {
diff --git a/chromium/services/device/battery/battery_status_manager_linux.cc b/chromium/services/device/battery/battery_status_manager_linux.cc
index 467717f4ab7..e5c44e3ee55 100644
--- a/chromium/services/device/battery/battery_status_manager_linux.cc
+++ b/chromium/services/device/battery/battery_status_manager_linux.cc
@@ -15,9 +15,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/message_loop/message_pump_type.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/values.h"
#include "base/version.h"
diff --git a/chromium/services/device/battery/battery_status_manager_linux_unittest.cc b/chromium/services/device/battery/battery_status_manager_linux_unittest.cc
index 6c8b578d769..7802e05acb1 100644
--- a/chromium/services/device/battery/battery_status_manager_linux_unittest.cc
+++ b/chromium/services/device/battery/battery_status_manager_linux_unittest.cc
@@ -9,8 +9,8 @@
#include <string>
#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
@@ -41,6 +41,10 @@ const char kUPowerDisplayDevicePath[] =
class MockUPowerObject {
public:
MockUPowerObject() {}
+
+ MockUPowerObject(const MockUPowerObject&) = delete;
+ MockUPowerObject& operator=(const MockUPowerObject&) = delete;
+
void ConnectToSignal(
const std::string& interface_name,
const std::string& signal_name,
@@ -59,9 +63,6 @@ class MockUPowerObject {
std::string daemon_version;
std::list<std::string> devices;
std::string display_device;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockUPowerObject);
};
void MockUPowerObject::ConnectToSignal(
@@ -172,6 +173,10 @@ class MockBatteryObject {
MockBatteryObject(dbus::Bus* bus,
const std::string& object_path,
MockBatteryProperties* properties);
+
+ MockBatteryObject(const MockBatteryObject&) = delete;
+ MockBatteryObject& operator=(const MockBatteryObject&) = delete;
+
void ConnectToSignal(
const std::string& interface_name,
const std::string& signal_name,
@@ -194,8 +199,6 @@ class MockBatteryObject {
void AppendPropertyToWriter(dbus::MessageWriter* writer,
const std::string& property_name);
void AppendAllPropertiesToWriter(dbus::MessageWriter* writer);
-
- DISALLOW_COPY_AND_ASSIGN(MockBatteryObject);
};
MockBatteryObject::MockBatteryObject(dbus::Bus* bus,
@@ -346,6 +349,11 @@ void MockBatteryObject::AppendAllPropertiesToWriter(
class BatteryStatusManagerLinuxTest : public testing::Test {
public:
BatteryStatusManagerLinuxTest() {}
+
+ BatteryStatusManagerLinuxTest(const BatteryStatusManagerLinuxTest&) = delete;
+ BatteryStatusManagerLinuxTest& operator=(
+ const BatteryStatusManagerLinuxTest&) = delete;
+
void SetUp() override;
MockBatteryObject& SetUpDisplayDeviceProxy(MockBatteryProperties* properties);
@@ -391,8 +399,6 @@ class BatteryStatusManagerLinuxTest : public testing::Test {
std::unique_ptr<BatteryStatusManagerLinux> manager_;
int count_battery_updates_ = 0;
mojom::BatteryStatus last_status_;
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerLinuxTest);
};
void BatteryStatusManagerLinuxTest::SetUp() {
diff --git a/chromium/services/device/battery/battery_status_manager_mac.cc b/chromium/services/device/battery/battery_status_manager_mac.cc
index efbf817513f..d7c2bc89bea 100644
--- a/chromium/services/device/battery/battery_status_manager_mac.cc
+++ b/chromium/services/device/battery/battery_status_manager_mac.cc
@@ -13,7 +13,6 @@
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
-#include "base/macros.h"
#include "base/time/time.h"
namespace device {
diff --git a/chromium/services/device/battery/battery_status_manager_win.cc b/chromium/services/device/battery/battery_status_manager_win.cc
index d1911542e58..8887b3daa6c 100644
--- a/chromium/services/device/battery/battery_status_manager_win.cc
+++ b/chromium/services/device/battery/battery_status_manager_win.cc
@@ -8,7 +8,6 @@
#include <string>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/win/message_window.h"
#include "services/device/battery/battery_status_manager.h"
diff --git a/chromium/services/device/battery/battery_status_service.cc b/chromium/services/device/battery/battery_status_service.cc
index 7dd592e5048..ce1c6fcf913 100644
--- a/chromium/services/device/battery/battery_status_service.cc
+++ b/chromium/services/device/battery/battery_status_service.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/no_destructor.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/threading/thread_task_runner_handle.h"
#include "services/device/battery/battery_monitor_impl.h"
diff --git a/chromium/services/device/battery/battery_status_service.h b/chromium/services/device/battery/battery_status_service.h
index e44279b70c1..dc7468400e8 100644
--- a/chromium/services/device/battery/battery_status_service.h
+++ b/chromium/services/device/battery/battery_status_service.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/callback_list.h"
-#include "base/macros.h"
#include "services/device/public/mojom/battery_status.mojom.h"
namespace base {
diff --git a/chromium/services/device/battery/battery_status_service_unittest.cc b/chromium/services/device/battery/battery_status_service_unittest.cc
index f5674cfbd94..2243de24f09 100644
--- a/chromium/services/device/battery/battery_status_service_unittest.cc
+++ b/chromium/services/device/battery/battery_status_service_unittest.cc
@@ -8,7 +8,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "services/device/battery/battery_status_manager.h"
@@ -116,7 +116,7 @@ class BatteryStatusServiceTest : public testing::Test {
base::test::SingleThreadTaskEnvironment task_environment_;
BatteryStatusService battery_service_;
- FakeBatteryManager* battery_manager_;
+ raw_ptr<FakeBatteryManager> battery_manager_;
BatteryStatusService::BatteryUpdateCallback callback1_;
BatteryStatusService::BatteryUpdateCallback callback2_;
int callback1_invoked_count_;
diff --git a/chromium/services/device/binder_overrides.cc b/chromium/services/device/binder_overrides.cc
index 845eb38251d..cac7f1ac284 100644
--- a/chromium/services/device/binder_overrides.cc
+++ b/chromium/services/device/binder_overrides.cc
@@ -14,5 +14,12 @@ GeolocationContextBinder& GetGeolocationContextBinderOverride() {
return *binder;
}
+#if defined(OS_ANDROID)
+NFCProviderBinder& GetNFCProviderBinderOverride() {
+ static base::NoDestructor<NFCProviderBinder> binder;
+ return *binder;
+}
+#endif
+
} // namespace internal
} // namespace device
diff --git a/chromium/services/device/binder_overrides.h b/chromium/services/device/binder_overrides.h
index a000f15a8bc..d6aa0926e99 100644
--- a/chromium/services/device/binder_overrides.h
+++ b/chromium/services/device/binder_overrides.h
@@ -7,9 +7,14 @@
#include "base/callback.h"
#include "base/component_export.h"
+#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
+#if defined(OS_ANDROID)
+#include "services/device/public/mojom/nfc_provider.mojom.h"
+#endif
+
namespace device {
namespace internal {
@@ -18,6 +23,13 @@ using GeolocationContextBinder = base::RepeatingCallback<void(
COMPONENT_EXPORT(DEVICE_SERVICE_BINDER_OVERRIDES)
GeolocationContextBinder& GetGeolocationContextBinderOverride();
+#if defined(OS_ANDROID)
+using NFCProviderBinder = base::RepeatingCallback<void(
+ mojo::PendingReceiver<device::mojom::NFCProvider>)>;
+COMPONENT_EXPORT(DEVICE_SERVICE_BINDER_OVERRIDES)
+NFCProviderBinder& GetNFCProviderBinderOverride();
+#endif
+
} // namespace internal
} // namespace device
diff --git a/chromium/services/device/bluetooth/bluetooth_system.cc b/chromium/services/device/bluetooth/bluetooth_system.cc
index c9f6e5a44ff..687680165b9 100644
--- a/chromium/services/device/bluetooth/bluetooth_system.cc
+++ b/chromium/services/device/bluetooth/bluetooth_system.cc
@@ -16,6 +16,7 @@
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_admin_policy_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"
@@ -23,6 +24,23 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace device {
+namespace {
+
+bool GetDeviceIsBlockedByPolicy(const dbus::ObjectPath& device_path) {
+ bluez::BluetoothAdminPolicyClient::Properties* properties =
+ bluez::BluezDBusManager::Get()
+ ->GetAlternateBluetoothAdminPolicyClient()
+ ->GetProperties(device_path);
+ if (!properties)
+ return false;
+
+ if (!properties->is_blocked_by_policy.is_valid())
+ return false;
+
+ return properties->is_blocked_by_policy.value();
+}
+
+} // namespace
void BluetoothSystem::Create(
mojo::PendingReceiver<mojom::BluetoothSystem> receiver,
@@ -227,8 +245,7 @@ void BluetoothSystem::GetAvailableDevices(
? mojom::BluetoothDeviceInfo::ConnectionState::kConnected
: mojom::BluetoothDeviceInfo::ConnectionState::kNotConnected;
device_info->is_paired = properties->paired.value();
- device_info->is_blocked_by_policy =
- properties->is_blocked_by_policy.value();
+ device_info->is_blocked_by_policy = GetDeviceIsBlockedByPolicy(device_path);
// TODO(ortuno): Get the DeviceType from the device Class and Appearance.
devices.push_back(std::move(device_info));
diff --git a/chromium/services/device/bluetooth/bluetooth_system.h b/chromium/services/device/bluetooth/bluetooth_system.h
index 15074d7bb36..fe3188ed41f 100644
--- a/chromium/services/device/bluetooth/bluetooth_system.h
+++ b/chromium/services/device/bluetooth/bluetooth_system.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "dbus/object_path.h"
#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
diff --git a/chromium/services/device/bluetooth/bluetooth_system_factory.h b/chromium/services/device/bluetooth/bluetooth_system_factory.h
index 1ddf9b7bce9..6fe5383ab94 100644
--- a/chromium/services/device/bluetooth/bluetooth_system_factory.h
+++ b/chromium/services/device/bluetooth/bluetooth_system_factory.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_BLUETOOTH_BLUETOOTH_SYSTEM_FACTORY_H_
#define SERVICES_DEVICE_BLUETOOTH_BLUETOOTH_SYSTEM_FACTORY_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/mojom/bluetooth_system.mojom.h"
diff --git a/chromium/services/device/bluetooth/bluetooth_system_unittest.cc b/chromium/services/device/bluetooth/bluetooth_system_unittest.cc
index d5cb835737e..38e546e912e 100644
--- a/chromium/services/device/bluetooth/bluetooth_system_unittest.cc
+++ b/chromium/services/device/bluetooth/bluetooth_system_unittest.cc
@@ -17,6 +17,7 @@
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_admin_policy_client.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -64,7 +65,6 @@ struct FakeDeviceOptions {
absl::optional<std::string> name;
bool paired = false;
bool connected = false;
- bool is_blocked_by_policy = false;
};
// Exposes high-level methods to simulate Bluetooth events e.g. a new adapter
@@ -516,7 +516,6 @@ class DEVICE_BLUETOOTH_EXPORT TestBluetoothDeviceClient
}
properties->paired.ReplaceValue(options.paired);
- properties->is_blocked_by_policy.ReplaceValue(options.is_blocked_by_policy);
properties->connected.ReplaceValue(options.connected);
properties->adapter.ReplaceValue(options.adapter_object_path);
@@ -642,6 +641,91 @@ class DEVICE_BLUETOOTH_EXPORT TestBluetoothDeviceClient
base::ObserverList<Observer>::Unchecked observers_;
};
+// Exposes high-level methods to retrieve Bluetooth device admin policy info.
+class DEVICE_BLUETOOTH_EXPORT TestBluetoothAdminPolicyClient
+ : public bluez::BluetoothAdminPolicyClient {
+ public:
+ struct Properties : public bluez::BluetoothAdminPolicyClient::Properties {
+ explicit Properties(const PropertyChangedCallback& callback)
+ : BluetoothAdminPolicyClient::Properties(
+ /*object_proxy=*/nullptr,
+ bluetooth_admin_policy::kBluetoothAdminPolicyStatusInterface,
+ callback) {}
+ ~Properties() override = default;
+
+ // dbus::PropertySet
+ void Get(dbus::PropertyBase* property,
+ dbus::PropertySet::GetCallback callback) override {
+ NOTIMPLEMENTED() << "Get " << property->name();
+ }
+
+ void GetAll() override { NOTIMPLEMENTED() << "GetAll"; }
+
+ void Set(dbus::PropertyBase* property,
+ dbus::PropertySet::SetCallback callback) override {
+ NOTIMPLEMENTED() << "Set " << property->name();
+ }
+ };
+
+ TestBluetoothAdminPolicyClient() = default;
+ ~TestBluetoothAdminPolicyClient() override = default;
+
+ void SimulateAdminPolicyAdded(const dbus::ObjectPath& object_path,
+ bool is_blocked_by_policy) {
+ ObjectPathToProperties::iterator it;
+ bool was_inserted;
+ std::tie(it, was_inserted) = device_object_paths_to_properties_.emplace(
+ object_path,
+ std::make_unique<Properties>(
+ base::BindLambdaForTesting([&](const std::string& property_name) {
+ for (auto& observer : observers_)
+ observer.AdminPolicyPropertyChanged(object_path, property_name);
+ })));
+
+ DCHECK(was_inserted);
+
+ auto* properties = GetProperties(object_path);
+ properties->is_blocked_by_policy.ReplaceValue(is_blocked_by_policy);
+ properties->is_blocked_by_policy.set_valid(true);
+
+ for (auto& observer : observers_)
+ observer.AdminPolicyAdded(object_path);
+ }
+
+ // bluez::BluetoothAdminPolicyClient
+ void Init(dbus::Bus* bus,
+ const std::string& bluetooth_service_name) override {}
+
+ void AddObserver(Observer* observer) override {
+ observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(Observer* observer) override {
+ observers_.RemoveObserver(observer);
+ }
+
+ Properties* GetProperties(const dbus::ObjectPath& object_path) override {
+ auto it = device_object_paths_to_properties_.find(object_path);
+ if (it == device_object_paths_to_properties_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ void SetServiceAllowList(const dbus::ObjectPath& object_path,
+ const UUIDList& service_uuids,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) override {
+ NOTIMPLEMENTED() << "SetServiceAllowList";
+ }
+
+ private:
+ using ObjectPathToProperties =
+ std::map<dbus::ObjectPath, std::unique_ptr<Properties>>;
+ ObjectPathToProperties device_object_paths_to_properties_;
+
+ base::ObserverList<Observer>::Unchecked observers_;
+};
+
} // namespace
class BluetoothSystemTest : public DeviceServiceTestBase,
@@ -662,6 +746,10 @@ class BluetoothSystemTest : public DeviceServiceTestBase,
auto test_bluetooth_adapter_client =
std::make_unique<TestBluetoothAdapterClient>();
test_bluetooth_adapter_client_ = test_bluetooth_adapter_client.get();
+ auto test_bluetooth_admin_policy_client =
+ std::make_unique<TestBluetoothAdminPolicyClient>();
+ test_bluetooth_admin_policy_client_ =
+ test_bluetooth_admin_policy_client.get();
auto test_bluetooth_device_client =
std::make_unique<TestBluetoothDeviceClient>();
test_bluetooth_device_client_ = test_bluetooth_device_client.get();
@@ -670,6 +758,8 @@ class BluetoothSystemTest : public DeviceServiceTestBase,
bluez::BluezDBusManager::GetSetterForTesting();
dbus_setter->SetAlternateBluetoothAdapterClient(
std::move(test_bluetooth_adapter_client));
+ dbus_setter->SetAlternateBluetoothAdminPolicyClient(
+ std::move(test_bluetooth_admin_policy_client));
dbus_setter->SetAlternateBluetoothDeviceClient(
std::move(test_bluetooth_device_client));
}
@@ -769,6 +859,7 @@ class BluetoothSystemTest : public DeviceServiceTestBase,
mojo::Remote<mojom::BluetoothSystemFactory> system_factory_;
TestBluetoothAdapterClient* test_bluetooth_adapter_client_;
+ TestBluetoothAdminPolicyClient* test_bluetooth_admin_policy_client_;
TestBluetoothDeviceClient* test_bluetooth_device_client_;
mojo::Receiver<mojom::BluetoothSystemClient> system_client_receiver_{this};
@@ -1961,8 +2052,9 @@ TEST_F(BluetoothSystemTest, GetAvailableDevices) {
fake_options.name = "Fake Device";
fake_options.paired = true;
fake_options.connected = true;
- fake_options.is_blocked_by_policy = true;
test_bluetooth_device_client_->SimulateDeviceAdded(fake_options);
+ test_bluetooth_admin_policy_client_->SimulateAdminPolicyAdded(
+ fake_options.object_path, /*is_blocked_by_policy=*/true);
}
{
FakeDeviceOptions fake_options("2");
@@ -1970,8 +2062,9 @@ TEST_F(BluetoothSystemTest, GetAvailableDevices) {
fake_options.name = absl::nullopt;
fake_options.paired = false;
fake_options.connected = false;
- fake_options.is_blocked_by_policy = false;
test_bluetooth_device_client_->SimulateDeviceAdded(fake_options);
+ test_bluetooth_admin_policy_client_->SimulateAdminPolicyAdded(
+ fake_options.object_path, /*is_blocked_by_policy=*/false);
}
auto devices = GetAvailableDevicesAndWait(system.get());
diff --git a/chromium/services/device/device_posture/device_posture_platform_provider.h b/chromium/services/device/device_posture/device_posture_platform_provider.h
index 5986cfdf33f..73b68614ea7 100644
--- a/chromium/services/device/device_posture/device_posture_platform_provider.h
+++ b/chromium/services/device/device_posture/device_posture_platform_provider.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/memory/raw_ptr.h"
#include "services/device/public/mojom/device_posture_provider.mojom.h"
namespace device {
@@ -42,7 +43,7 @@ class DevicePosturePlatformProvider {
private:
// DevicePosturePlatformProvider is created and owned by
// DevicePostureProviderImpl making it safe to hold a raw pointer.
- DevicePostureProviderImpl* provider_;
+ raw_ptr<DevicePostureProviderImpl> provider_;
};
} // namespace device
diff --git a/chromium/services/device/device_posture/device_posture_provider_impl.h b/chromium/services/device/device_posture/device_posture_provider_impl.h
index 0dab91815d6..df4beaccb7c 100644
--- a/chromium/services/device/device_posture/device_posture_provider_impl.h
+++ b/chromium/services/device/device_posture/device_posture_provider_impl.h
@@ -9,7 +9,7 @@
#include <memory>
#include <string>
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.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/device_service.cc b/chromium/services/device/device_service.cc
index 407e434bfae..1081fb518f8 100644
--- a/chromium/services/device/device_service.cc
+++ b/chromium/services/device/device_service.cc
@@ -8,8 +8,8 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -119,8 +119,7 @@ DeviceService::DeviceService(
java_nfc_delegate_.Reset(params->java_nfc_delegate);
#endif
-#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
- defined(OS_WIN) || defined(OS_MAC)
+#if defined(IS_SERIAL_ENABLED_PLATFORM)
serial_port_manager_ = std::make_unique<SerialPortManagerImpl>(
io_task_runner_, base::ThreadTaskRunnerHandle::Get());
#if defined(OS_MAC)
@@ -133,7 +132,7 @@ DeviceService::DeviceService(
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT});
#endif
-#endif
+#endif // defined(IS_SERIAL_ENABLED_PLATFORM)
#if !defined(OS_ANDROID)
// Ensure that the battery backend is initialized now; otherwise it may end up
@@ -151,11 +150,18 @@ DeviceService::~DeviceService() {
// it's not really important that this runs anyway.
device::BatteryStatusService::GetInstance()->Shutdown();
#endif
-#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
+#if defined(IS_SERIAL_ENABLED_PLATFORM)
+ auto* serial_port_manager = serial_port_manager_.release();
+ if (!serial_port_manager_task_runner_->DeleteSoon(FROM_HERE,
+ serial_port_manager)) {
+ // The ThreadPool can be shutdown by the time ~DeviceService is triggered.
+ // Synchronously delete |serial_port_manager| in that event (which is
+ // naturally sequenced after the last task on
+ // |serial_port_manager_task_runner_| per ThreadPool shutdown semantics).
+ // See crbug.com/1263149#c20 for details.
+ delete serial_port_manager;
+ }
+#endif // defined(IS_SERIAL_ENABLED_PLATFORM)
}
void DeviceService::AddReceiver(
@@ -185,9 +191,19 @@ void DeviceService::BindBatteryMonitor(
}
#if defined(OS_ANDROID)
+// static
+void DeviceService::OverrideNFCProviderBinderForTesting(
+ NFCProviderBinder binder) {
+ internal::GetNFCProviderBinderOverride() = std::move(binder);
+}
+
void DeviceService::BindNFCProvider(
mojo::PendingReceiver<mojom::NFCProvider> receiver) {
- GetJavaInterfaceProvider()->GetInterface(std::move(receiver));
+ const auto& binder_override = internal::GetNFCProviderBinderOverride();
+ if (binder_override)
+ binder_override.Run(std::move(receiver));
+ else
+ GetJavaInterfaceProvider()->GetInterface(std::move(receiver));
}
#endif
@@ -322,8 +338,7 @@ void DeviceService::BindDevicePostureProvider(
void DeviceService::BindSerialPortManager(
mojo::PendingReceiver<mojom::SerialPortManager> receiver) {
-#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
- defined(OS_WIN) || defined(OS_MAC)
+#if defined(IS_SERIAL_ENABLED_PLATFORM)
// TODO(crbug.com/1109621): SerialPortManagerImpl depends on the
// permission_broker service on Chromium OS. We will need to redirect
// connections for LaCrOS here.
@@ -332,9 +347,9 @@ void DeviceService::BindSerialPortManager(
FROM_HERE, base::BindOnce(&SerialPortManagerImpl::Bind,
base::Unretained(serial_port_manager_.get()),
std::move(receiver)));
-#else
+#else // defined(IS_SERIAL_ENABLED_PLATFORM)
NOTREACHED() << "Serial devices not supported on this platform.";
-#endif
+#endif // defined(IS_SERIAL_ENABLED_PLATFORM)
}
void DeviceService::BindTimeZoneMonitor(
diff --git a/chromium/services/device/device_service.h b/chromium/services/device/device_service.h
index a12af40ed40..3320dc4751f 100644
--- a/chromium/services/device/device_service.h
+++ b/chromium/services/device/device_service.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -94,11 +95,12 @@ struct DeviceServiceParams {
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
- network::NetworkConnectionTracker* network_connection_tracker = nullptr;
+ raw_ptr<network::NetworkConnectionTracker> network_connection_tracker =
+ nullptr;
std::string geolocation_api_key;
CustomLocationProviderCallback custom_location_provider_callback;
bool use_gms_core_location_provider = false;
- GeolocationManager* geolocation_manager = nullptr;
+ raw_ptr<GeolocationManager> geolocation_manager = nullptr;
WakeLockContextCallback wake_lock_context_callback;
#if defined(OS_ANDROID)
@@ -131,6 +133,13 @@ class DeviceService : public mojom::DeviceService {
static void OverrideGeolocationContextBinderForTesting(
GeolocationContextBinder binder);
+#if defined(OS_ANDROID)
+ // Allows tests to override how frame hosts bind NFCProvider receivers.
+ using NFCProviderBinder = base::RepeatingCallback<void(
+ mojo::PendingReceiver<device::mojom::NFCProvider>)>;
+ static void OverrideNFCProviderBinderForTesting(NFCProviderBinder binder);
+#endif
+
private:
// mojom::DeviceService implementation:
void BindFingerprint(
@@ -216,7 +225,7 @@ class DeviceService : public mojom::DeviceService {
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
- network::NetworkConnectionTracker* network_connection_tracker_;
+ raw_ptr<network::NetworkConnectionTracker> network_connection_tracker_;
const std::string geolocation_api_key_;
WakeLockContextCallback wake_lock_context_callback_;
@@ -238,14 +247,13 @@ class DeviceService : public mojom::DeviceService {
std::unique_ptr<HidManagerImpl> hid_manager_;
#endif
-#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
- defined(OS_WIN) || defined(OS_MAC)
+#if defined(IS_SERIAL_ENABLED_PLATFORM)
// 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.
std::unique_ptr<SerialPortManagerImpl> serial_port_manager_;
scoped_refptr<base::SequencedTaskRunner> serial_port_manager_task_runner_;
-#endif
+#endif // defined(IS_SERIAL_ENABLED_PLATFORM)
#if defined(OS_ANDROID) || defined(OS_WIN)
std::unique_ptr<DevicePostureProviderImpl> device_posture_provider_;
diff --git a/chromium/services/device/device_service_test_base.cc b/chromium/services/device/device_service_test_base.cc
index 291d68099ab..ca8053c77ed 100644
--- a/chromium/services/device/device_service_test_base.cc
+++ b/chromium/services/device/device_service_test_base.cc
@@ -7,10 +7,9 @@
#include <memory>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "services/device/device_service.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
diff --git a/chromium/services/device/device_service_test_base.h b/chromium/services/device/device_service_test_base.h
index a7026e59d26..d6c287caa4a 100644
--- a/chromium/services/device/device_service_test_base.h
+++ b/chromium/services/device/device_service_test_base.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_DEVICE_SERVICE_TEST_BASE_H_
#define SERVICES_DEVICE_DEVICE_SERVICE_TEST_BASE_H_
-#include "base/macros.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/device/fingerprint/fingerprint_chromeos.h b/chromium/services/device/fingerprint/fingerprint_chromeos.h
index 2b5b2dd8e0b..e52b5fc37d3 100644
--- a/chromium/services/device/fingerprint/fingerprint_chromeos.h
+++ b/chromium/services/device/fingerprint/fingerprint_chromeos.h
@@ -9,7 +9,6 @@
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
-#include "base/macros.h"
#include "chromeos/dbus/biod/biod_client.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/device/fingerprint/fingerprint_chromeos_unittest.cc b/chromium/services/device/fingerprint/fingerprint_chromeos_unittest.cc
index 5a7dd822ccd..85ca06a675c 100644
--- a/chromium/services/device/fingerprint/fingerprint_chromeos_unittest.cc
+++ b/chromium/services/device/fingerprint/fingerprint_chromeos_unittest.cc
@@ -5,7 +5,6 @@
#include "services/device/fingerprint/fingerprint_chromeos.h"
#include "base/bind.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
diff --git a/chromium/services/device/generic_sensor/OWNERS b/chromium/services/device/generic_sensor/OWNERS
index d97025031c0..a7408f90cd6 100644
--- a/chromium/services/device/generic_sensor/OWNERS
+++ b/chromium/services/device/generic_sensor/OWNERS
@@ -1,2 +1,2 @@
raphael.kubo.da.costa@intel.com
-timvolodine@chromium.org
+reillyg@chromium.org
diff --git a/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h b/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h
index a84844477e9..13289f2bee3 100644
--- a/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h
+++ b/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_ABSOLUTE_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_ACCELEROMETER_AND_MAGNETOMETER_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_ABSOLUTE_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_ACCELEROMETER_AND_MAGNETOMETER_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
@@ -17,16 +16,21 @@ class
: public PlatformSensorFusionAlgorithm {
public:
AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer();
+
+ AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer(
+ const AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer&) =
+ delete;
+ AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer&
+ operator=(
+ const AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer&) =
+ delete;
+
~AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer()
override;
protected:
bool GetFusedDataInternal(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer_unittest.cc b/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer_unittest.cc
index cc5d2398abb..35b609730b7 100644
--- a/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer_unittest.cc
+++ b/chromium/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer_unittest.cc
@@ -4,6 +4,7 @@
#include <cmath>
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h"
@@ -69,7 +70,8 @@ class
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer*
+ raw_ptr<
+ AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer>
fusion_algorithm_;
};
diff --git a/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.cc b/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.cc
index 60d210d55bb..4d25d663bdd 100644
--- a/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.cc
+++ b/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.cc
@@ -26,7 +26,7 @@ FakePlatformSensor::FakePlatformSensor(
if (GetType() == mojom::SensorType::AMBIENT_LIGHT) {
// Set the shared buffer value as frequency for testing purpose.
reading.als.value = configuration.frequency();
- UpdateSharedBufferAndNotifyClients(reading);
+ AddNewReading(reading);
}
return true;
}));
@@ -58,6 +58,10 @@ double FakePlatformSensor::GetMinimumSupportedFrequency() {
return 1.0;
}
+void FakePlatformSensor::AddNewReading(const SensorReading& reading) {
+ UpdateSharedBufferAndNotifyClients(reading);
+}
+
FakePlatformSensorProvider::FakePlatformSensorProvider() {
ON_CALL(*this, DoCreateSensorInternal(_, _, _))
.WillByDefault(
diff --git a/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.h b/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.h
index 34ffbc7d6a8..fc71a26fd6c 100644
--- a/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.h
+++ b/chromium/services/device/generic_sensor/fake_platform_sensor_and_provider.h
@@ -5,8 +5,8 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_FAKE_PLATFORM_SENSOR_AND_PROVIDER_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_FAKE_PLATFORM_SENSOR_AND_PROVIDER_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
+#include "services/device/generic_sensor/platform_sensor.h"
#include "services/device/generic_sensor/platform_sensor_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -18,6 +18,9 @@ class FakePlatformSensor : public PlatformSensor {
SensorReadingSharedBuffer* reading_buffer,
PlatformSensorProvider* provider);
+ FakePlatformSensor(const FakePlatformSensor&) = delete;
+ FakePlatformSensor& operator=(const FakePlatformSensor&) = delete;
+
// PlatformSensor:
MOCK_METHOD1(StartSensor,
bool(const PlatformSensorConfiguration& configuration));
@@ -26,6 +29,9 @@ class FakePlatformSensor : public PlatformSensor {
maximum_supported_frequency_ = maximum_supported_frequency;
}
+ // Public interface to UpdateSharedBufferAndNotifyClients().
+ void AddNewReading(const SensorReading& reading);
+
protected:
void StopSensor() override {}
@@ -42,8 +48,6 @@ class FakePlatformSensor : public PlatformSensor {
double maximum_supported_frequency_ = 50.0;
~FakePlatformSensor() override;
-
- DISALLOW_COPY_AND_ASSIGN(FakePlatformSensor);
};
class FakePlatformSensorProvider : public PlatformSensorProvider {
@@ -84,6 +88,8 @@ class MockPlatformSensorClient : public PlatformSensor::Client {
~MockPlatformSensorClient() override;
+ scoped_refptr<PlatformSensor> sensor() const { return sensor_; }
+
// PlatformSensor::Client:
MOCK_METHOD1(OnSensorReadingChanged, void(mojom::SensorType type));
MOCK_METHOD0(OnSensorError, void());
diff --git a/chromium/services/device/generic_sensor/fake_platform_sensor_fusion.h b/chromium/services/device/generic_sensor/fake_platform_sensor_fusion.h
index de726d24095..3ce2bf7c2cd 100644
--- a/chromium/services/device/generic_sensor/fake_platform_sensor_fusion.h
+++ b/chromium/services/device/generic_sensor/fake_platform_sensor_fusion.h
@@ -8,7 +8,6 @@
#include <utility>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion.h"
namespace device {
@@ -18,6 +17,9 @@ class FakePlatformSensorFusion : public PlatformSensorFusion {
explicit FakePlatformSensorFusion(
std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm);
+ FakePlatformSensorFusion(const FakePlatformSensorFusion&) = delete;
+ FakePlatformSensorFusion& operator=(const FakePlatformSensorFusion&) = delete;
+
// PlatformSensorFusion:
bool GetSourceReading(mojom::SensorType type, SensorReading* result) override;
@@ -31,8 +33,6 @@ class FakePlatformSensorFusion : public PlatformSensorFusion {
private:
base::flat_map<mojom::SensorType, std::pair<SensorReading, bool>>
sensor_readings_;
-
- DISALLOW_COPY_AND_ASSIGN(FakePlatformSensorFusion);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc b/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc
index 12c7a591a12..a7cdc029057 100644
--- a/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc
+++ b/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc
@@ -5,8 +5,8 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -40,11 +40,13 @@ void CheckSuccess(base::OnceClosure quit_closure,
std::move(quit_closure).Run();
}
-
class TestSensorClient : public mojom::SensorClient {
public:
TestSensorClient(SensorType type) : type_(type) {}
+ TestSensorClient(const TestSensorClient&) = delete;
+ TestSensorClient& operator=(const TestSensorClient&) = delete;
+
// Implements mojom::SensorClient:
void SensorReadingChanged() override {
UpdateReadingData();
@@ -143,14 +145,15 @@ class TestSensorClient : public mojom::SensorClient {
// expected in SensorReadingChanged().
base::OnceCallback<void(double)> check_value_;
SensorType type_;
-
- DISALLOW_COPY_AND_ASSIGN(TestSensorClient);
};
class GenericSensorServiceTest : public DeviceServiceTestBase {
public:
GenericSensorServiceTest() = default;
+ GenericSensorServiceTest(const GenericSensorServiceTest&) = delete;
+ GenericSensorServiceTest& operator=(const GenericSensorServiceTest&) = delete;
+
void SetUp() override {
scoped_feature_list_.InitWithFeatures(
{features::kGenericSensorExtraClasses}, {});
@@ -158,7 +161,7 @@ class GenericSensorServiceTest : public DeviceServiceTestBase {
fake_platform_sensor_provider_ = new FakePlatformSensorProvider();
device_service_impl()->SetPlatformSensorProviderForTesting(
- base::WrapUnique(fake_platform_sensor_provider_));
+ base::WrapUnique(fake_platform_sensor_provider_.get()));
device_service()->BindSensorProvider(
sensor_provider_.BindNewPipeAndPassReceiver());
}
@@ -167,9 +170,7 @@ class GenericSensorServiceTest : public DeviceServiceTestBase {
base::test::ScopedFeatureList scoped_feature_list_;
// This object is owned by the DeviceService instance.
- FakePlatformSensorProvider* fake_platform_sensor_provider_;
-
- DISALLOW_COPY_AND_ASSIGN(GenericSensorServiceTest);
+ raw_ptr<FakePlatformSensorProvider> fake_platform_sensor_provider_;
};
// Requests the SensorProvider to create a sensor.
@@ -360,41 +361,41 @@ TEST_F(GenericSensorServiceTest, AddAndRemoveConfigurationTest) {
}
// Expect the SensorReadingChanged() will be called. The frequency value
- // should be 30.0
- PlatformSensorConfiguration configuration_30(30.0);
- client->sensor()->AddConfiguration(
- configuration_30,
- base::BindOnce(&TestSensorClient::OnAddConfiguration,
- base::Unretained(client.get()),
- base::BindOnce(&CheckSuccess, base::DoNothing(), true)));
+ // should be 10.0.
{
+ PlatformSensorConfiguration configuration_10(10.0);
+ client->sensor()->AddConfiguration(
+ configuration_10,
+ base::BindOnce(&TestSensorClient::OnAddConfiguration,
+ base::Unretained(client.get()),
+ base::BindOnce(&CheckSuccess, base::DoNothing(), true)));
base::RunLoop run_loop;
- client->SetCheckValueCallback(base::BindOnce(&CheckValue, 30.0));
+ client->SetCheckValueCallback(base::BindOnce(&CheckValue, 10.0));
client->SetQuitClosure(run_loop.QuitClosure());
run_loop.Run();
}
// Expect the SensorReadingChanged() will be called. The frequency value
- // should be 30.0 instead of 20.0
+ // should be 40.0.
+ PlatformSensorConfiguration configuration_40(40.0);
+ client->sensor()->AddConfiguration(
+ configuration_40,
+ base::BindOnce(&TestSensorClient::OnAddConfiguration,
+ base::Unretained(client.get()),
+ base::BindOnce(&CheckSuccess, base::DoNothing(), true)));
{
base::RunLoop run_loop;
- PlatformSensorConfiguration configuration_20(20.0);
- client->sensor()->AddConfiguration(
- configuration_20,
- base::BindOnce(&TestSensorClient::OnAddConfiguration,
- base::Unretained(client.get()),
- base::BindOnce(&CheckSuccess, base::DoNothing(), true)));
- client->SetCheckValueCallback(base::BindOnce(&CheckValue, 30.0));
+ client->SetCheckValueCallback(base::BindOnce(&CheckValue, 40.0));
client->SetQuitClosure(run_loop.QuitClosure());
run_loop.Run();
}
- // After 'configuration_30' is removed, expect the SensorReadingChanged() will
- // be called. The frequency value should be 20.0.
+ // After |configuration_40| is removed, expect the SensorReadingChanged() will
+ // be called. The frequency value should be 10.0.
{
base::RunLoop run_loop;
- client->sensor()->RemoveConfiguration(configuration_30);
- client->SetCheckValueCallback(base::BindOnce(&CheckValue, 20.0));
+ client->sensor()->RemoveConfiguration(configuration_40);
+ client->SetCheckValueCallback(base::BindOnce(&CheckValue, 10.0));
client->SetQuitClosure(run_loop.QuitClosure());
run_loop.Run();
}
@@ -455,16 +456,16 @@ TEST_F(GenericSensorServiceTest, SuspendThenResumeTest) {
}
// Expect the SensorReadingChanged() will be called. The frequency should
- // be 30.0 after AddConfiguration.
+ // be 10.0 after AddConfiguration.
{
base::RunLoop run_loop;
- PlatformSensorConfiguration configuration_1(30.0);
+ PlatformSensorConfiguration configuration_1(10.0);
client->sensor()->AddConfiguration(
configuration_1,
base::BindOnce(&TestSensorClient::OnAddConfiguration,
base::Unretained(client.get()),
base::BindOnce(&CheckSuccess, base::DoNothing(), true)));
- client->SetCheckValueCallback(base::BindOnce(&CheckValue, 30.0));
+ client->SetCheckValueCallback(base::BindOnce(&CheckValue, 10.0));
client->SetQuitClosure(run_loop.QuitClosure());
run_loop.Run();
}
diff --git a/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h b/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h
index 348ddb03089..94050de4bfb 100644
--- a/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h
+++ b/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_GRAVITY_FUSION_ALGORITHM_USING_ACCELEROMETER_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_GRAVITY_FUSION_ALGORITHM_USING_ACCELEROMETER_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
diff --git a/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer_unittest.cc b/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer_unittest.cc
index 68938e4b4b9..976b4ce6fe2 100644
--- a/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer_unittest.cc
+++ b/chromium/services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer_unittest.cc
@@ -4,6 +4,7 @@
#include "services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "services/device/generic_sensor/fake_platform_sensor_fusion.h"
@@ -101,7 +102,7 @@ class GravityFusionAlgorithmUsingAccelerometerTest : public testing::Test {
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- GravityFusionAlgorithmUsingAccelerometer* fusion_algorithm_;
+ raw_ptr<GravityFusionAlgorithmUsingAccelerometer> fusion_algorithm_;
};
} // namespace
diff --git a/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h b/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h
index 2cbea942c56..3e3338e27e5 100644
--- a/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h
+++ b/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_LINEAR_ACCELERATION_FUSION_ALGORITHM_USING_ACCELEROMETER_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_LINEAR_ACCELERATION_FUSION_ALGORITHM_USING_ACCELEROMETER_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
diff --git a/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer_unittest.cc b/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer_unittest.cc
index 995e5cc1d5b..f43b3208534 100644
--- a/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer_unittest.cc
+++ b/chromium/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer_unittest.cc
@@ -4,6 +4,7 @@
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "services/device/generic_sensor/fake_platform_sensor_fusion.h"
@@ -109,7 +110,8 @@ class LinearAccelerationFusionAlgorithmUsingAccelerometerTest
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- LinearAccelerationFusionAlgorithmUsingAccelerometer* fusion_algorithm_;
+ raw_ptr<LinearAccelerationFusionAlgorithmUsingAccelerometer>
+ fusion_algorithm_;
};
} // namespace
diff --git a/chromium/services/device/generic_sensor/linux/sensor_device_manager.h b/chromium/services/device/generic_sensor/linux/sensor_device_manager.h
index 45983ed0316..3227de5e9f9 100644
--- a/chromium/services/device/generic_sensor/linux/sensor_device_manager.h
+++ b/chromium/services/device/generic_sensor/linux/sensor_device_manager.h
@@ -7,10 +7,9 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "device/udev_linux/udev_watcher.h"
#include "services/device/public/mojom/sensor.mojom.h"
@@ -45,6 +44,10 @@ class SensorDeviceManager : public UdevWatcher::Observer {
};
explicit SensorDeviceManager(base::WeakPtr<Delegate> delegate);
+
+ SensorDeviceManager(const SensorDeviceManager&) = delete;
+ SensorDeviceManager& operator=(const SensorDeviceManager&) = delete;
+
~SensorDeviceManager() override;
// Starts monitoring sensor-related udev events, and enumerates existing
@@ -79,8 +82,6 @@ class SensorDeviceManager : public UdevWatcher::Observer {
base::WeakPtr<Delegate> delegate_;
scoped_refptr<base::SequencedTaskRunner> delegate_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(SensorDeviceManager);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h b/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h
index 4478d22af34..8df4be2ba4b 100644
--- a/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h
+++ b/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_QUATERNION_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_QUATERNION_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
@@ -16,15 +15,17 @@ class OrientationEulerAnglesFusionAlgorithmUsingQuaternion
: public PlatformSensorFusionAlgorithm {
public:
explicit OrientationEulerAnglesFusionAlgorithmUsingQuaternion(bool absolute);
+
+ OrientationEulerAnglesFusionAlgorithmUsingQuaternion(
+ const OrientationEulerAnglesFusionAlgorithmUsingQuaternion&) = delete;
+ OrientationEulerAnglesFusionAlgorithmUsingQuaternion& operator=(
+ const OrientationEulerAnglesFusionAlgorithmUsingQuaternion&) = delete;
+
~OrientationEulerAnglesFusionAlgorithmUsingQuaternion() override;
protected:
bool GetFusedDataInternal(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- OrientationEulerAnglesFusionAlgorithmUsingQuaternion);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion_unittest.cc b/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion_unittest.cc
index 60805f47f32..2c8f4d5be1c 100644
--- a/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion_unittest.cc
+++ b/chromium/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion_unittest.cc
@@ -4,6 +4,7 @@
#include "services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "services/device/generic_sensor/fake_platform_sensor_fusion.h"
@@ -29,7 +30,8 @@ class OrientationEulerAnglesFusionAlgorithmUsingQuaternionTest
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- OrientationEulerAnglesFusionAlgorithmUsingQuaternion* fusion_algorithm_;
+ raw_ptr<OrientationEulerAnglesFusionAlgorithmUsingQuaternion>
+ fusion_algorithm_;
};
TEST_F(OrientationEulerAnglesFusionAlgorithmUsingQuaternionTest,
diff --git a/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h b/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h
index 3cf574f48e0..742e2b771d1 100644
--- a/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h
+++ b/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_ORIENTATION_QUATERNION_FUSION_ALGORITHM_USING_EULER_ANGLES_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_ORIENTATION_QUATERNION_FUSION_ALGORITHM_USING_EULER_ANGLES_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
@@ -16,15 +15,17 @@ class OrientationQuaternionFusionAlgorithmUsingEulerAngles
: public PlatformSensorFusionAlgorithm {
public:
explicit OrientationQuaternionFusionAlgorithmUsingEulerAngles(bool absolute);
+
+ OrientationQuaternionFusionAlgorithmUsingEulerAngles(
+ const OrientationQuaternionFusionAlgorithmUsingEulerAngles&) = delete;
+ OrientationQuaternionFusionAlgorithmUsingEulerAngles& operator=(
+ const OrientationQuaternionFusionAlgorithmUsingEulerAngles&) = delete;
+
~OrientationQuaternionFusionAlgorithmUsingEulerAngles() override;
protected:
bool GetFusedDataInternal(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- OrientationQuaternionFusionAlgorithmUsingEulerAngles);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc b/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc
index 298925c1d29..9e3b084bf1e 100644
--- a/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc
+++ b/chromium/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc
@@ -4,6 +4,7 @@
#include <cmath>
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "services/device/generic_sensor/fake_platform_sensor_fusion.h"
@@ -30,7 +31,8 @@ class OrientationQuaternionFusionAlgorithmUsingEulerAnglesTest
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- OrientationQuaternionFusionAlgorithmUsingEulerAngles* fusion_algorithm_;
+ raw_ptr<OrientationQuaternionFusionAlgorithmUsingEulerAngles>
+ fusion_algorithm_;
};
TEST_F(OrientationQuaternionFusionAlgorithmUsingEulerAnglesTest,
diff --git a/chromium/services/device/generic_sensor/platform_sensor.cc b/chromium/services/device/generic_sensor/platform_sensor.cc
index d0ccc94e703..c1a3604fea7 100644
--- a/chromium/services/device/generic_sensor/platform_sensor.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
+#include "base/containers/cxx20_erase.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "services/device/generic_sensor/platform_sensor_provider.h"
#include "services/device/generic_sensor/platform_sensor_util.h"
@@ -23,12 +24,14 @@ PlatformSensor::PlatformSensor(mojom::SensorType type,
: main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
reading_buffer_(reading_buffer),
type_(type),
- provider_(provider),
- have_raw_reading_(false) {}
+ provider_(provider) {
+ VLOG(1) << "Platform sensor created. Type " << type_ << ".";
+}
PlatformSensor::~PlatformSensor() {
if (provider_)
provider_->RemoveSensor(GetType(), this);
+ VLOG(1) << "Platform sensor released. Type " << type_ << ".";
}
mojom::SensorType PlatformSensor::GetType() const {
@@ -72,23 +75,16 @@ bool PlatformSensor::StopListening(Client* client,
return false;
auto& config_list = client_entry->second;
- auto config_entry = std::find(config_list.begin(), config_list.end(), config);
- if (config_entry == config_list.end())
+ if (base::Erase(config_list, config) == 0)
return false;
- config_list.erase(config_entry);
-
return UpdateSensorInternal(config_map_);
}
bool PlatformSensor::StopListening(Client* client) {
DCHECK(client);
- auto client_entry = config_map_.find(client);
- if (client_entry == config_map_.end())
+ if (config_map_.erase(client) == 0)
return false;
-
- config_map_.erase(client_entry);
-
return UpdateSensorInternal(config_map_);
}
@@ -116,34 +112,43 @@ bool PlatformSensor::GetLatestReading(SensorReading* result) {
bool PlatformSensor::GetLatestRawReading(SensorReading* result) const {
base::AutoLock auto_lock(lock_);
- if (!have_raw_reading_)
+ if (!last_raw_reading_.has_value())
return false;
- *result = last_raw_reading_;
+ *result = last_raw_reading_.value();
return true;
}
void PlatformSensor::UpdateSharedBufferAndNotifyClients(
const SensorReading& reading) {
- UpdateSharedBuffer(reading);
- main_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&PlatformSensor::NotifySensorReadingChanged,
- weak_factory_.GetWeakPtr()));
+ if (UpdateSharedBuffer(reading, /*do_significance_check=*/true)) {
+ main_task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&PlatformSensor::NotifySensorReadingChanged,
+ weak_factory_.GetWeakPtr()));
+ }
}
-void PlatformSensor::UpdateSharedBuffer(const SensorReading& reading) {
+bool PlatformSensor::UpdateSharedBuffer(const SensorReading& reading,
+ bool do_significance_check) {
if (!reading_buffer_)
- return;
-
- ReadingBuffer* buffer = reading_buffer_;
- auto& seqlock = buffer->seqlock.value();
+ return false;
- // Save the raw (non-rounded) reading for fusion sensors.
{
base::AutoLock auto_lock(lock_);
+ // Bail out early if the new reading does not differ significantly from
+ // our current one, when the sensor is not reporting data continuously.
+ // Empty readings (i.e. with a zero timestamp) are always processed.
+ if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE &&
+ do_significance_check && last_raw_reading_.has_value() &&
+ !IsSignificantlyDifferent(*last_raw_reading_, reading, type_)) {
+ return false;
+ }
+ // Save the raw (non-rounded) reading for fusion sensors.
last_raw_reading_ = reading;
- have_raw_reading_ = true;
}
+ ReadingBuffer* buffer = reading_buffer_;
+ auto& seqlock = buffer->seqlock.value();
+
// Round the reading to guard user privacy. See https://crbug.com/1018180.
SensorReading rounded_reading = reading;
RoundSensorReading(&rounded_reading, type_);
@@ -151,6 +156,7 @@ void PlatformSensor::UpdateSharedBuffer(const SensorReading& reading) {
seqlock.WriteBegin();
buffer->reading = rounded_reading;
seqlock.WriteEnd();
+ return true;
}
void PlatformSensor::NotifySensorReadingChanged() {
@@ -185,7 +191,11 @@ bool PlatformSensor::UpdateSensorInternal(const ConfigMap& configurations) {
if (!optimal_configuration) {
is_active_ = false;
StopSensor();
- UpdateSharedBuffer(SensorReading());
+ // If we reached this condition, we want to set the current reading to zero
+ // regardless of the previous reading's value per
+ // https://w3c.github.io/sensors/#set-sensor-settings. That is the reason
+ // to skip significance check.
+ UpdateSharedBuffer(SensorReading(), /*do_significance_check=*/false);
return true;
}
diff --git a/chromium/services/device/generic_sensor/platform_sensor.h b/chromium/services/device/generic_sensor/platform_sensor.h
index e60d0164992..ff5ac15b838 100644
--- a/chromium/services/device/generic_sensor/platform_sensor.h
+++ b/chromium/services/device/generic_sensor/platform_sensor.h
@@ -11,15 +11,17 @@
#include "base/callback_forward.h"
#include "base/location.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/thread_annotations.h"
#include "mojo/public/cpp/system/buffer.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "services/device/public/mojom/sensor.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace device {
@@ -41,6 +43,9 @@ class PlatformSensor : public base::RefCountedThreadSafe<PlatformSensor> {
virtual ~Client() {}
};
+ PlatformSensor(const PlatformSensor&) = delete;
+ PlatformSensor& operator=(const PlatformSensor&) = delete;
+
virtual mojom::ReportingMode GetReportingMode() = 0;
virtual PlatformSensorConfiguration GetDefaultConfiguration() = 0;
virtual bool CheckSensorConfiguration(
@@ -105,10 +110,6 @@ class PlatformSensor : public base::RefCountedThreadSafe<PlatformSensor> {
// Note: this method is thread-safe.
void UpdateSharedBufferAndNotifyClients(const SensorReading& reading);
- // Updates shared buffer with provided SensorReading
- // Note: this method is thread-safe.
- void UpdateSharedBuffer(const SensorReading& reading);
-
void NotifySensorReadingChanged();
void NotifySensorError();
@@ -126,18 +127,26 @@ class PlatformSensor : public base::RefCountedThreadSafe<PlatformSensor> {
private:
friend class base::RefCountedThreadSafe<PlatformSensor>;
+ // Updates shared buffer with provided SensorReading. If
+ // |do_significance_check| is true then |last_raw_reading_| and
+ // |reading_buffer_| are only updated if |reading| is significantly different
+ // from |last_raw_reading_|. Returns true if |reading_buffer_| has been
+ // updated, and false otherwise.
+ // Note: this method is thread-safe.
+ bool UpdateSharedBuffer(const SensorReading& reading,
+ bool do_significance_check);
+
scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
- SensorReadingSharedBuffer* reading_buffer_; // NOTE: Owned by |provider_|.
+ raw_ptr<SensorReadingSharedBuffer>
+ reading_buffer_; // NOTE: Owned by |provider_|.
mojom::SensorType type_;
ConfigMap config_map_;
- PlatformSensorProvider* provider_;
+ raw_ptr<PlatformSensorProvider> provider_;
bool is_active_ = false;
- SensorReading last_raw_reading_;
- mutable base::Lock lock_; // Protect have_raw_reading_ and last_raw_reading_.
- bool have_raw_reading_;
+ absl::optional<SensorReading> last_raw_reading_ GUARDED_BY(lock_);
+ mutable base::Lock lock_; // Protect last_raw_reading_.
base::WeakPtrFactory<PlatformSensor> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(PlatformSensor);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_accelerometer_mac.h b/chromium/services/device/generic_sensor/platform_sensor_accelerometer_mac.h
index d1adb4cc997..d4244224373 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_accelerometer_mac.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_accelerometer_mac.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "services/device/generic_sensor/platform_sensor.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
@@ -27,6 +27,11 @@ class PlatformSensorAccelerometerMac : public PlatformSensor {
PlatformSensorAccelerometerMac(SensorReadingSharedBuffer* reading_buffer,
PlatformSensorProvider* provider);
+ PlatformSensorAccelerometerMac(const PlatformSensorAccelerometerMac&) =
+ delete;
+ PlatformSensorAccelerometerMac& operator=(
+ const PlatformSensorAccelerometerMac&) = delete;
+
mojom::ReportingMode GetReportingMode() override;
// Can only be called once, the first time or after a StopSensor call.
bool StartSensor(const PlatformSensorConfiguration& configuration) override;
@@ -52,8 +57,6 @@ class PlatformSensorAccelerometerMac : public PlatformSensor {
bool is_reading_active_ = false;
base::WeakPtrFactory<PlatformSensorAccelerometerMac> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorAccelerometerMac);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_ambient_light_mac.h b/chromium/services/device/generic_sensor/platform_sensor_ambient_light_mac.h
index c8c9db86800..398a4db92ab 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_ambient_light_mac.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_ambient_light_mac.h
@@ -24,6 +24,10 @@ class PlatformSensorAmbientLightMac : public PlatformSensor {
PlatformSensorAmbientLightMac(SensorReadingSharedBuffer* reading_buffer,
PlatformSensorProvider* provider);
+ PlatformSensorAmbientLightMac(const PlatformSensorAmbientLightMac&) = delete;
+ PlatformSensorAmbientLightMac& operator=(
+ const PlatformSensorAmbientLightMac&) = delete;
+
mojom::ReportingMode GetReportingMode() override;
// Can only be called once, the first time or after a StopSensor call.
bool StartSensor(const PlatformSensorConfiguration& configuration) override;
@@ -54,8 +58,6 @@ class PlatformSensorAmbientLightMac : public PlatformSensor {
// sensor is busy.
base::mac::ScopedIOObject<io_object_t> light_sensor_busy_notification_;
double current_lux_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorAmbientLightMac);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc
index 5218e2df796..ef85521920f 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
#include "services/device/generic_sensor/platform_sensor_provider.h"
#include "base/bind.h"
-#include "base/macros.h"
#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
#include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
+#include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
+#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
@@ -16,19 +19,58 @@ using ::testing::NiceMock;
namespace device {
+using mojom::SensorType;
+
+namespace {
+
+// Attempts to add a new reading to the sensor owned by |sensor_client|, and
+// asserts that it does not lead to OnSensorReadingChanged() being called (i.e.
+// PlatformSensor's significance check has failed).
+void AddNewReadingAndExpectNoReadingChangedEvent(
+ MockPlatformSensorClient* sensor_client,
+ const SensorReading& new_reading) {
+ scoped_refptr<FakePlatformSensor> fake_sensor =
+ static_cast<FakePlatformSensor*>(sensor_client->sensor().get());
+ fake_sensor->AddNewReading(new_reading);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(*sensor_client, OnSensorReadingChanged(SensorType::AMBIENT_LIGHT))
+ .Times(0);
+ run_loop.RunUntilIdle();
+}
+
+// Add a new reading to the sensor owned by |sensor_client|, and expect reading
+// change event.
+void AddNewReadingAndExpectReadingChangedEvent(
+ MockPlatformSensorClient* sensor_client,
+ const SensorReading& new_reading) {
+ scoped_refptr<FakePlatformSensor> fake_sensor =
+ static_cast<FakePlatformSensor*>(sensor_client->sensor().get());
+ fake_sensor->AddNewReading(new_reading);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(*sensor_client, OnSensorReadingChanged(SensorType::AMBIENT_LIGHT))
+ .WillOnce(Invoke([&](SensorType) { run_loop.Quit(); }));
+ run_loop.Run();
+}
+
+} // namespace
+
class PlatformSensorProviderTest : public testing::Test {
public:
PlatformSensorProviderTest() {
provider_ = std::make_unique<FakePlatformSensorProvider>();
}
+ PlatformSensorProviderTest(const PlatformSensorProviderTest&) = delete;
+ PlatformSensorProviderTest& operator=(const PlatformSensorProviderTest&) =
+ delete;
+
protected:
std::unique_ptr<FakePlatformSensorProvider> provider_;
private:
base::test::TaskEnvironment task_environment_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorProviderTest);
};
TEST_F(PlatformSensorProviderTest, ResourcesAreFreed) {
@@ -98,4 +140,61 @@ TEST_F(PlatformSensorProviderTest, SharedBufferCleared) {
}));
}
+TEST_F(PlatformSensorProviderTest, PlatformSensorSignificanceChecks) {
+ base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
+ provider_->CreateSensor(SensorType::AMBIENT_LIGHT, future.GetCallback());
+ scoped_refptr<FakePlatformSensor> fake_sensor =
+ static_cast<FakePlatformSensor*>(future.Get().get());
+
+ // Override FakePlatformSensor's default StartSensor() expectation; we
+ // do not want to do anything in StartSensor().
+ ON_CALL(*fake_sensor, StartSensor(_))
+ .WillByDefault(
+ Invoke([&](const PlatformSensorConfiguration& configuration) {
+ return true;
+ }));
+
+ auto client = std::make_unique<MockPlatformSensorClient>(fake_sensor);
+ EXPECT_TRUE(fake_sensor->StartListening(client.get(),
+ PlatformSensorConfiguration(10)));
+
+ // This checks that illuminance significance check causes the following
+ // to happen:
+ // 1. Initial value is set to 24. And test checks it can be read back.
+ // 2. New reading is attempted to set to 35.
+ // 3. Value is read from sensor and compared new reading. But as new
+ // reading was not significantly different compared to initial, for
+ // privacy reasons, service returns the initial value.
+ // 4. New value is set to 49. And test checks it can be read back. New
+ // value is allowed as it is significantly different compared to old
+ // value (24).
+ // 5. New reading is attempted to set to 35.
+ // 6. Value is read from sensor and compared new reading. But as new
+ // reading was not significantly different compared to initial, for
+ // privacy reasons, service returns the initial value.
+ // 7. New value is set to 24. And test checks it can be read back. New
+ // value is allowed as it is significantly different compared to old
+ // value (49).
+ const struct {
+ const double attempted_als_value;
+ const double expected_als_value;
+ } kTestCases[] = {
+ {24, 24}, {35, 24}, {49, 49}, {35, 49}, {24, 24},
+ };
+
+ for (const auto& test_case : kTestCases) {
+ SensorReading reading;
+ reading.raw.timestamp = 1.0;
+ reading.als.value = test_case.attempted_als_value;
+
+ if (reading.als.value == test_case.expected_als_value)
+ AddNewReadingAndExpectReadingChangedEvent(client.get(), reading);
+ else
+ AddNewReadingAndExpectNoReadingChangedEvent(client.get(), reading);
+
+ fake_sensor->GetLatestReading(&reading);
+ EXPECT_EQ(reading.als.value, test_case.expected_als_value);
+ }
+}
+
} // namespace device
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 4af5f198568..7345269a4b8 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
@@ -5,6 +5,7 @@
#include <algorithm>
#include <memory>
+#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -977,4 +978,46 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
EXPECT_TRUE(sensor);
}
+// https://crbug.com/1254396: Make sure sensor enumeration steps happen in the
+// right order. This could be converted into a web test in the future if we
+// stop using mocks there (just setting window.ondevicemotion is enough to
+// trigger similar behavior).
+TEST_F(PlatformSensorAndProviderLinuxTest,
+ AccelerometerAndLinearAccelerationEnumeration) {
+ double sensor_values[kSensorValuesSize] = {0, 0, -base::kMeanGravityDouble};
+ InitializeSupportedSensor(SensorType::ACCELEROMETER,
+ kAccelerometerFrequencyValue, kZero, kZero,
+ sensor_values);
+
+ SetServiceStart();
+
+ base::RunLoop run_loop;
+ base::RepeatingClosure barrier_closure =
+ base::BarrierClosure(2, run_loop.QuitClosure());
+
+ // We cannot call PlatformSensorAndProviderLinuxTest::CreateSensor() like the
+ // other tests because we need more control over the RunLoop; both calls to
+ // PlatformSensorProviderBase::CreateSensor() must happen before the RunLoop
+ // runs (and therefore before sensor enumeration finishes).
+ scoped_refptr<PlatformSensor> accelerometer;
+ provider_->CreateSensor(
+ SensorType::ACCELEROMETER,
+ base::BindLambdaForTesting([&](scoped_refptr<PlatformSensor> sensor) {
+ accelerometer = std::move(sensor);
+ barrier_closure.Run();
+ }));
+ scoped_refptr<PlatformSensor> linear_acceleration;
+ provider_->CreateSensor(
+ SensorType::LINEAR_ACCELERATION,
+ base::BindLambdaForTesting([&](scoped_refptr<PlatformSensor> sensor) {
+ linear_acceleration = std::move(sensor);
+ barrier_closure.Run();
+ }));
+
+ run_loop.Run();
+
+ ASSERT_TRUE(accelerometer);
+ ASSERT_TRUE(linear_acceleration);
+}
+
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_android.h b/chromium/services/device/generic_sensor/platform_sensor_android.h
index 31f6140aef3..2acd5de501d 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_android.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_android.h
@@ -25,6 +25,9 @@ class PlatformSensorAndroid : public PlatformSensor {
SensorReadingSharedBuffer* reading_buffer,
PlatformSensorProvider* provider);
+ PlatformSensorAndroid(const PlatformSensorAndroid&) = delete;
+ PlatformSensorAndroid& operator=(const PlatformSensorAndroid&) = delete;
+
mojom::ReportingMode GetReportingMode() override;
PlatformSensorConfiguration GetDefaultConfiguration() override;
double GetMaximumSupportedFrequency() override;
@@ -51,7 +54,6 @@ class PlatformSensorAndroid : public PlatformSensor {
private:
// Java object org.chromium.device.sensors.PlatformSensor
base::android::ScopedJavaGlobalRef<jobject> j_object_;
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorAndroid);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_chromeos.h b/chromium/services/device/generic_sensor/platform_sensor_chromeos.h
index 406630bebd4..3c13ef20d8d 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_chromeos.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_chromeos.h
@@ -103,11 +103,6 @@ class PlatformSensorChromeOS
// Channel indices of |required_channel_ids_| to enable.
std::vector<int32_t> channel_indices_;
- // Stores previously read values that are used to
- // determine whether the recent values are changed
- // and IPC can be notified that updates are available.
- SensorReading old_values_;
-
// Number of failed reads. Triggers an error if it reaches
// kNumFailedReadsBeforeGivingUp.
uint32_t num_failed_reads_ = 0;
diff --git a/chromium/services/device/generic_sensor/platform_sensor_fusion.cc b/chromium/services/device/generic_sensor/platform_sensor_fusion.cc
index 5193295d54f..f3f6e0526dc 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_fusion.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_fusion.cc
@@ -8,8 +8,10 @@
#include "base/bind.h"
#include "base/check.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
+#include "base/ranges/algorithm.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
#include "services/device/generic_sensor/platform_sensor_provider.h"
#include "services/device/generic_sensor/platform_sensor_util.h"
@@ -87,8 +89,9 @@ class PlatformSensorFusion::Factory : public base::RefCounted<Factory> {
std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm_;
PlatformSensorProviderBase::CreateSensorCallback result_callback_;
- SensorReadingSharedBuffer* reading_buffer_; // NOTE: Owned by |provider_|.
- PlatformSensorProvider* provider_;
+ raw_ptr<SensorReadingSharedBuffer>
+ reading_buffer_; // NOTE: Owned by |provider_|.
+ raw_ptr<PlatformSensorProvider> provider_;
PlatformSensorFusion::SourcesMap sources_map_;
};
@@ -116,11 +119,10 @@ PlatformSensorFusion::PlatformSensorFusion(
fusion_algorithm_->set_fusion_sensor(this);
- if (std::any_of(source_sensors_.begin(), source_sensors_.end(),
- [](const SourcesMapEntry& pair) {
- return pair.second->GetReportingMode() ==
- mojom::ReportingMode::ON_CHANGE;
- })) {
+ if (base::ranges::any_of(source_sensors_, [](const auto& pair) {
+ return pair.second->GetReportingMode() ==
+ mojom::ReportingMode::ON_CHANGE;
+ })) {
reporting_mode_ = mojom::ReportingMode::ON_CHANGE;
}
}
diff --git a/chromium/services/device/generic_sensor/platform_sensor_fusion.h b/chromium/services/device/generic_sensor/platform_sensor_fusion.h
index 902fbc42c84..70d172bb7f0 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_fusion.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_fusion.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor.h"
#include "services/device/generic_sensor/platform_sensor_provider_base.h"
@@ -24,8 +23,8 @@ class PlatformSensorFusionAlgorithm;
//
// This class implements the generic concept of sensor fusion. It implements
// a new sensor using data from one or more existing sensors. For example,
-// it can implements a *_EULER_ANGLES orientation sensor using a
-// *_QUATERNION orientation sensor, or vice a versa.
+// it can implement a *_EULER_ANGLES orientation sensor using a
+// *_QUATERNION orientation sensor, or vice-versa.
//
// It can also implement an orientation sensor using an ACCELEROMETER, etc.
class PlatformSensorFusion : public PlatformSensor,
@@ -43,6 +42,9 @@ class PlatformSensorFusion : public PlatformSensor,
std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm,
PlatformSensorProviderBase::CreateSensorCallback callback);
+ PlatformSensorFusion(const PlatformSensorFusion&) = delete;
+ PlatformSensorFusion& operator=(const PlatformSensorFusion&) = delete;
+
// PlatformSensor:
mojom::ReportingMode GetReportingMode() override;
PlatformSensorConfiguration GetDefaultConfiguration() override;
@@ -59,11 +61,8 @@ class PlatformSensorFusion : public PlatformSensor,
protected:
class Factory;
- friend class Factory;
using SourcesMap =
base::flat_map<mojom::SensorType, scoped_refptr<PlatformSensor>>;
- using SourcesMapEntry =
- std::pair<mojom::SensorType, scoped_refptr<PlatformSensor>>;
PlatformSensorFusion(
SensorReadingSharedBuffer* reading_buffer,
PlatformSensorProvider* provider,
@@ -78,8 +77,6 @@ class PlatformSensorFusion : public PlatformSensor,
std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm_;
SourcesMap source_sensors_;
mojom::ReportingMode reporting_mode_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorFusion);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_fusion_algorithm.h b/chromium/services/device/generic_sensor/platform_sensor_fusion_algorithm.h
index 30d9d93bf34..d3f8214de46 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_fusion_algorithm.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_fusion_algorithm.h
@@ -7,7 +7,7 @@
#include <vector>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
@@ -60,7 +60,7 @@ class PlatformSensorFusionAlgorithm {
SensorReading* fused_reading) = 0;
// This raw pointer is safe because |fusion_sensor_| owns this object.
- PlatformSensorFusion* fusion_sensor_ = nullptr;
+ raw_ptr<PlatformSensorFusion> fusion_sensor_ = nullptr;
private:
// Default threshold for comparing SensorReading values. If a
diff --git a/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
index f7845c9b78d..29206b1a0a5 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
@@ -6,9 +6,9 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
#include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h"
#include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
@@ -31,38 +31,22 @@ class PlatformSensorFusionTest : public testing::Test {
provider_ = std::make_unique<FakePlatformSensorProvider>();
}
- protected:
- void AccelerometerCallback(scoped_refptr<PlatformSensor> sensor) {
- accelerometer_callback_called_ = true;
- accelerometer_ = static_cast<FakePlatformSensor*>(sensor.get());
- }
-
- void MagnetometerCallback(scoped_refptr<PlatformSensor> sensor) {
- magnetometer_callback_called_ = true;
- magnetometer_ = static_cast<FakePlatformSensor*>(sensor.get());
- }
-
- void PlatformSensorFusionCallback(scoped_refptr<PlatformSensor> sensor) {
- platform_sensor_fusion_callback_called_ = true;
- fusion_sensor_ = static_cast<PlatformSensorFusion*>(sensor.get());
- }
+ PlatformSensorFusionTest(const PlatformSensorFusionTest&) = delete;
+ PlatformSensorFusionTest& operator=(const PlatformSensorFusionTest&) = delete;
+ protected:
void CreateAccelerometer() {
- auto callback =
- base::BindOnce(&PlatformSensorFusionTest::AccelerometerCallback,
- base::Unretained(this));
- provider_->CreateSensor(SensorType::ACCELEROMETER, std::move(callback));
- EXPECT_TRUE(accelerometer_callback_called_);
+ base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
+ provider_->CreateSensor(SensorType::ACCELEROMETER, future.GetCallback());
+ accelerometer_ = static_cast<FakePlatformSensor*>(future.Get().get());
EXPECT_TRUE(accelerometer_);
EXPECT_EQ(SensorType::ACCELEROMETER, accelerometer_->GetType());
}
void CreateMagnetometer() {
- auto callback =
- base::BindOnce(&PlatformSensorFusionTest::MagnetometerCallback,
- base::Unretained(this));
- provider_->CreateSensor(SensorType::MAGNETOMETER, std::move(callback));
- EXPECT_TRUE(magnetometer_callback_called_);
+ base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
+ provider_->CreateSensor(SensorType::MAGNETOMETER, future.GetCallback());
+ magnetometer_ = static_cast<FakePlatformSensor*>(future.Get().get());
EXPECT_TRUE(magnetometer_);
EXPECT_EQ(SensorType::MAGNETOMETER, magnetometer_->GetType());
}
@@ -81,27 +65,19 @@ class PlatformSensorFusionTest : public testing::Test {
void CreateFusionSensor(
std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm) {
- auto callback =
- base::BindOnce(&PlatformSensorFusionTest::PlatformSensorFusionCallback,
- base::Unretained(this));
- SensorType type = fusion_algorithm->fused_type();
+ base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
+ const SensorType type = fusion_algorithm->fused_type();
PlatformSensorFusion::Create(provider_->GetSensorReadingBuffer(type),
provider_.get(), std::move(fusion_algorithm),
- std::move(callback));
- EXPECT_TRUE(platform_sensor_fusion_callback_called_);
+ future.GetCallback());
+ fusion_sensor_ = static_cast<PlatformSensorFusion*>(future.Get().get());
}
base::test::TaskEnvironment task_environment_;
std::unique_ptr<FakePlatformSensorProvider> provider_;
- bool accelerometer_callback_called_ = false;
scoped_refptr<FakePlatformSensor> accelerometer_;
- bool magnetometer_callback_called_ = false;
scoped_refptr<FakePlatformSensor> magnetometer_;
- bool platform_sensor_fusion_callback_called_ = false;
scoped_refptr<PlatformSensorFusion> fusion_sensor_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorFusionTest);
};
// The following code tests creating a fusion sensor that needs one source
diff --git a/chromium/services/device/generic_sensor/platform_sensor_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_linux.cc
index b629761b948..7f22b2af9ff 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_linux.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_linux.cc
@@ -35,11 +35,6 @@ mojom::ReportingMode PlatformSensorLinux::GetReportingMode() {
void PlatformSensorLinux::UpdatePlatformSensorReading(SensorReading reading) {
DCHECK(main_task_runner()->RunsTasksInCurrentSequence());
- if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE &&
- base::ranges::equal(reading.raw.values, old_values_.raw.values)) {
- return;
- }
- old_values_ = reading;
reading.raw.timestamp =
(base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
UpdateSharedBufferAndNotifyClients(reading);
diff --git a/chromium/services/device/generic_sensor/platform_sensor_linux.h b/chromium/services/device/generic_sensor/platform_sensor_linux.h
index 2702f9789fd..465f7fc1569 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_linux.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_linux.h
@@ -19,6 +19,9 @@ class PlatformSensorLinux : public PlatformSensor {
PlatformSensorProvider* provider,
const SensorInfoLinux* sensor_device);
+ PlatformSensorLinux(const PlatformSensorLinux&) = delete;
+ PlatformSensorLinux& operator=(const PlatformSensorLinux&) = delete;
+
mojom::ReportingMode GetReportingMode() override;
// Called by a sensor reader. Takes new readings.
@@ -43,14 +46,7 @@ class PlatformSensorLinux : public PlatformSensor {
// and stores them to a SensorReading structure.
std::unique_ptr<SensorReader> sensor_reader_;
- // Stores previously read values that are used to
- // determine whether the recent values are changed
- // and IPC can be notified that updates are available.
- SensorReading old_values_;
-
base::WeakPtrFactory<PlatformSensorLinux> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorLinux);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_base.h b/chromium/services/device/generic_sensor/platform_sensor_provider_base.h
index 749ddc1f5f8..b84a268eabd 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_base.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_base.h
@@ -5,9 +5,7 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_BASE_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_BASE_H_
-#include "base/macros.h"
-
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "services/device/generic_sensor/platform_sensor.h"
@@ -20,6 +18,10 @@ class PlatformSensorProviderBase {
using CreateSensorCallback =
base::OnceCallback<void(scoped_refptr<PlatformSensor>)>;
+ PlatformSensorProviderBase(const PlatformSensorProviderBase&) = delete;
+ PlatformSensorProviderBase& operator=(const PlatformSensorProviderBase&) =
+ delete;
+
// Creates new instance of PlatformSensor.
void CreateSensor(mojom::SensorType type, CreateSensorCallback callback);
@@ -71,8 +73,6 @@ class PlatformSensorProviderBase {
std::map<mojom::SensorType, CallbackQueue> requests_map_;
mojo::ScopedSharedBufferHandle shared_buffer_handle_;
mojo::ScopedSharedBufferMapping shared_buffer_mapping_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorProviderBase);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc
index 95d89dc610c..88153f326cb 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc
@@ -8,11 +8,12 @@
#include <vector>
#include "base/bind.h"
+#include "base/compiler_specific.h"
#include "base/containers/contains.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/post_task.h"
+#include "base/task/task_runner_util.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
#include "services/device/generic_sensor/linux/sensor_data_linux.h"
#include "services/device/generic_sensor/platform_sensor_linux.h"
#include "services/device/generic_sensor/platform_sensor_reader_linux.h"
@@ -27,9 +28,7 @@ constexpr base::TaskTraits kBlockingTaskRunnerTraits = {
} // namespace
PlatformSensorProviderLinux::PlatformSensorProviderLinux()
- : sensor_nodes_enumerated_(false),
- sensor_nodes_enumeration_started_(false),
- blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+ : blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
kBlockingTaskRunnerTraits)),
sensor_device_manager_(nullptr,
base::OnTaskRunnerDeleter(blocking_task_runner_)) {
@@ -45,32 +44,39 @@ void PlatformSensorProviderLinux::CreateSensorInternal(
CreateSensorCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (!sensor_nodes_enumerated_) {
- if (!sensor_nodes_enumeration_started_) {
+ switch (enumeration_status_) {
+ case SensorEnumerationState::kNotEnumerated: {
// Unretained() is safe because the deletion of |sensor_device_manager_|
// is scheduled on |blocking_task_runner_| when
// PlatformSensorProviderLinux is deleted.
- sensor_nodes_enumeration_started_ = blocking_task_runner_->PostTask(
+ const bool will_run = blocking_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&SensorDeviceManager::Start,
base::Unretained(sensor_device_manager_.get())));
- }
- return;
- }
+ if (will_run)
+ enumeration_status_ = SensorEnumerationState::kEnumerationStarted;
- if (IsFusionSensorType(type)) {
- CreateFusionSensor(type, reading_buffer, std::move(callback));
- return;
- }
-
- SensorInfoLinux* sensor_device = GetSensorDevice(type);
- if (!sensor_device) {
- std::move(callback).Run(nullptr);
- return;
+ FALLTHROUGH;
+ }
+ case SensorEnumerationState::kEnumerationStarted:
+ return;
+ case SensorEnumerationState::kEnumerationFinished:
+ if (IsFusionSensorType(type)) {
+ CreateFusionSensor(type, reading_buffer, std::move(callback));
+ return;
+ }
+
+ SensorInfoLinux* sensor_device = GetSensorDevice(type);
+ if (!sensor_device) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ std::move(callback).Run(base::MakeRefCounted<PlatformSensorLinux>(
+ type, reading_buffer, this, sensor_device));
+
+ break;
}
-
- std::move(callback).Run(base::MakeRefCounted<PlatformSensorLinux>(
- type, reading_buffer, this, sensor_device));
}
void PlatformSensorProviderLinux::FreeResources() {
@@ -138,8 +144,8 @@ void PlatformSensorProviderLinux::CreateSensorAndNotify(
void PlatformSensorProviderLinux::OnSensorNodesEnumerated() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(!sensor_nodes_enumerated_);
- sensor_nodes_enumerated_ = true;
+ DCHECK_EQ(enumeration_status_, SensorEnumerationState::kEnumerationStarted);
+ enumeration_status_ = SensorEnumerationState::kEnumerationFinished;
ProcessStoredRequests();
}
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h
index 24dfe0a853e..1d86d8fcbde 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h
@@ -8,7 +8,7 @@
#include "services/device/generic_sensor/platform_sensor_provider_linux_base.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "services/device/generic_sensor/linux/sensor_device_manager.h"
namespace device {
@@ -68,11 +68,16 @@ class PlatformSensorProviderLinux : public PlatformSensorProviderLinuxBase,
void OnDeviceRemoved(mojom::SensorType type,
const std::string& device_node) override;
- // Set to true when enumeration is ready.
- bool sensor_nodes_enumerated_;
+ enum class SensorEnumerationState : uint8_t {
+ // Original state.
+ kNotEnumerated,
- // Set to true when |sensor_device_manager_| has already started enumeration.
- bool sensor_nodes_enumeration_started_;
+ // |sensor_device_manager_| has started to enumerate sensors.
+ kEnumerationStarted,
+
+ // Sensor enumeration has finished.
+ kEnumerationFinished
+ } enumeration_status_ = SensorEnumerationState::kNotEnumerated;
// Stores all available sensor devices by type.
SensorDeviceMap sensor_devices_by_type_;
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_unittest_android.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_unittest_android.cc
index 5f33ea4641e..e742a9019b4 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_unittest_android.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_unittest_android.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_win.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_win.cc
index 9d1e663e560..38494a570e9 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_win.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_win.cc
@@ -11,9 +11,9 @@
#include "base/bind.h"
#include "base/task/post_task.h"
+#include "base/task/task_runner_util.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h"
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_winrt.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_winrt.cc
index 1cb16b95fd7..aab37b096f3 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_winrt.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_winrt.cc
@@ -7,8 +7,8 @@
#include <comdef.h>
#include "base/task/post_task.h"
+#include "base/task/task_runner_util.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
#include "services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h"
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
#include "services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.h"
diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_reader_linux.cc
index e0282adb635..f493cf11173 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_linux.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_linux.cc
@@ -10,10 +10,10 @@
#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/timer/timer.h"
#include "services/device/generic_sensor/linux/sensor_data_linux.h"
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 8d35f512989..823f7d21b0c 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_win.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_win.cc
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/numerics/math_constants.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -261,6 +262,9 @@ class EventListener
DCHECK(platform_sensor_reader_);
}
+ EventListener(const EventListener&) = delete;
+ EventListener& operator=(const EventListener&) = delete;
+
static Microsoft::WRL::ComPtr<ISensorEvents> CreateInstance(
PlatformSensorReaderWin32* platform_sensor_reader) {
Microsoft::WRL::ComPtr<EventListener> event_listener =
@@ -346,10 +350,8 @@ class EventListener
}
private:
- PlatformSensorReaderWin32* const platform_sensor_reader_;
+ const raw_ptr<PlatformSensorReaderWin32> platform_sensor_reader_;
SensorReading last_sensor_reading_;
-
- DISALLOW_COPY_AND_ASSIGN(EventListener);
};
// static
diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_win.h b/chromium/services/device/generic_sensor/platform_sensor_reader_win.h
index a21a4460fc7..8f608d2b604 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_win.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_win.h
@@ -8,6 +8,7 @@
#include <SensorsApi.h>
#include <wrl/client.h>
+#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "services/device/generic_sensor/platform_sensor_reader_win_base.h"
@@ -71,7 +72,7 @@ class PlatformSensorReaderWin32 final : public PlatformSensorReaderWinBase {
// PlatformSensorWin that can modify internal state of the object.
base::Lock lock_;
bool sensor_active_ GUARDED_BY(lock_);
- Client* client_ GUARDED_BY(lock_);
+ raw_ptr<Client> client_ GUARDED_BY(lock_);
Microsoft::WRL::ComPtr<ISensor> sensor_;
Microsoft::WRL::ComPtr<ISensorEvents> event_listener_;
base::WeakPtrFactory<PlatformSensorReaderWin32> weak_factory_{this};
diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h
index 661cbb7addd..cc0ae0a45ae 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h
@@ -13,6 +13,7 @@
#include <memory>
#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "services/device/generic_sensor/platform_sensor_reader_win_base.h"
@@ -96,7 +97,7 @@ class PlatformSensorReaderWinrtBase : public PlatformSensorReaderWinBase {
// threads by PlatformSensorWin.
base::Lock lock_;
// Null if there is no client to notify, non-null otherwise.
- Client* client_ GUARDED_BY(lock_);
+ raw_ptr<Client> client_ GUARDED_BY(lock_);
// Always report the first sample received after starting the sensor.
bool has_received_first_sample_ = false;
diff --git a/chromium/services/device/generic_sensor/platform_sensor_util.cc b/chromium/services/device/generic_sensor/platform_sensor_util.cc
index c204574afc4..97fd95f581b 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_util.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_util.cc
@@ -6,6 +6,8 @@
#include <cmath>
+#include "base/notreached.h"
+#include "base/ranges/algorithm.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
namespace device {
@@ -128,4 +130,29 @@ void RoundSensorReading(SensorReading* reading, mojom::SensorType sensor_type) {
}
}
+bool IsSignificantlyDifferent(const SensorReading& lhs,
+ const SensorReading& rhs,
+ mojom::SensorType sensor_type) {
+ switch (sensor_type) {
+ case mojom::SensorType::AMBIENT_LIGHT:
+ return std::fabs(lhs.als.value - rhs.als.value) >=
+ kAlsSignificanceThreshold / 2;
+
+ case mojom::SensorType::ACCELEROMETER:
+ case mojom::SensorType::GRAVITY:
+ case mojom::SensorType::LINEAR_ACCELERATION:
+ case mojom::SensorType::GYROSCOPE:
+ case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES:
+ case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES:
+ case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION:
+ case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION:
+ case mojom::SensorType::MAGNETOMETER:
+ case mojom::SensorType::PRESSURE:
+ case mojom::SensorType::PROXIMITY:
+ return !base::ranges::equal(lhs.raw.values, rhs.raw.values);
+ }
+ NOTREACHED();
+ return false;
+}
+
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_util.h b/chromium/services/device/generic_sensor/platform_sensor_util.h
index b7490186881..0e19b274b4f 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_util.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_util.h
@@ -33,6 +33,11 @@ constexpr double kOrientationEulerRoundingMultiple = 0.1;
// Units are radians. This value corresponds to 0.1 degrees.
constexpr double kOrientationQuaternionRoundingMultiple = 0.0017453292519943296;
+// Some sensor types also ignore value changes below a certain threshold to
+// avoid exposing whether a value is too close to the limit between one
+// rounded value and the next.
+constexpr int kAlsSignificanceThreshold = 50;
+
// Round |value| to be a multiple of |multiple|.
//
// NOTE: Exposed for testing. Please use other Rounding functions below.
@@ -61,6 +66,14 @@ void RoundOrientationQuaternionReading(SensorReadingQuat* reading);
// Round the sensor reading to guard user privacy.
void RoundSensorReading(SensorReading* reading, mojom::SensorType sensor_type);
+// Checks if new value is significantly different than old value.
+// When the reading we get does not differ significantly from our current
+// value, we discard this reading and do not emit any events. This is a privacy
+// measure to avoid giving readings that are too specific.
+bool IsSignificantlyDifferent(const SensorReading& lhs,
+ const SensorReading& rhs,
+ mojom::SensorType sensor_type);
+
} // namespace device
#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_UTIL_H_
diff --git a/chromium/services/device/generic_sensor/platform_sensor_util_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_util_unittest.cc
index f95cdf918fe..88cd4bd10a0 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_util_unittest.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_util_unittest.cc
@@ -6,10 +6,13 @@
#include <limits>
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
+using mojom::SensorType;
+
TEST(PlatformSensorUtil, RoundPositive) {
EXPECT_DOUBLE_EQ(1.2, RoundToMultiple(1.20, 0.1));
EXPECT_DOUBLE_EQ(1.2, RoundToMultiple(1.24, 0.1));
@@ -94,4 +97,113 @@ TEST(PlatformSensorUtil, RoundQuaternion) {
EXPECT_LT(std::abs(quat.w), epsilon);
}
+TEST(PlatformSensorUtil, IsSignificantlyDifferentAmbientLight) {
+ // Test for AMBIENT_LIGHT as it has different significance threshold compared
+ // to others.
+ const double kTestValue = 100.0; // Made up test value.
+
+ // Ambient light sensor has threshold points around initial_reading.
+ // IsSignificantlyDifferent() returns false when value is located between
+ // upper and lower threshold point and true when it is outside of threshold
+ // points. Below text shows these threshold points and different areas.
+ //
+ // Smaller value Large values
+ // [--------------X--------------]
+ // (1) (2) (3) (4) (5) (6) (7)
+ //
+ // Selected test values are:
+ // 1. just below lower threshold point in significantly different lower area
+ // 2. lower threshold point
+ // 3. just above lower threshold point in not significantly different area
+ // 4. center (new reading is same as initial reading)
+ // 5. just below upper threshold point in not significantly different area
+ // 6. upper threshold point
+ // 7. just above upper threshold point in significantly different upper area
+ const struct {
+ const bool expectation;
+ const double new_reading;
+ } kTestCases[] = {
+ {true, kTestValue - kAlsSignificanceThreshold / 2 - 1},
+ {true, kTestValue - kAlsSignificanceThreshold / 2},
+ {false, kTestValue - kAlsSignificanceThreshold / 2 + 1},
+ {false, kTestValue},
+ {false, kTestValue + kAlsSignificanceThreshold / 2 - 1},
+ {true, kTestValue + kAlsSignificanceThreshold / 2},
+ {true, kTestValue + kAlsSignificanceThreshold / 2 + 1},
+ };
+
+ SensorReading initial_reading;
+ initial_reading.als.value = kTestValue;
+
+ for (const auto& test_case : kTestCases) {
+ SensorReading new_reading;
+ new_reading.als.value = test_case.new_reading;
+ EXPECT_THAT(IsSignificantlyDifferent(initial_reading, new_reading,
+ SensorType::AMBIENT_LIGHT),
+ test_case.expectation);
+ }
+}
+
+TEST(PlatformSensorUtil, IsSignificantlyDifferentPressure) {
+ // Test for standard sensor with single value.
+ const double kTestValue = 100.0; // Made up test value.
+ const double kSmallDelta = 0.0005;
+ SensorReading last_reading;
+ SensorReading new_reading;
+
+ // No difference in values does not count as a significant change.
+ last_reading.pressure.value = kTestValue;
+ EXPECT_FALSE(IsSignificantlyDifferent(last_reading, last_reading,
+ SensorType::PRESSURE));
+
+ // Check that different values are reported as significantly different.
+ new_reading.pressure.value = last_reading.pressure.value + kSmallDelta;
+ EXPECT_TRUE(IsSignificantlyDifferent(last_reading, new_reading,
+ SensorType::PRESSURE));
+
+ // Check that different values are reported as significantly different.
+ new_reading.pressure.value = last_reading.pressure.value - kSmallDelta;
+ EXPECT_TRUE(IsSignificantlyDifferent(last_reading, new_reading,
+ SensorType::PRESSURE));
+}
+
+TEST(PlatformSensorUtil, IsSignificantlyDifferentMagnetometer) {
+ // Test for standard sensor with three values.
+ const double kTestValue = 100.0; // Made up test value.
+ const double kSmallDelta = 0.0005;
+ SensorReading last_reading;
+ SensorReading new_reading;
+
+ // No difference in values does not count as a significant change.
+ last_reading.magn.x = kTestValue;
+ last_reading.magn.y = kTestValue;
+ last_reading.magn.z = kTestValue;
+ EXPECT_FALSE(IsSignificantlyDifferent(last_reading, last_reading,
+ SensorType::MAGNETOMETER));
+
+ // Check that different values on one axis are reported as significantly
+ // different.
+ new_reading.magn.x = last_reading.magn.x;
+ new_reading.magn.y = last_reading.magn.y + kSmallDelta;
+ new_reading.magn.z = last_reading.magn.z;
+ EXPECT_TRUE(IsSignificantlyDifferent(last_reading, new_reading,
+ SensorType::MAGNETOMETER));
+
+ // Check that different values on all axis are reported as significantly
+ // different.
+ new_reading.magn.x = last_reading.magn.x + kSmallDelta;
+ new_reading.magn.y = last_reading.magn.y + kSmallDelta;
+ new_reading.magn.z = last_reading.magn.z + kSmallDelta;
+ EXPECT_TRUE(IsSignificantlyDifferent(last_reading, new_reading,
+ SensorType::MAGNETOMETER));
+
+ // Check that different values on all axis are reported as significantly
+ // different.
+ new_reading.magn.x = last_reading.magn.x - kSmallDelta;
+ new_reading.magn.y = last_reading.magn.y - kSmallDelta;
+ new_reading.magn.z = last_reading.magn.z - kSmallDelta;
+ EXPECT_TRUE(IsSignificantlyDifferent(last_reading, new_reading,
+ SensorType::MAGNETOMETER));
+}
+
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_win.cc b/chromium/services/device/generic_sensor/platform_sensor_win.cc
index 7a4559eb428..c3fd2d55509 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_win.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_win.cc
@@ -5,14 +5,11 @@
#include "services/device/generic_sensor/platform_sensor_win.h"
#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
namespace device {
-namespace {
-constexpr double kDefaultSensorReportingFrequency = 5.0;
-} // namespace
-
PlatformSensorWin::PlatformSensorWin(
mojom::SensorType type,
SensorReadingSharedBuffer* reading_buffer,
@@ -27,7 +24,7 @@ PlatformSensorWin::PlatformSensorWin(
}
PlatformSensorConfiguration PlatformSensorWin::GetDefaultConfiguration() {
- return PlatformSensorConfiguration(kDefaultSensorReportingFrequency);
+ return PlatformSensorConfiguration(GetSensorDefaultFrequency(GetType()));
}
mojom::ReportingMode PlatformSensorWin::GetReportingMode() {
@@ -40,7 +37,7 @@ double PlatformSensorWin::GetMaximumSupportedFrequency() {
base::TimeDelta minimal_reporting_interval_ms =
sensor_reader_->GetMinimalReportingInterval();
if (minimal_reporting_interval_ms.is_zero())
- return kDefaultSensorReportingFrequency;
+ return GetSensorDefaultFrequency(GetType());
return 1.0 / minimal_reporting_interval_ms.InSecondsF();
}
@@ -78,7 +75,7 @@ bool PlatformSensorWin::CheckSensorConfiguration(
PlatformSensorWin::~PlatformSensorWin() {
sensor_reader_->SetClient(nullptr);
- sensor_thread_runner_->DeleteSoon(FROM_HERE, sensor_reader_);
+ sensor_thread_runner_->DeleteSoon(FROM_HERE, sensor_reader_.get());
}
} // namespace device
diff --git a/chromium/services/device/generic_sensor/platform_sensor_win.h b/chromium/services/device/generic_sensor/platform_sensor_win.h
index d8f7deff398..17ff2517467 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_win.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_win.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_WIN_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_WIN_H_
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "services/device/generic_sensor/platform_sensor.h"
#include "services/device/generic_sensor/platform_sensor_reader_win.h"
@@ -32,6 +33,9 @@ class PlatformSensorWin final : public PlatformSensor,
scoped_refptr<base::SingleThreadTaskRunner> sensor_thread_runner,
std::unique_ptr<PlatformSensorReaderWinBase> sensor_reader);
+ PlatformSensorWin(const PlatformSensorWin&) = delete;
+ PlatformSensorWin& operator=(const PlatformSensorWin&) = delete;
+
PlatformSensorConfiguration GetDefaultConfiguration() override;
mojom::ReportingMode GetReportingMode() override;
double GetMaximumSupportedFrequency() override;
@@ -51,10 +55,8 @@ class PlatformSensorWin final : public PlatformSensor,
private:
scoped_refptr<base::SingleThreadTaskRunner> sensor_thread_runner_;
- PlatformSensorReaderWinBase* const sensor_reader_;
+ const raw_ptr<PlatformSensorReaderWinBase> sensor_reader_;
base::WeakPtrFactory<PlatformSensorWin> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PlatformSensorWin);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h
index 3658fe8f4d0..268a67e491d 100644
--- a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h
+++ b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_RELATIVE_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_ACCELEROMETER_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_RELATIVE_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_ACCELEROMETER_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
@@ -16,15 +15,19 @@ class RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer
: public PlatformSensorFusionAlgorithm {
public:
RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer();
+
+ RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer(
+ const RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer&) =
+ delete;
+ RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer& operator=(
+ const RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer&) =
+ delete;
+
~RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer() override;
protected:
bool GetFusedDataInternal(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h
index 04446400ae7..58ae0a61dfd 100644
--- a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h
+++ b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_RELATIVE_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_ACCELEROMETER_AND_GYROSCOPE_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_RELATIVE_ORIENTATION_EULER_ANGLES_FUSION_ALGORITHM_USING_ACCELEROMETER_AND_GYROSCOPE_H_
-#include "base/macros.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
namespace device {
@@ -15,6 +14,15 @@ class
final : public PlatformSensorFusionAlgorithm {
public:
RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope();
+
+ RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope(
+ const RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope&) =
+ delete;
+ RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope&
+ operator=(
+ const RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope&) =
+ delete;
+
~RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope()
override;
@@ -30,9 +38,6 @@ class
double beta_;
double gamma_;
const double kBias = 0.98;
-
- DISALLOW_COPY_AND_ASSIGN(
- RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope);
};
} // namespace device
diff --git a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope_unittest.cc b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope_unittest.cc
index deed0eb11e8..51155d77ca0 100644
--- a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope_unittest.cc
+++ b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope_unittest.cc
@@ -5,6 +5,7 @@
#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/numerics/math_constants.h"
#include "base/test/task_environment.h"
@@ -72,7 +73,8 @@ class
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope*
+ raw_ptr<
+ RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope>
fusion_algorithm_;
};
diff --git a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc
index 096ed5d19f0..d49491a6774 100644
--- a/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc
+++ b/chromium/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc
@@ -4,6 +4,7 @@
#include <cmath>
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/numerics/math_constants.h"
#include "base/test/task_environment.h"
@@ -57,7 +58,7 @@ class RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerTest
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakePlatformSensorFusion> fake_fusion_sensor_;
- RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer*
+ raw_ptr<RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer>
fusion_algorithm_;
};
diff --git a/chromium/services/device/generic_sensor/sensor_fusion_algorithm_using_accelerometer_unittest.cc b/chromium/services/device/generic_sensor/sensor_fusion_algorithm_using_accelerometer_unittest.cc
index 38f17f969b0..6fe5bf9817a 100644
--- a/chromium/services/device/generic_sensor/sensor_fusion_algorithm_using_accelerometer_unittest.cc
+++ b/chromium/services/device/generic_sensor/sensor_fusion_algorithm_using_accelerometer_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/raw_ptr.h"
#include "services/device/generic_sensor/gravity_fusion_algorithm_using_accelerometer.h"
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
@@ -107,8 +108,8 @@ class SensorFusionAlgorithmUsingAccelerometerTest : public testing::Test {
scoped_refptr<FakePlatformSensorFusion> fake_gravity_fusion_sensor_;
scoped_refptr<FakePlatformSensorFusion>
fake_linear_acceleration_fusion_sensor_;
- GravityFusionAlgorithmUsingAccelerometer* gravity_fusion_algorithm_;
- LinearAccelerationFusionAlgorithmUsingAccelerometer*
+ raw_ptr<GravityFusionAlgorithmUsingAccelerometer> gravity_fusion_algorithm_;
+ raw_ptr<LinearAccelerationFusionAlgorithmUsingAccelerometer>
linear_acceleration_fusion_algorithm_;
};
diff --git a/chromium/services/device/generic_sensor/sensor_impl.h b/chromium/services/device/generic_sensor/sensor_impl.h
index 5f68282b753..3e13cf03f9c 100644
--- a/chromium/services/device/generic_sensor/sensor_impl.h
+++ b/chromium/services/device/generic_sensor/sensor_impl.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_SENSOR_IMPL_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_SENSOR_IMPL_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/generic_sensor/platform_sensor.h"
diff --git a/chromium/services/device/generic_sensor/sensor_provider_impl.h b/chromium/services/device/generic_sensor/sensor_provider_impl.h
index ce179e9baf3..275c98f9c71 100644
--- a/chromium/services/device/generic_sensor/sensor_provider_impl.h
+++ b/chromium/services/device/generic_sensor/sensor_provider_impl.h
@@ -5,8 +5,7 @@
#ifndef SERVICES_DEVICE_GENERIC_SENSOR_SENSOR_PROVIDER_IMPL_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_SENSOR_PROVIDER_IMPL_H_
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
diff --git a/chromium/services/device/geolocation/OWNERS b/chromium/services/device/geolocation/OWNERS
index bf1f2fa8e48..f3b2efb3adb 100644
--- a/chromium/services/device/geolocation/OWNERS
+++ b/chromium/services/device/geolocation/OWNERS
@@ -1,4 +1 @@
-mattreynolds@chromium.org
-
-# Original (legacy) owners.
-mcasas@chromium.org
+file://content/browser/geolocation/OWNERS
diff --git a/chromium/services/device/geolocation/empty_wifi_data_provider.h b/chromium/services/device/geolocation/empty_wifi_data_provider.h
index 5ac432d3666..8d20ac64286 100644
--- a/chromium/services/device/geolocation/empty_wifi_data_provider.h
+++ b/chromium/services/device/geolocation/empty_wifi_data_provider.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
#define SERVICES_DEVICE_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
-#include "base/macros.h"
#include "services/device/geolocation/wifi_data_provider.h"
namespace device {
@@ -16,6 +15,9 @@ class EmptyWifiDataProvider : public WifiDataProvider {
public:
EmptyWifiDataProvider();
+ EmptyWifiDataProvider(const EmptyWifiDataProvider&) = delete;
+ EmptyWifiDataProvider& operator=(const EmptyWifiDataProvider&) = delete;
+
// WifiDataProvider implementation
void StartDataProvider() override {}
void StopDataProvider() override {}
@@ -25,8 +27,6 @@ class EmptyWifiDataProvider : public WifiDataProvider {
private:
~EmptyWifiDataProvider() override;
-
- DISALLOW_COPY_AND_ASSIGN(EmptyWifiDataProvider);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/fake_location_provider.h b/chromium/services/device/geolocation/fake_location_provider.h
index bb16c37d500..90e9f931228 100644
--- a/chromium/services/device/geolocation/fake_location_provider.h
+++ b/chromium/services/device/geolocation/fake_location_provider.h
@@ -6,9 +6,8 @@
#define SERVICES_DEVICE_GEOLOCATION_FAKE_LOCATION_PROVIDER_H_
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
#include "services/device/public/mojom/geoposition.mojom.h"
diff --git a/chromium/services/device/geolocation/fake_position_cache.h b/chromium/services/device/geolocation/fake_position_cache.h
index c2d6952d181..faf88fcae7d 100644
--- a/chromium/services/device/geolocation/fake_position_cache.h
+++ b/chromium/services/device/geolocation/fake_position_cache.h
@@ -8,7 +8,6 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
#include "services/device/geolocation/position_cache.h"
#include "services/device/public/mojom/geoposition.mojom.h"
diff --git a/chromium/services/device/geolocation/geolocation_context.h b/chromium/services/device/geolocation/geolocation_context.h
index ffba32c07cc..ecde841c50d 100644
--- a/chromium/services/device/geolocation/geolocation_context.h
+++ b/chromium/services/device/geolocation/geolocation_context.h
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/geolocation.mojom.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
diff --git a/chromium/services/device/geolocation/geolocation_impl.h b/chromium/services/device/geolocation/geolocation_impl.h
index dda37eb23f8..9f4f5699781 100644
--- a/chromium/services/device/geolocation/geolocation_impl.h
+++ b/chromium/services/device/geolocation/geolocation_impl.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_DEVICE_GEOLOCATION_GEOLOCATION_IMPL_H_
#define SERVICES_DEVICE_GEOLOCATION_GEOLOCATION_IMPL_H_
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/device/geolocation/geolocation_provider_impl.h"
#include "services/device/public/mojom/geolocation.mojom.h"
@@ -52,7 +52,7 @@ class GeolocationImpl : public mojom::Geolocation {
mojo::Receiver<mojom::Geolocation> receiver_;
// Owns this object.
- GeolocationContext* context_;
+ raw_ptr<GeolocationContext> context_;
// Token that unsubscribes from GeolocationProvider updates when destroyed.
base::CallbackListSubscription geolocation_subscription_;
diff --git a/chromium/services/device/geolocation/geolocation_provider_impl.cc b/chromium/services/device/geolocation/geolocation_provider_impl.cc
index 800da1acb78..dc0d12f68a0 100644
--- a/chromium/services/device/geolocation/geolocation_provider_impl.cc
+++ b/chromium/services/device/geolocation/geolocation_provider_impl.cc
@@ -15,7 +15,7 @@
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
#include "base/notreached.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "net/base/network_change_notifier.h"
diff --git a/chromium/services/device/geolocation/geolocation_provider_impl.h b/chromium/services/device/geolocation/geolocation_provider_impl.h
index 26a397ba3af..27d618f5eb1 100644
--- a/chromium/services/device/geolocation/geolocation_provider_impl.h
+++ b/chromium/services/device/geolocation/geolocation_provider_impl.h
@@ -12,7 +12,6 @@
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -62,6 +61,9 @@ class GeolocationProviderImpl : public GeolocationProvider,
// instantiated on the same thread. Ownership is NOT returned.
static GeolocationProviderImpl* GetInstance();
+ GeolocationProviderImpl(const GeolocationProviderImpl&) = delete;
+ GeolocationProviderImpl& operator=(const GeolocationProviderImpl&) = delete;
+
// Optional: Provide global configuration to Geolocation. Should be called
// before using Init() on the singleton GetInstance().
// |url_loader_factory| : a factory to use for network geolocation requests.
@@ -145,8 +147,6 @@ class GeolocationProviderImpl : public GeolocationProvider,
std::unique_ptr<LocationProvider> arbitrator_;
mojo::Receiver<mojom::GeolocationControl> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(GeolocationProviderImpl);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc b/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc
index ccdee01402a..91c33c11f02 100644
--- a/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc
+++ b/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc
@@ -11,11 +11,11 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -61,6 +61,9 @@ class GeopositionEqMatcher
explicit GeopositionEqMatcher(const mojom::Geoposition& expected)
: expected_(expected) {}
+ GeopositionEqMatcher(const GeopositionEqMatcher&) = delete;
+ GeopositionEqMatcher& operator=(const GeopositionEqMatcher&) = delete;
+
bool MatchAndExplain(const mojom::Geoposition& actual,
MatchResultListener* listener) const override {
return actual.latitude == expected_.latitude &&
@@ -85,8 +88,6 @@ class GeopositionEqMatcher
private:
mojom::Geoposition expected_;
-
- DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
};
Matcher<const mojom::Geoposition&> GeopositionEq(
@@ -105,9 +106,12 @@ class GeolocationProviderTest : public testing::Test {
: task_environment_(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI),
arbitrator_(new FakeLocationProvider) {
- provider()->SetArbitratorForTesting(base::WrapUnique(arbitrator_));
+ provider()->SetArbitratorForTesting(base::WrapUnique(arbitrator_.get()));
}
+ GeolocationProviderTest(const GeolocationProviderTest&) = delete;
+ GeolocationProviderTest& operator=(const GeolocationProviderTest&) = delete;
+
~GeolocationProviderTest() override = default;
GeolocationProviderImpl* provider() {
@@ -134,12 +138,10 @@ class GeolocationProviderTest : public testing::Test {
base::ThreadChecker thread_checker_;
// Owned by the GeolocationProviderImpl class.
- FakeLocationProvider* arbitrator_;
+ raw_ptr<FakeLocationProvider> arbitrator_;
// True if |arbitrator_| is started.
bool is_started_;
-
- DISALLOW_COPY_AND_ASSIGN(GeolocationProviderTest);
};
bool GeolocationProviderTest::ProvidersStarted() {
diff --git a/chromium/services/device/geolocation/location_arbitrator.h b/chromium/services/device/geolocation/location_arbitrator.h
index 85e3dc54d1b..0467f2d0348 100644
--- a/chromium/services/device/geolocation/location_arbitrator.h
+++ b/chromium/services/device/geolocation/location_arbitrator.h
@@ -12,6 +12,7 @@
#include "base/callback_forward.h"
#include "base/cancelable_callback.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "services/device/geolocation/geolocation_provider_impl.h"
@@ -102,7 +103,7 @@ class LocationArbitrator : public LocationProvider {
bool from_same_provider) const;
const CustomLocationProviderCallback custom_location_provider_getter_;
- GeolocationManager* const geolocation_manager_;
+ const raw_ptr<GeolocationManager> geolocation_manager_;
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
const std::string api_key_;
@@ -112,7 +113,7 @@ class LocationArbitrator : public LocationProvider {
std::vector<std::unique_ptr<LocationProvider>> providers_;
bool enable_high_accuracy_;
// The provider which supplied the current |position_|
- const LocationProvider* position_provider_;
+ raw_ptr<const LocationProvider> position_provider_;
bool is_permission_granted_;
// The current best estimate of our position.
mojom::Geoposition position_;
diff --git a/chromium/services/device/geolocation/location_arbitrator_unittest.cc b/chromium/services/device/geolocation/location_arbitrator_unittest.cc
index 5a1b8df3fd3..90dfc8ab2cb 100644
--- a/chromium/services/device/geolocation/location_arbitrator_unittest.cc
+++ b/chromium/services/device/geolocation/location_arbitrator_unittest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/test/task_environment.h"
#include "services/device/geolocation/fake_location_provider.h"
#include "services/device/geolocation/fake_position_cache.h"
@@ -104,7 +105,7 @@ class TestingLocationArbitrator : public LocationArbitrator {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const std::string& api_key) override {
network_location_provider_ = new FakeLocationProvider;
- return base::WrapUnique(network_location_provider_);
+ return base::WrapUnique(network_location_provider_.get());
}
std::unique_ptr<LocationProvider> NewSystemLocationProvider() override {
@@ -113,11 +114,11 @@ class TestingLocationArbitrator : public LocationArbitrator {
}
system_location_provider_ = new FakeLocationProvider;
- return base::WrapUnique(system_location_provider_);
+ return base::WrapUnique(system_location_provider_.get());
}
- FakeLocationProvider* network_location_provider_ = nullptr;
- FakeLocationProvider* system_location_provider_ = nullptr;
+ raw_ptr<FakeLocationProvider> network_location_provider_ = nullptr;
+ raw_ptr<FakeLocationProvider> system_location_provider_ = nullptr;
bool should_use_system_location_provider_;
};
diff --git a/chromium/services/device/geolocation/network_location_provider.cc b/chromium/services/device/geolocation/network_location_provider.cc
index 4e381ce1816..110959bebf7 100644
--- a/chromium/services/device/geolocation/network_location_provider.cc
+++ b/chromium/services/device/geolocation/network_location_provider.cc
@@ -10,9 +10,9 @@
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_runner.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/task/task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/chromium/services/device/geolocation/network_location_provider.h b/chromium/services/device/geolocation/network_location_provider.h
index dda1dbf75f4..a6674a40931 100644
--- a/chromium/services/device/geolocation/network_location_provider.h
+++ b/chromium/services/device/geolocation/network_location_provider.h
@@ -12,7 +12,7 @@
#include <memory>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
@@ -69,7 +69,7 @@ class NetworkLocationProvider : public LocationProvider,
// The wifi data provider, acquired via global factories. Valid between
// StartProvider() and StopProvider(), and checked via IsStarted().
- WifiDataProviderManager* wifi_data_provider_manager_;
+ raw_ptr<WifiDataProviderManager> wifi_data_provider_manager_;
WifiDataProviderManager::WifiDataUpdateCallback wifi_data_update_callback_;
@@ -90,7 +90,7 @@ class NetworkLocationProvider : public LocationProvider,
// The timestamp for the latest wifi data update.
base::Time wifi_timestamp_;
- PositionCache* const position_cache_;
+ const raw_ptr<PositionCache> position_cache_;
LocationProvider::LocationProviderUpdateCallback
location_provider_update_callback_;
diff --git a/chromium/services/device/geolocation/network_location_provider_unittest.cc b/chromium/services/device/geolocation/network_location_provider_unittest.cc
index 9cb67fb166c..0d58ac142c1 100644
--- a/chromium/services/device/geolocation/network_location_provider_unittest.cc
+++ b/chromium/services/device/geolocation/network_location_provider_unittest.cc
@@ -14,7 +14,6 @@
#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -80,6 +79,9 @@ class MockWifiDataProvider : public WifiDataProvider {
MockWifiDataProvider() : start_calls_(0), stop_calls_(0), got_data_(true) {}
+ MockWifiDataProvider(const MockWifiDataProvider&) = delete;
+ MockWifiDataProvider& operator=(const MockWifiDataProvider&) = delete;
+
// WifiDataProvider implementation.
void StartDataProvider() override { ++start_calls_; }
@@ -117,8 +119,6 @@ class MockWifiDataProvider : public WifiDataProvider {
WifiData data_;
bool got_data_;
-
- DISALLOW_COPY_AND_ASSIGN(MockWifiDataProvider);
};
MockWifiDataProvider* MockWifiDataProvider::instance_ = nullptr;
@@ -227,7 +227,10 @@ class GeolocationNetworkProviderTest : public testing::Test {
pos.longitude = -(id + 1);
pos.altitude = 2 * id;
pos.accuracy = 3 * id;
- pos.timestamp = base::Time::Now();
+ // Ensure last_position.timestamp be earlier than any future calls to
+ // base::time::Now() as well as not old enough to be considered invalid
+ // (kLastPositionMaxAgeSeconds)
+ pos.timestamp = base::Time::Now() - base::Minutes(5);
return pos;
}
@@ -300,17 +303,21 @@ class GeolocationNetworkProviderTest : public testing::Test {
ASSERT_TRUE(
JsonGetList("wifiAccessPoints", *request_json, &wifi_aps_json));
for (size_t i = 0; i < expected_wifi_aps_json.GetList().size(); ++i) {
- const base::DictionaryValue* expected_json;
- ASSERT_TRUE(expected_wifi_aps_json.GetDictionary(i, &expected_json));
- const base::DictionaryValue* actual_json;
- ASSERT_TRUE(wifi_aps_json->GetDictionary(i, &actual_json));
+ const base::Value& expected_json_value =
+ expected_wifi_aps_json.GetList()[i];
+ ASSERT_TRUE(expected_json_value.is_dict());
+ const base::DictionaryValue& expected_json =
+ base::Value::AsDictionaryValue(expected_json_value);
+ const base::Value& actual_json_value = wifi_aps_json->GetList()[i];
+ ASSERT_TRUE(actual_json_value.is_dict());
+ const base::DictionaryValue& actual_json =
+ base::Value::AsDictionaryValue(actual_json_value);
+ ASSERT_TRUE(JsonFieldEquals("macAddress", expected_json, actual_json));
ASSERT_TRUE(
- JsonFieldEquals("macAddress", *expected_json, *actual_json));
+ JsonFieldEquals("signalStrength", expected_json, actual_json));
+ ASSERT_TRUE(JsonFieldEquals("channel", expected_json, actual_json));
ASSERT_TRUE(
- JsonFieldEquals("signalStrength", *expected_json, *actual_json));
- ASSERT_TRUE(JsonFieldEquals("channel", *expected_json, *actual_json));
- ASSERT_TRUE(JsonFieldEquals("signalToNoiseRatio", *expected_json,
- *actual_json));
+ JsonFieldEquals("signalToNoiseRatio", expected_json, actual_json));
}
} else {
ASSERT_FALSE(request_json->HasKey("wifiAccessPoints"));
diff --git a/chromium/services/device/geolocation/network_location_request.cc b/chromium/services/device/geolocation/network_location_request.cc
index dc1fcc838dc..8f5a06e2fbf 100644
--- a/chromium/services/device/geolocation/network_location_request.cc
+++ b/chromium/services/device/geolocation/network_location_request.cc
@@ -296,7 +296,7 @@ void FormatPositionError(const GURL& server_url,
mojom::Geoposition* position) {
position->error_code = mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
position->error_message = "Network location provider at '";
- position->error_message += server_url.GetOrigin().spec();
+ position->error_message += server_url.DeprecatedGetOriginAsURL().spec();
position->error_message += "' : ";
position->error_message += message;
position->error_message += ".";
diff --git a/chromium/services/device/geolocation/network_location_request.h b/chromium/services/device/geolocation/network_location_request.h
index e04a5330f2d..48479a28d61 100644
--- a/chromium/services/device/geolocation/network_location_request.h
+++ b/chromium/services/device/geolocation/network_location_request.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "services/device/geolocation/wifi_data_provider.h"
#include "services/device/public/mojom/geoposition.mojom.h"
diff --git a/chromium/services/device/geolocation/position_cache_impl.h b/chromium/services/device/geolocation/position_cache_impl.h
index 4f39a8a75df..8a6c1739514 100644
--- a/chromium/services/device/geolocation/position_cache_impl.h
+++ b/chromium/services/device/geolocation/position_cache_impl.h
@@ -10,7 +10,7 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/network_change_notifier.h"
@@ -87,7 +87,7 @@ class PositionCacheImpl
static Hash MakeKey(const WifiData& wifi_data);
void EvictEntry(const Hash& hash);
- const base::TickClock* clock_;
+ raw_ptr<const base::TickClock> clock_;
std::vector<CacheEntry> data_;
mojom::Geoposition last_used_position_;
};
diff --git a/chromium/services/device/geolocation/public_ip_address_geolocation_provider.h b/chromium/services/device/geolocation/public_ip_address_geolocation_provider.h
index e19868d3c1c..4df8bac1247 100644
--- a/chromium/services/device/geolocation/public_ip_address_geolocation_provider.h
+++ b/chromium/services/device/geolocation/public_ip_address_geolocation_provider.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/chromium/services/device/geolocation/public_ip_address_geolocator.h b/chromium/services/device/geolocation/public_ip_address_geolocator.h
index 03f86098a4e..616381fb6f0 100644
--- a/chromium/services/device/geolocation/public_ip_address_geolocator.h
+++ b/chromium/services/device/geolocation/public_ip_address_geolocator.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/device/geolocation/public_ip_address_location_notifier.h"
@@ -55,7 +55,7 @@ class PublicIpAddressGeolocator : public mojom::Geolocation {
base::Time last_updated_timestamp_;
// Notifier to ask for IP-geolocation updates.
- PublicIpAddressLocationNotifier* const notifier_;
+ const raw_ptr<PublicIpAddressLocationNotifier> notifier_;
// The most recent PartialNetworkTrafficAnnotationTag provided by a client.
std::unique_ptr<const net::PartialNetworkTrafficAnnotationTag>
diff --git a/chromium/services/device/geolocation/public_ip_address_location_notifier.h b/chromium/services/device/geolocation/public_ip_address_location_notifier.h
index 8047547974d..637b44e5942 100644
--- a/chromium/services/device/geolocation/public_ip_address_location_notifier.h
+++ b/chromium/services/device/geolocation/public_ip_address_location_notifier.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/cancelable_callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/device/geolocation/geolocation_provider.h"
@@ -102,7 +102,7 @@ class PublicIpAddressLocationNotifier
// Used to listen to network connection changes.
// Must outlive this object.
- network::NetworkConnectionTracker* network_connection_tracker_;
+ raw_ptr<network::NetworkConnectionTracker> network_connection_tracker_;
// Used to make calls to the Maps geolocate API.
// Empty unless a call is currently in progress.
diff --git a/chromium/services/device/geolocation/wifi_data_provider.h b/chromium/services/device/geolocation/wifi_data_provider.h
index 2a60f1bfdfe..2af90a6a2e2 100644
--- a/chromium/services/device/geolocation/wifi_data_provider.h
+++ b/chromium/services/device/geolocation/wifi_data_provider.h
@@ -8,9 +8,8 @@
#include <set>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "services/device/geolocation/wifi_data.h"
namespace device {
@@ -19,6 +18,9 @@ class WifiDataProvider : public base::RefCountedThreadSafe<WifiDataProvider> {
public:
WifiDataProvider();
+ WifiDataProvider(const WifiDataProvider&) = delete;
+ WifiDataProvider& operator=(const WifiDataProvider&) = delete;
+
// Tells the provider to start looking for data. Callbacks will start
// receiving notifications after this call.
virtual void StartDataProvider() = 0;
@@ -68,8 +70,6 @@ class WifiDataProvider : public base::RefCountedThreadSafe<WifiDataProvider> {
scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
CallbackSet callbacks_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProvider);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_data_provider_chromeos.h b/chromium/services/device/geolocation/wifi_data_provider_chromeos.h
index 76ba459441e..e8ece00f3d1 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_chromeos.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_chromeos.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "services/device/geolocation/wifi_data_provider.h"
#include "services/device/geolocation/wifi_polling_policy.h"
@@ -18,6 +17,9 @@ class WifiDataProviderChromeOs : public WifiDataProvider {
public:
WifiDataProviderChromeOs();
+ WifiDataProviderChromeOs(const WifiDataProviderChromeOs&) = delete;
+ WifiDataProviderChromeOs& operator=(const WifiDataProviderChromeOs&) = delete;
+
// WifiDataProvider
void StartDataProvider() override;
void StopDataProvider() override;
@@ -62,8 +64,6 @@ class WifiDataProviderChromeOs : public WifiDataProvider {
// Whether our first scan was delayed due to polling policy. (client thread)
bool first_scan_delayed_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderChromeOs);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_data_provider_common.cc b/chromium/services/device/geolocation/wifi_data_provider_common.cc
index fb1670dc6ce..0e4c39c736a 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_common.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_common.cc
@@ -6,9 +6,9 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/single_thread_task_runner.h"
namespace device {
diff --git a/chromium/services/device/geolocation/wifi_data_provider_common.h b/chromium/services/device/geolocation/wifi_data_provider_common.h
index a5a5c031774..f66e374dd5a 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_common.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_common.h
@@ -11,7 +11,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "services/device/geolocation/wifi_data_provider.h"
#include "services/device/geolocation/wifi_polling_policy.h"
@@ -39,6 +38,9 @@ class WifiDataProviderCommon : public WifiDataProvider {
WifiDataProviderCommon();
+ WifiDataProviderCommon(const WifiDataProviderCommon&) = delete;
+ WifiDataProviderCommon& operator=(const WifiDataProviderCommon&) = delete;
+
// WifiDataProvider implementation
void StartDataProvider() override;
void StopDataProvider() override;
@@ -74,8 +76,6 @@ class WifiDataProviderCommon : public WifiDataProvider {
// Holder for delayed tasks; takes care of cleanup.
base::WeakPtrFactory<WifiDataProviderCommon> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommon);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc b/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc
index 2505982a140..d721b48d1db 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc
@@ -7,10 +7,10 @@
#include <memory>
#include "base/callback_helpers.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "services/device/geolocation/wifi_data_provider_manager.h"
@@ -63,6 +63,11 @@ class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
public:
WifiDataProviderCommonWithMock() : wlan_api_(new MockWlanApi) {}
+ WifiDataProviderCommonWithMock(const WifiDataProviderCommonWithMock&) =
+ delete;
+ WifiDataProviderCommonWithMock& operator=(
+ const WifiDataProviderCommonWithMock&) = delete;
+
// WifiDataProviderCommon
std::unique_ptr<WlanApiInterface> CreateWlanApi() override {
return std::move(wlan_api_);
@@ -75,12 +80,10 @@ class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
}
std::unique_ptr<MockWlanApi> wlan_api_;
- MockPollingPolicy* polling_policy_ = nullptr;
+ raw_ptr<MockPollingPolicy> polling_policy_ = nullptr;
private:
~WifiDataProviderCommonWithMock() override = default;
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommonWithMock);
};
// Main test fixture
@@ -132,8 +135,8 @@ class GeolocationWifiDataProviderCommonTest : public testing::Test {
WifiDataProviderManager::WifiDataUpdateCallback wifi_data_callback_;
scoped_refptr<WifiDataProviderCommonWithMock> provider_;
- MockWlanApi* wlan_api_ = nullptr;
- MockPollingPolicy* polling_policy_ = nullptr;
+ raw_ptr<MockWlanApi> wlan_api_ = nullptr;
+ raw_ptr<MockPollingPolicy> polling_policy_ = nullptr;
};
TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
diff --git a/chromium/services/device/geolocation/wifi_data_provider_linux.cc b/chromium/services/device/geolocation/wifi_data_provider_linux.cc
index d56c0e21069..ecc00cc799d 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_linux.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_linux.cc
@@ -17,7 +17,6 @@
#include <vector>
#include "base/logging.h"
-#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "dbus/bus.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_linux.h b/chromium/services/device/geolocation/wifi_data_provider_linux.h
index abbbbdb3397..0b19c540f75 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_linux.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_linux.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "services/device/geolocation/wifi_data_provider_common.h"
namespace dbus {
@@ -20,6 +19,9 @@ class WifiDataProviderLinux : public WifiDataProviderCommon {
public:
WifiDataProviderLinux();
+ WifiDataProviderLinux(const WifiDataProviderLinux&) = delete;
+ WifiDataProviderLinux& operator=(const WifiDataProviderLinux&) = delete;
+
private:
friend class GeolocationWifiDataProviderLinuxTest;
@@ -31,8 +33,6 @@ class WifiDataProviderLinux : public WifiDataProviderCommon {
std::unique_ptr<WlanApiInterface> CreateWlanApiForTesting(
scoped_refptr<dbus::Bus> bus);
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderLinux);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_data_provider_mac.h b/chromium/services/device/geolocation/wifi_data_provider_mac.h
index 62d54965cf4..d2055ae13aa 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_mac.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_mac.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_MAC_H_
#define SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_MAC_H_
-#include "base/macros.h"
#include "services/device/geolocation/wifi_data_provider_common.h"
namespace device {
@@ -17,14 +16,15 @@ class WifiDataProviderMac : public WifiDataProviderCommon {
public:
WifiDataProviderMac();
+ WifiDataProviderMac(const WifiDataProviderMac&) = delete;
+ WifiDataProviderMac& operator=(const WifiDataProviderMac&) = delete;
+
private:
~WifiDataProviderMac() override;
// WifiDataProviderCommon implementation
std::unique_ptr<WlanApiInterface> CreateWlanApi() override;
std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override;
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderMac);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_data_provider_mac.mm b/chromium/services/device/geolocation/wifi_data_provider_mac.mm
index 5764adf247c..028c805acea 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_mac.mm
+++ b/chromium/services/device/geolocation/wifi_data_provider_mac.mm
@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/sys_string_conversions.h"
#include "services/device/geolocation/wifi_data_provider_common.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_manager.h b/chromium/services/device/geolocation/wifi_data_provider_manager.h
index 87c4d5ffb7f..5dd7cf166d2 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_manager.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_manager.h
@@ -17,7 +17,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "services/device/geolocation/wifi_data.h"
@@ -50,6 +49,9 @@ class WifiDataProviderManager {
// Instantiates the singleton if necessary, and always returns it.
static WifiDataProviderManager* Register(WifiDataUpdateCallback* callback);
+ WifiDataProviderManager(const WifiDataProviderManager&) = delete;
+ WifiDataProviderManager& operator=(const WifiDataProviderManager&) = delete;
+
// Removes a callback. If this is the last callback, deletes the singleton
// instance. Return value indicates success.
static bool Unregister(WifiDataUpdateCallback* callback);
@@ -89,8 +91,6 @@ class WifiDataProviderManager {
// The internal implementation.
scoped_refptr<WifiDataProvider> impl_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderManager);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_data_provider_win.h b/chromium/services/device/geolocation/wifi_data_provider_win.h
index 8154147e83d..289220079bc 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_win.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_win.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_WIN_H_
#define SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_WIN_H_
-#include "base/macros.h"
#include "services/device/geolocation/wifi_data_provider_common.h"
namespace device {
@@ -14,14 +13,15 @@ class WifiDataProviderWin : public WifiDataProviderCommon {
public:
WifiDataProviderWin();
+ WifiDataProviderWin(const WifiDataProviderWin&) = delete;
+ WifiDataProviderWin& operator=(const WifiDataProviderWin&) = delete;
+
private:
~WifiDataProviderWin() override;
// WifiDataProviderCommon implementation
std::unique_ptr<WlanApiInterface> CreateWlanApi() override;
std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override;
-
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderWin);
};
} // namespace device
diff --git a/chromium/services/device/geolocation/wifi_polling_policy.h b/chromium/services/device/geolocation/wifi_polling_policy.h
index 427f4a62bd8..4e0534881ec 100644
--- a/chromium/services/device/geolocation/wifi_polling_policy.h
+++ b/chromium/services/device/geolocation/wifi_polling_policy.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/time/time.h"
namespace device {
diff --git a/chromium/services/device/geolocation/wifi_polling_policy_unittest.cc b/chromium/services/device/geolocation/wifi_polling_policy_unittest.cc
index e26bee4940a..b33f88456f3 100644
--- a/chromium/services/device/geolocation/wifi_polling_policy_unittest.cc
+++ b/chromium/services/device/geolocation/wifi_polling_policy_unittest.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/memory/raw_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
@@ -36,7 +37,7 @@ class GeolocationWifiPollingPolicyTest : public testing::Test {
}
protected:
- WifiPollingPolicy* polling_policy_ = nullptr;
+ raw_ptr<WifiPollingPolicy> polling_policy_ = nullptr;
};
TEST_F(GeolocationWifiPollingPolicyTest, CreateDestroy) {
diff --git a/chromium/services/device/geolocation/win/fake_geocoordinate_winrt.h b/chromium/services/device/geolocation/win/fake_geocoordinate_winrt.h
index 2bf04deeefa..3c71ba3c2d7 100644
--- a/chromium/services/device/geolocation/win/fake_geocoordinate_winrt.h
+++ b/chromium/services/device/geolocation/win/fake_geocoordinate_winrt.h
@@ -10,7 +10,6 @@
#include <wrl/client.h>
#include <wrl/implements.h>
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace device {
diff --git a/chromium/services/device/geolocation/win/fake_geoposition_winrt.h b/chromium/services/device/geolocation/win/fake_geoposition_winrt.h
index 6c89fdaa14b..528400fe072 100644
--- a/chromium/services/device/geolocation/win/fake_geoposition_winrt.h
+++ b/chromium/services/device/geolocation/win/fake_geoposition_winrt.h
@@ -11,8 +11,6 @@
#include <wrl/implements.h>
#include <memory>
-#include "base/macros.h"
-
namespace device {
struct FakeGeocoordinateData;
diff --git a/chromium/services/device/geolocation/win/fake_position_changed_event_args_winrt.h b/chromium/services/device/geolocation/win/fake_position_changed_event_args_winrt.h
index 61692ca96c4..213c3603c64 100644
--- a/chromium/services/device/geolocation/win/fake_position_changed_event_args_winrt.h
+++ b/chromium/services/device/geolocation/win/fake_position_changed_event_args_winrt.h
@@ -11,8 +11,6 @@
#include <wrl/implements.h>
#include <memory>
-#include "base/macros.h"
-
namespace device {
struct FakeGeocoordinateData;
diff --git a/chromium/services/device/geolocation/win/fake_status_changed_event_args_winrt.h b/chromium/services/device/geolocation/win/fake_status_changed_event_args_winrt.h
index e736e3a8116..7148d026ab3 100644
--- a/chromium/services/device/geolocation/win/fake_status_changed_event_args_winrt.h
+++ b/chromium/services/device/geolocation/win/fake_status_changed_event_args_winrt.h
@@ -10,8 +10,6 @@
#include <wrl/client.h>
#include <wrl/implements.h>
-#include "base/macros.h"
-
namespace device {
class FakeStatusChangedEventArgs
diff --git a/chromium/services/device/hid/hid_connection.h b/chromium/services/device/hid/hid_connection.h
index a83904e3c02..0f58eebbfc6 100644
--- a/chromium/services/device/hid/hid_connection.h
+++ b/chromium/services/device/hid/hid_connection.h
@@ -11,6 +11,7 @@
#include "base/callback_forward.h"
#include "base/containers/queue.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "services/device/hid/hid_device_info.h"
@@ -110,7 +111,7 @@ class HidConnection : public base::RefCountedThreadSafe<HidConnection> {
scoped_refptr<HidDeviceInfo> device_info_;
const bool allow_protected_reports_;
const bool allow_fido_reports_;
- Client* client_ = nullptr;
+ raw_ptr<Client> client_ = nullptr;
bool has_always_protected_collection_;
bool closed_;
diff --git a/chromium/services/device/hid/hid_connection_impl.h b/chromium/services/device/hid/hid_connection_impl.h
index a81ebff735f..4c7f3e54373 100644
--- a/chromium/services/device/hid/hid_connection_impl.h
+++ b/chromium/services/device/hid/hid_connection_impl.h
@@ -29,6 +29,9 @@ class HidConnectionImpl final : public mojom::HidConnection,
mojo::PendingRemote<mojom::HidConnectionClient> connection_client,
mojo::PendingRemote<mojom::HidConnectionWatcher> watcher);
+ HidConnectionImpl(const HidConnectionImpl&) = delete;
+ HidConnectionImpl& operator=(const HidConnectionImpl&) = delete;
+
// HidConnection::Client implementation:
void OnInputReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size) override;
@@ -73,8 +76,6 @@ class HidConnectionImpl final : public mojom::HidConnection,
mojo::Remote<mojom::HidConnectionWatcher> watcher_;
base::WeakPtrFactory<HidConnectionImpl> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(HidConnectionImpl);
};
} // namespace device
diff --git a/chromium/services/device/hid/hid_connection_impl_unittest.cc b/chromium/services/device/hid/hid_connection_impl_unittest.cc
index 08de33eb0b5..7b54227ef4f 100644
--- a/chromium/services/device/hid/hid_connection_impl_unittest.cc
+++ b/chromium/services/device/hid/hid_connection_impl_unittest.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -201,7 +202,8 @@ class HidConnectionImplTest : public DeviceServiceTestBase {
}
mojo::PendingRemote<mojom::HidConnection> hid_connection_;
- HidConnectionImpl* hid_connection_impl_; // Owned by |hid_connection_|.
+ raw_ptr<HidConnectionImpl>
+ hid_connection_impl_; // Owned by |hid_connection_|.
scoped_refptr<FakeHidConnection> fake_connection_;
std::unique_ptr<TestHidConnectionClient> connection_client_;
};
diff --git a/chromium/services/device/hid/hid_connection_linux.cc b/chromium/services/device/hid/hid_connection_linux.cc
index 18fa287d099..26aa289e45c 100644
--- a/chromium/services/device/hid/hid_connection_linux.cc
+++ b/chromium/services/device/hid/hid_connection_linux.cc
@@ -14,7 +14,6 @@
#include "base/bind.h"
#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/posix/eintr_wrapper.h"
#include "base/threading/scoped_blocking_call.h"
diff --git a/chromium/services/device/hid/hid_connection_linux.h b/chromium/services/device/hid/hid_connection_linux.h
index 9fd3ab93635..436df218c85 100644
--- a/chromium/services/device/hid/hid_connection_linux.h
+++ b/chromium/services/device/hid/hid_connection_linux.h
@@ -10,7 +10,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "services/device/hid/hid_connection.h"
namespace base {
diff --git a/chromium/services/device/hid/hid_connection_mac.cc b/chromium/services/device/hid/hid_connection_mac.cc
index e592528de28..f2e7d1b5302 100644
--- a/chromium/services/device/hid/hid_connection_mac.cc
+++ b/chromium/services/device/hid/hid_connection_mac.cc
@@ -9,8 +9,8 @@
#include "base/mac/foundation_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/numerics/safe_math.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/device_event_log/device_event_log.h"
diff --git a/chromium/services/device/hid/hid_manager_unittest.cc b/chromium/services/device/hid/hid_manager_unittest.cc
index 105dcbf3a04..6112f24c358 100644
--- a/chromium/services/device/hid/hid_manager_unittest.cc
+++ b/chromium/services/device/hid/hid_manager_unittest.cc
@@ -4,7 +4,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
@@ -134,7 +134,7 @@ class HidManagerTest : public DeviceServiceTestBase {
}
mojo::Remote<mojom::HidManager> hid_manager_;
- MockHidService* mock_hid_service_;
+ raw_ptr<MockHidService> mock_hid_service_;
};
// Test the GetDevices.
diff --git a/chromium/services/device/hid/hid_service_linux.cc b/chromium/services/device/hid/hid_service_linux.cc
index 1c6844819da..71d3a743045 100644
--- a/chromium/services/device/hid/hid_service_linux.cc
+++ b/chromium/services/device/hid/hid_service_linux.cc
@@ -20,12 +20,11 @@
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
diff --git a/chromium/services/device/hid/hid_service_linux.h b/chromium/services/device/hid/hid_service_linux.h
index 83aa2b3de58..1c8acd690e5 100644
--- a/chromium/services/device/hid/hid_service_linux.h
+++ b/chromium/services/device/hid/hid_service_linux.h
@@ -10,7 +10,7 @@
#include "base/compiler_specific.h"
#include "base/files/scoped_file.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "services/device/hid/hid_device_info.h"
diff --git a/chromium/services/device/hid/hid_service_mac.cc b/chromium/services/device/hid/hid_service_mac.cc
index 3e70fa7aba6..45bd75d1397 100644
--- a/chromium/services/device/hid/hid_service_mac.cc
+++ b/chromium/services/device/hid/hid_service_mac.cc
@@ -80,7 +80,8 @@ scoped_refptr<HidDeviceInfo> CreateDeviceInfo(
}
int32_t location_id = GetIntProperty(service, CFSTR(kIOHIDLocationIDKey));
- std::string physical_device_id = base::NumberToString(location_id);
+ std::string physical_device_id =
+ location_id == 0 ? "" : base::NumberToString(location_id);
return new HidDeviceInfo(
entry_id, physical_device_id,
diff --git a/chromium/services/device/hid/hid_service_win.cc b/chromium/services/device/hid/hid_service_win.cc
index fb6dd105c20..21140cd107f 100644
--- a/chromium/services/device/hid/hid_service_win.cc
+++ b/chromium/services/device/hid/hid_service_win.cc
@@ -24,11 +24,11 @@
#include "base/files/file.h"
#include "base/location.h"
#include "base/memory/free_deleter.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/win/scoped_devinfo.h"
diff --git a/chromium/services/device/hid/input_service_linux.cc b/chromium/services/device/hid/input_service_linux.cc
index 7f514352dda..5687904525e 100644
--- a/chromium/services/device/hid/input_service_linux.cc
+++ b/chromium/services/device/hid/input_service_linux.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/scoped_observation.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -85,6 +84,9 @@ std::string GetParentDeviceName(udev_device* device, const char* subsystem) {
class InputServiceLinuxImpl : public InputServiceLinux,
public DeviceMonitorLinux::Observer {
public:
+ InputServiceLinuxImpl(const InputServiceLinuxImpl&) = delete;
+ InputServiceLinuxImpl& operator=(const InputServiceLinuxImpl&) = delete;
+
// Implements DeviceMonitorLinux::Observer:
void OnDeviceAdded(udev_device* device) override;
void OnDeviceRemoved(udev_device* device) override;
@@ -97,8 +99,6 @@ class InputServiceLinuxImpl : public InputServiceLinux,
base::ScopedObservation<DeviceMonitorLinux, DeviceMonitorLinux::Observer>
observation_{this};
-
- DISALLOW_COPY_AND_ASSIGN(InputServiceLinuxImpl);
};
InputServiceLinuxImpl::InputServiceLinuxImpl() {
diff --git a/chromium/services/device/hid/input_service_linux.h b/chromium/services/device/hid/input_service_linux.h
index dfa14c3aa89..09d9bab82d9 100644
--- a/chromium/services/device/hid/input_service_linux.h
+++ b/chromium/services/device/hid/input_service_linux.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc b/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc
index 7c6f76a212d..0486165b8ff 100644
--- a/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc
+++ b/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "dbus/bus.h"
#include "dbus/message.h"
@@ -51,6 +50,11 @@ class MediaTransferProtocolDaemonClientImpl
dbus::ObjectPath(mtpd::kMtpdServicePath))),
listen_for_changes_called_(false) {}
+ MediaTransferProtocolDaemonClientImpl(
+ const MediaTransferProtocolDaemonClientImpl&) = delete;
+ MediaTransferProtocolDaemonClientImpl& operator=(
+ const MediaTransferProtocolDaemonClientImpl&) = delete;
+
// MediaTransferProtocolDaemonClient override.
void EnumerateStorages(EnumerateStoragesCallback callback,
ErrorCallback error_callback) override {
@@ -506,8 +510,6 @@ class MediaTransferProtocolDaemonClientImpl
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<MediaTransferProtocolDaemonClientImpl> weak_ptr_factory_{
this};
-
- DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl);
};
} // namespace
diff --git a/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h b/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h
index d85f52fd36e..90601001859 100644
--- a/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h
+++ b/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h
@@ -17,7 +17,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "services/device/public/mojom/mtp_file_entry.mojom.h"
diff --git a/chromium/services/device/media_transfer_protocol/mtp_device_manager.h b/chromium/services/device/media_transfer_protocol/mtp_device_manager.h
index 5476eaf5f32..bcdd5b45fe3 100644
--- a/chromium/services/device/media_transfer_protocol/mtp_device_manager.h
+++ b/chromium/services/device/media_transfer_protocol/mtp_device_manager.h
@@ -14,7 +14,7 @@
#include "base/containers/flat_set.h"
#include "base/containers/queue.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "build/chromeos_buildflags.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
diff --git a/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java b/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
index 2e0bcb9af0e..e506a6dd3d0 100644
--- a/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
+++ b/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
@@ -51,8 +51,8 @@ import org.chromium.device.mojom.NdefMessage;
import org.chromium.device.mojom.NdefRecord;
import org.chromium.device.mojom.NdefRecordTypeCategory;
import org.chromium.device.mojom.NdefWriteOptions;
-import org.chromium.device.mojom.Nfc.PushResponse;
-import org.chromium.device.mojom.Nfc.WatchResponse;
+import org.chromium.device.mojom.Nfc.Push_Response;
+import org.chromium.device.mojom.Nfc.Watch_Response;
import org.chromium.device.mojom.NfcClient;
import org.chromium.testing.local.LocalRobolectricTestRunner;
@@ -174,7 +174,7 @@ public class NFCTest {
doReturn(null).when(mNfcManager).getDefaultAdapter();
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- WatchResponse mockCallback = mock(WatchResponse.class);
+ Watch_Response mockCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockCallback);
verify(mockCallback).call(mErrorCaptor.capture());
assertEquals(NdefErrorType.NOT_SUPPORTED, mErrorCaptor.getValue().errorType);
@@ -190,7 +190,7 @@ public class NFCTest {
.when(mContext)
.checkPermission(anyString(), anyInt(), anyInt());
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
- WatchResponse mockCallback = mock(WatchResponse.class);
+ Watch_Response mockCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockCallback);
verify(mockCallback).call(mErrorCaptor.capture());
assertEquals(NdefErrorType.NOT_ALLOWED, mErrorCaptor.getValue().errorType);
@@ -204,7 +204,7 @@ public class NFCTest {
public void testNFCIsSupported() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- WatchResponse mockCallback = mock(WatchResponse.class);
+ Watch_Response mockCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockCallback);
verify(mockCallback).call(mErrorCaptor.capture());
assertNull(mErrorCaptor.getValue());
@@ -1080,7 +1080,7 @@ public class NFCTest {
public void testInvalidNdefMessage() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
nfc.push(new NdefMessage(), createNdefWriteOptions(), mockCallback);
nfc.processPendingOperationsForTesting(mNfcTagHandler);
verify(mockCallback).call(mErrorCaptor.capture());
@@ -1100,7 +1100,7 @@ public class NFCTest {
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
- WatchResponse mockCallback = mock(WatchResponse.class);
+ Watch_Response mockCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockCallback);
nfc.suspendNfcOperations();
verify(mNfcAdapter, times(1)).disableReaderMode(mActivity);
@@ -1132,7 +1132,7 @@ public class NFCTest {
nfc.suspendNfcOperations();
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
- WatchResponse mockCallback = mock(WatchResponse.class);
+ Watch_Response mockCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockCallback);
// Check that watch request was completed successfully even if NFC operations are suspended.
@@ -1166,7 +1166,7 @@ public class NFCTest {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
nfc.suspendNfcOperations();
mDelegate.invokeCallback();
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback);
// Check that push request was cancelled with OPERATION_CANCELLED.
@@ -1183,7 +1183,7 @@ public class NFCTest {
public void testSuspendNfcOperationsCancelPush() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockPushCallback = mock(PushResponse.class);
+ Push_Response mockPushCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockPushCallback);
nfc.suspendNfcOperations();
@@ -1201,7 +1201,7 @@ public class NFCTest {
public void testPush() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback);
nfc.processPendingOperationsForTesting(mNfcTagHandler);
verify(mockCallback).call(mErrorCaptor.capture());
@@ -1216,7 +1216,7 @@ public class NFCTest {
public void testCancelPush() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockPushCallback = mock(PushResponse.class);
+ Push_Response mockPushCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockPushCallback);
nfc.cancelPush();
@@ -1235,7 +1235,7 @@ public class NFCTest {
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
int watchId1 = mNextWatchId++;
- WatchResponse mockWatchCallback1 = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback1 = mock(Watch_Response.class);
nfc.watch(watchId1, mockWatchCallback1);
// Check that watch requests were completed successfully.
@@ -1243,7 +1243,7 @@ public class NFCTest {
assertNull(mErrorCaptor.getValue());
int watchId2 = mNextWatchId++;
- WatchResponse mockWatchCallback2 = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback2 = mock(Watch_Response.class);
nfc.watch(watchId2, mockWatchCallback2);
verify(mockWatchCallback2).call(mErrorCaptor.capture());
assertNull(mErrorCaptor.getValue());
@@ -1269,7 +1269,7 @@ public class NFCTest {
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
int watchId = mNextWatchId++;
- WatchResponse mockWatchCallback = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback = mock(Watch_Response.class);
nfc.watch(watchId, mockWatchCallback);
verify(mockWatchCallback).call(mErrorCaptor.capture());
assertNull(mErrorCaptor.getValue());
@@ -1293,7 +1293,7 @@ public class NFCTest {
public void testCancelWatch() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- WatchResponse mockWatchCallback = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockWatchCallback);
verify(mockWatchCallback).call(mErrorCaptor.capture());
@@ -1318,10 +1318,10 @@ public class NFCTest {
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
// Prepare at least one watcher, otherwise the error won't be notified.
- WatchResponse mockWatchCallback = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockWatchCallback);
// Start a push.
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback);
// Pass null tag handler to simulate that the tag is not NDEF compatible.
@@ -1353,10 +1353,10 @@ public class NFCTest {
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
// Prepare at least one watcher, otherwise the error won't be notified.
- WatchResponse mockWatchCallback = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockWatchCallback);
// Start a push.
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback);
// Mocks blocked 'NFC tag found' event.
@@ -1411,7 +1411,7 @@ public class NFCTest {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
- WatchResponse mockWatchCallback = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockWatchCallback);
// Force read operation to fail
@@ -1437,7 +1437,7 @@ public class NFCTest {
public void testTagDisconnectedDuringWrite() throws IOException, FormatException {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
// Force write operation to fail
doThrow(IllegalStateException.class)
@@ -1461,8 +1461,8 @@ public class NFCTest {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback1 = mock(PushResponse.class);
- PushResponse mockCallback2 = mock(PushResponse.class);
+ Push_Response mockCallback1 = mock(Push_Response.class);
+ Push_Response mockCallback2 = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback1);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback2);
@@ -1484,7 +1484,7 @@ public class NFCTest {
public void testPushInvocationWithCancel() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback);
@@ -1513,8 +1513,8 @@ public class NFCTest {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback1 = mock(PushResponse.class);
- PushResponse mockCallback2 = mock(PushResponse.class);
+ Push_Response mockCallback1 = mock(Push_Response.class);
+ Push_Response mockCallback2 = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback1);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockCallback2);
@@ -1548,10 +1548,10 @@ public class NFCTest {
public void testCancelledPushDontDisableReaderMode() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- WatchResponse mockWatchCallback = mock(WatchResponse.class);
+ Watch_Response mockWatchCallback = mock(Watch_Response.class);
nfc.watch(mNextWatchId, mockWatchCallback);
- PushResponse mockPushCallback = mock(PushResponse.class);
+ Push_Response mockPushCallback = mock(Push_Response.class);
nfc.push(createMojoNdefMessage(), createNdefWriteOptions(), mockPushCallback);
verify(mNfcAdapter, times(1))
@@ -1581,7 +1581,7 @@ public class NFCTest {
public void testPushWithEmptyRecord() {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
- PushResponse mockCallback = mock(PushResponse.class);
+ Push_Response mockCallback = mock(Push_Response.class);
// Create message with empty record.
NdefRecord emptyNdefRecord = new NdefRecord();
diff --git a/chromium/services/device/power_monitor/power_monitor_message_broadcaster.h b/chromium/services/device/power_monitor/power_monitor_message_broadcaster.h
index 75efec56da8..923fc0c2d63 100644
--- a/chromium/services/device/power_monitor/power_monitor_message_broadcaster.h
+++ b/chromium/services/device/power_monitor/power_monitor_message_broadcaster.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
#define SERVICES_DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
-#include "base/macros.h"
#include "base/power_monitor/power_observer.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc b/chromium/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
index a1005f222fc..813823856eb 100644
--- a/chromium/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
+++ b/chromium/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/power_monitor_test.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -45,6 +44,12 @@ class MockClient : public PowerMonitorBroadcastSource::Client {
};
class PowerMonitorMessageBroadcasterTest : public DeviceServiceTestBase {
+ public:
+ PowerMonitorMessageBroadcasterTest(
+ const PowerMonitorMessageBroadcasterTest&) = delete;
+ PowerMonitorMessageBroadcasterTest& operator=(
+ const PowerMonitorMessageBroadcasterTest&) = delete;
+
protected:
PowerMonitorMessageBroadcasterTest() = default;
~PowerMonitorMessageBroadcasterTest() override = default;
@@ -59,9 +64,6 @@ class PowerMonitorMessageBroadcasterTest : public DeviceServiceTestBase {
protected:
base::test::ScopedPowerMonitorTestSource power_monitor_source_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PowerMonitorMessageBroadcasterTest);
};
TEST_F(PowerMonitorMessageBroadcasterTest, PowerMessageBroadcast) {
diff --git a/chromium/services/device/public/cpp/BUILD.gn b/chromium/services/device/public/cpp/BUILD.gn
index 58126382548..1590d808866 100644
--- a/chromium/services/device/public/cpp/BUILD.gn
+++ b/chromium/services/device/public/cpp/BUILD.gn
@@ -55,6 +55,13 @@ source_set("test_support") {
"test/test_wake_lock_provider.h",
]
+ if (is_android) {
+ sources += [
+ "test/scoped_nfc_overrider.cc",
+ "test/scoped_nfc_overrider.h",
+ ]
+ }
+
public_deps = [
"//base",
"//services/device/public/cpp/generic_sensor",
diff --git a/chromium/services/device/public/cpp/device_feature_list.cc b/chromium/services/device/public/cpp/device_feature_list.cc
index 05d1ca3bdd0..09f7fd04dec 100644
--- a/chromium/services/device/public/cpp/device_feature_list.cc
+++ b/chromium/services/device/public/cpp/device_feature_list.cc
@@ -20,6 +20,7 @@ namespace {
// in other locations in the code base (e.g. content_features.h).
const base::Feature* const kFeaturesExposedToJava[] = {
&kGenericSensorExtraClasses,
+ &kWebBluetoothRequestLargerMtu,
};
// TODO(crbug.com/1060097): Removethis once a generalized FeatureList exists.
diff --git a/chromium/services/device/public/cpp/device_features.cc b/chromium/services/device/public/cpp/device_features.cc
index 17ce17db5ec..8357fad7521 100644
--- a/chromium/services/device/public/cpp/device_features.cc
+++ b/chromium/services/device/public/cpp/device_features.cc
@@ -18,5 +18,9 @@ const base::Feature kWinrtGeolocationImplementation{
// NetworkLocationProvider for macOS.
const base::Feature kMacCoreLocationBackend{"MacCoreLocationBackend",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether Web Bluetooth should request for a larger ATT MTU so that
+// more information can be exchanged per transmission.
+const base::Feature kWebBluetoothRequestLargerMtu{
+ "WebBluetoothRequestLargerMtu", base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace features
diff --git a/chromium/services/device/public/cpp/device_features.h b/chromium/services/device/public/cpp/device_features.h
index 04719255026..d9f20a94844 100644
--- a/chromium/services/device/public/cpp/device_features.h
+++ b/chromium/services/device/public/cpp/device_features.h
@@ -22,6 +22,7 @@ DEVICE_FEATURES_EXPORT extern const base::Feature
DEVICE_FEATURES_EXPORT extern const base::Feature
kMacCoreLocationImplementation;
DEVICE_FEATURES_EXPORT extern const base::Feature kMacCoreLocationBackend;
+DEVICE_FEATURES_EXPORT extern const base::Feature kWebBluetoothRequestLargerMtu;
} // namespace features
diff --git a/chromium/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h b/chromium/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h
index ed43fc18bca..f406362f226 100644
--- a/chromium/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h
+++ b/chromium/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "mojo/public/cpp/system/buffer.h"
namespace device {
diff --git a/chromium/services/device/public/cpp/hid/hid_collection.cc b/chromium/services/device/public/cpp/hid/hid_collection.cc
index 82262195bdd..c4107d0c069 100644
--- a/chromium/services/device/public/cpp/hid/hid_collection.cc
+++ b/chromium/services/device/public/cpp/hid/hid_collection.cc
@@ -78,7 +78,7 @@ std::vector<std::unique_ptr<HidCollection>> HidCollection::BuildCollections(
// Changes to input, output, and feature reports are propagated to all
// ancestor collections.
if (state.collection) {
- auto* collection = state.collection;
+ auto* collection = state.collection.get();
while (collection) {
collection->AddReportItem(current_item->tag(),
current_item->GetShortData(), state);
@@ -106,7 +106,7 @@ std::vector<std::unique_ptr<HidCollection>> HidCollection::BuildCollections(
// all ancestor collections.
if (state.collection) {
state.report_id = current_item->GetShortData();
- auto* collection = state.collection;
+ auto* collection = state.collection.get();
while (collection) {
collection->report_ids_.push_back(state.report_id);
collection = collection->parent_;
diff --git a/chromium/services/device/public/cpp/hid/hid_collection.h b/chromium/services/device/public/cpp/hid/hid_collection.h
index 32e92440832..9a17748fedd 100644
--- a/chromium/services/device/public/cpp/hid/hid_collection.h
+++ b/chromium/services/device/public/cpp/hid/hid_collection.h
@@ -12,6 +12,7 @@
#include <unordered_map>
#include <vector>
+#include "base/memory/raw_ptr.h"
#include "services/device/public/cpp/hid/hid_report_descriptor_item.h"
#include "services/device/public/cpp/hid/hid_report_item.h"
#include "services/device/public/mojom/hid.mojom.h"
@@ -83,7 +84,7 @@ class HidCollection {
HidItemStateTable& state);
// The parent collection, or nullptr if this is a top level collection.
- HidCollection* const parent_;
+ const raw_ptr<HidCollection> parent_;
// The children of this collection in the order they were encountered in the
// report descriptor.
diff --git a/chromium/services/device/public/cpp/hid/hid_item_state_table.h b/chromium/services/device/public/cpp/hid/hid_item_state_table.h
index 4cc79f4ac59..0b67720ce05 100644
--- a/chromium/services/device/public/cpp/hid/hid_item_state_table.h
+++ b/chromium/services/device/public/cpp/hid/hid_item_state_table.h
@@ -10,6 +10,7 @@
#include <vector>
+#include "base/memory/raw_ptr.h"
#include "services/device/public/cpp/hid/hid_report_descriptor_item.h"
#include "services/device/public/mojom/hid.mojom.h"
@@ -68,7 +69,7 @@ class HidItemStateTable {
size_t payload_size);
// The collection that will be modified when main items are encountered.
- HidCollection* collection = nullptr;
+ raw_ptr<HidCollection> collection = nullptr;
// The report ID is part of the global item state but is not affected by push
// or pop items.
diff --git a/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.h b/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.h
index 72b993f5410..78ca7b4927c 100644
--- a/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.h
+++ b/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.h
@@ -11,6 +11,7 @@
#include <memory>
#include "base/containers/span.h"
+#include "base/memory/raw_ptr.h"
namespace device {
@@ -167,9 +168,9 @@ class HidReportDescriptorItem {
private:
size_t GetHeaderSize() const;
- HidReportDescriptorItem* previous_;
- HidReportDescriptorItem* next_;
- HidReportDescriptorItem* parent_;
+ raw_ptr<HidReportDescriptorItem> previous_;
+ raw_ptr<HidReportDescriptorItem> next_;
+ raw_ptr<HidReportDescriptorItem> parent_;
Tag tag_;
uint32_t shortData_;
size_t payload_size_;
diff --git a/chromium/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc b/chromium/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
index 9d79f923613..b996bae4599 100644
--- a/chromium/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
+++ b/chromium/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
@@ -10,7 +10,6 @@
#include <unordered_map>
#include <utility>
-#include "base/macros.h"
#include "services/device/hid/test_report_descriptors.h"
#include "services/device/public/cpp/hid/hid_report_descriptor.h"
#include "services/device/public/cpp/hid/hid_usage_and_page.h"
diff --git a/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc b/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc
index 8fb1d0fa872..4077ba501f1 100644
--- a/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc
+++ b/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc
@@ -6,8 +6,7 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/macros.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace device {
diff --git a/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h b/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h
index c767be3fd1c..b0dab4ea65b 100644
--- a/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h
+++ b/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/power_monitor/power_monitor_source.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc b/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc
index 91787d229b7..0bc41a54481 100644
--- a/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc
+++ b/chromium/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc
@@ -4,7 +4,7 @@
#include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/power_monitor_test.h"
#include "base/test/task_environment.h"
@@ -14,6 +14,12 @@
namespace device {
class PowerMonitorBroadcastSourceTest : public testing::Test {
+ public:
+ PowerMonitorBroadcastSourceTest(const PowerMonitorBroadcastSourceTest&) =
+ delete;
+ PowerMonitorBroadcastSourceTest& operator=(
+ const PowerMonitorBroadcastSourceTest&) = delete;
+
protected:
PowerMonitorBroadcastSourceTest() {}
~PowerMonitorBroadcastSourceTest() override {}
@@ -38,9 +44,7 @@ class PowerMonitorBroadcastSourceTest : public testing::Test {
base::test::SingleThreadTaskEnvironment task_environment_;
private:
- PowerMonitorBroadcastSource* power_monitor_source_ptr_;
-
- DISALLOW_COPY_AND_ASSIGN(PowerMonitorBroadcastSourceTest);
+ raw_ptr<PowerMonitorBroadcastSource> power_monitor_source_ptr_;
};
TEST_F(PowerMonitorBroadcastSourceTest, PowerMessageReceiveBroadcast) {
diff --git a/chromium/services/device/public/cpp/usb/usb_ids.h b/chromium/services/device/public/cpp/usb/usb_ids.h
index 318abddc99c..5c89483f124 100644
--- a/chromium/services/device/public/cpp/usb/usb_ids.h
+++ b/chromium/services/device/public/cpp/usb/usb_ids.h
@@ -8,8 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/macros.h"
-
namespace device {
struct UsbProduct {
@@ -32,6 +30,9 @@ struct UsbVendor {
// mapping from a vendor/product ID pair to a product name.
class UsbIds {
public:
+ UsbIds(const UsbIds&) = delete;
+ UsbIds& operator=(const UsbIds&) = delete;
+
// Gets the name of the vendor who owns |vendor_id|. Returns NULL if the
// specified |vendor_id| does not exist.
static const char* GetVendorName(uint16_t vendor_id);
@@ -54,8 +55,6 @@ class UsbIds {
// more information on how they are generated.
static const size_t vendor_size_;
static const UsbVendor vendors_[];
-
- DISALLOW_COPY_AND_ASSIGN(UsbIds);
};
} // namespace device
diff --git a/chromium/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java b/chromium/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
index 18c616cf37b..a9cf1269fa5 100644
--- a/chromium/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
+++ b/chromium/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
@@ -18,6 +18,8 @@ import org.chromium.base.annotations.NativeMethods;
public class DeviceFeatureList {
public static final String GENERIC_SENSOR_EXTRA_CLASSES = "GenericSensorExtraClasses";
+ public static final String WEB_BLUETOOTH_REQUEST_LARGER_MTU = "WebBluetoothRequestLargerMtu";
+
private DeviceFeatureList() {}
/**
diff --git a/chromium/services/device/public/mojom/BUILD.gn b/chromium/services/device/public/mojom/BUILD.gn
index 01a767250ca..961f453c53b 100644
--- a/chromium/services/device/public/mojom/BUILD.gn
+++ b/chromium/services/device/public/mojom/BUILD.gn
@@ -75,6 +75,7 @@ mojom("mojom") {
visibility_blink = [
"//third_party/blink/renderer/platform:blink_platform_public_deps",
+ "//third_party/blink/renderer/platform/media:*",
"//third_party/blink/public/mojom:mojom_platform_blink",
]
}
@@ -181,7 +182,7 @@ mojom("usb") {
visibility_blink = [
":*",
- "//components/arc/mojom:mojom_blink",
+ "//ash/components/arc/mojom:mojom_blink",
"//third_party/blink/public/mojom/usb:usb_blink",
"//third_party/blink/renderer/modules/webusb",
"//chrome/browser/ui/webui/usb_internals:mojo_bindings_blink",
diff --git a/chromium/services/device/screen_orientation/OWNERS b/chromium/services/device/screen_orientation/OWNERS
deleted file mode 100644
index 39557cd3030..00000000000
--- a/chromium/services/device/screen_orientation/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-blundell@chromium.org
diff --git a/chromium/services/device/screen_orientation/screen_orientation_listener_android.h b/chromium/services/device/screen_orientation/screen_orientation_listener_android.h
index 21edcc12256..0db35789bed 100644
--- a/chromium/services/device/screen_orientation/screen_orientation_listener_android.h
+++ b/chromium/services/device/screen_orientation/screen_orientation_listener_android.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_SCREEN_ORIENTATION_SCREEN_ORIENTATION_LISTENER_ANDROID_H_
#define SERVICES_DEVICE_SCREEN_ORIENTATION_SCREEN_ORIENTATION_LISTENER_ANDROID_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/screen_orientation.mojom.h"
diff --git a/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc b/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc
index fd6100d42c3..bd69301e17d 100644
--- a/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc
+++ b/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc
@@ -14,55 +14,128 @@
namespace device {
-BluetoothSerialDeviceEnumerator::BluetoothSerialDeviceEnumerator() {
- DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBluetoothSerialPortProfileInSerialApi));
- device::BluetoothAdapterFactory::Get()->GetClassicAdapter(
- base::BindOnce(&BluetoothSerialDeviceEnumerator::OnGotClassicAdapter,
- base::Unretained(this)));
-}
+// Helper class to interact with the BluetoothAdapter which must be accessed
+// on a specific sequence.
+class BluetoothSerialDeviceEnumerator::AdapterHelper
+ : public BluetoothAdapter::Observer {
+ public:
+ AdapterHelper(base::WeakPtr<BluetoothSerialDeviceEnumerator> enumerator,
+ scoped_refptr<base::SequencedTaskRunner> enumerator_runner);
-BluetoothSerialDeviceEnumerator::~BluetoothSerialDeviceEnumerator() = default;
+ void OnGotClassicAdapter(scoped_refptr<device::BluetoothAdapter> adapter);
+
+ // BluetoothAdapter::Observer methods:
+ void DeviceAdded(BluetoothAdapter* adapter, BluetoothDevice* device) override;
+ void DeviceRemoved(BluetoothAdapter* adapter,
+ BluetoothDevice* device) override;
-void BluetoothSerialDeviceEnumerator::OnGotClassicAdapter(
+ private:
+ // The enumerator that owns this instance.
+ base::WeakPtr<BluetoothSerialDeviceEnumerator> enumerator_;
+ scoped_refptr<base::SequencedTaskRunner> enumerator_runner_;
+ SEQUENCE_CHECKER(sequence_checker_);
+ base::WeakPtrFactory<AdapterHelper> weak_ptr_factory_{this};
+};
+
+BluetoothSerialDeviceEnumerator::AdapterHelper::AdapterHelper(
+ base::WeakPtr<BluetoothSerialDeviceEnumerator> enumerator,
+ scoped_refptr<base::SequencedTaskRunner> enumerator_runner)
+ : enumerator_(std::move(enumerator)),
+ enumerator_runner_(std::move(enumerator_runner)) {
+ device::BluetoothAdapterFactory::Get()->GetClassicAdapter(base::BindOnce(
+ &BluetoothSerialDeviceEnumerator::AdapterHelper::OnGotClassicAdapter,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothSerialDeviceEnumerator::AdapterHelper::OnGotClassicAdapter(
scoped_refptr<device::BluetoothAdapter> adapter) {
+ SEQUENCE_CHECKER(sequence_checker_);
DCHECK(adapter);
- adapter_ = adapter;
- adapter_->AddObserver(this);
- BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
+ adapter->AddObserver(this);
+ std::vector<std::string> port_device_addresses;
+ 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->GetAddress());
- port->type = mojom::DeviceType::SPP_DEVICE;
- bluetooth_ports_.insert(
- std::make_pair(device->GetAddress(), port->token));
- AddPort(std::move(port));
+ port_device_addresses.push_back(device->GetAddress());
}
}
+
+ enumerator_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BluetoothSerialDeviceEnumerator::SetClassicAdapter,
+ enumerator_, std::move(adapter),
+ std::move(port_device_addresses)));
}
-void BluetoothSerialDeviceEnumerator::DeviceAdded(BluetoothAdapter* adapter,
- BluetoothDevice* device) {
+void BluetoothSerialDeviceEnumerator::AdapterHelper::DeviceAdded(
+ BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
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->GetAddress());
- port->type = mojom::DeviceType::SPP_DEVICE;
- bluetooth_ports_.insert(std::make_pair(device->GetAddress(), port->token));
- AddPort(std::move(port));
+ if (!base::Contains(device_uuids, GetSerialPortProfileUUID()))
+ return;
+
+ enumerator_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&BluetoothSerialDeviceEnumerator::PortAdded,
+ enumerator_, device->GetAddress()));
+}
+
+void BluetoothSerialDeviceEnumerator::AdapterHelper::DeviceRemoved(
+ BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ enumerator_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&BluetoothSerialDeviceEnumerator::PortRemoved,
+ enumerator_, device->GetAddress()));
+}
+
+BluetoothSerialDeviceEnumerator::BluetoothSerialDeviceEnumerator(
+ scoped_refptr<base::SingleThreadTaskRunner> adapter_runner) {
+ DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi));
+
+ helper_ = base::SequenceBound<AdapterHelper>(
+ std::move(adapter_runner), weak_ptr_factory_.GetWeakPtr(),
+ base::SequencedTaskRunnerHandle::Get());
+}
+
+BluetoothSerialDeviceEnumerator::~BluetoothSerialDeviceEnumerator() = default;
+
+void BluetoothSerialDeviceEnumerator::SetClassicAdapter(
+ scoped_refptr<device::BluetoothAdapter> adapter,
+ std::vector<std::string> port_device_addresses) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(adapter);
+ adapter_ = std::move(adapter);
+ DCHECK(device_ports_.empty());
+ for (const auto& device_address : port_device_addresses) {
+ PortAdded(device_address);
+ }
+ if (got_adapter_callback_) {
+ std::move(got_adapter_callback_).Run();
}
}
-void BluetoothSerialDeviceEnumerator::DeviceRemoved(BluetoothAdapter* adapter,
- BluetoothDevice* device) {
- auto it = bluetooth_ports_.find(device->GetAddress());
- DCHECK(it != bluetooth_ports_.end());
+void BluetoothSerialDeviceEnumerator::PortAdded(
+ const std::string& device_address) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!base::Contains(device_ports_, device_address));
+ auto port = mojom::SerialPortInfo::New();
+ port->token = base::UnguessableToken::Create();
+ port->path = base::FilePath::FromUTF8Unsafe(device_address);
+ port->type = mojom::DeviceType::SPP_DEVICE;
+ device_ports_.insert(std::make_pair(device_address, port->token));
+ AddPort(std::move(port));
+}
+
+void BluetoothSerialDeviceEnumerator::PortRemoved(
+ const std::string& device_address) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = device_ports_.find(device_address);
+ DCHECK(it != device_ports_.end());
base::UnguessableToken token = it->second;
- bluetooth_ports_.erase(it);
+ device_ports_.erase(it);
RemovePort(token);
}
@@ -73,11 +146,35 @@ scoped_refptr<BluetoothAdapter> BluetoothSerialDeviceEnumerator::GetAdapter() {
absl::optional<std::string>
BluetoothSerialDeviceEnumerator::GetAddressFromToken(
const base::UnguessableToken& token) {
- for (const auto& entry : bluetooth_ports_) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ for (const auto& entry : device_ports_) {
if (entry.second == token)
return entry.first;
}
return absl::nullopt;
}
+void BluetoothSerialDeviceEnumerator::OnGotAdapterForTesting(
+ base::OnceClosure closure) {
+ if (adapter_) {
+ std::move(closure).Run();
+ return;
+ }
+
+ DCHECK(!got_adapter_callback_);
+ got_adapter_callback_ = std::move(closure);
+}
+
+void BluetoothSerialDeviceEnumerator::DeviceAddedForTesting(
+ BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ // Pass the device to our helper, which will in turn pass it back to me.
+ helper_.AsyncCall(&AdapterHelper::DeviceAdded)
+ .WithArgs(base::Unretained(adapter), device);
+}
+
+void BluetoothSerialDeviceEnumerator::SynchronouslyResetHelperForTesting() {
+ helper_.SynchronouslyResetForTest(); // IN-TEST
+}
+
} // namespace device
diff --git a/chromium/services/device/serial/bluetooth_serial_device_enumerator.h b/chromium/services/device/serial/bluetooth_serial_device_enumerator.h
index 9b624df241a..2bc7ec3bfc7 100644
--- a/chromium/services/device/serial/bluetooth_serial_device_enumerator.h
+++ b/chromium/services/device/serial/bluetooth_serial_device_enumerator.h
@@ -6,28 +6,33 @@
#define SERVICES_DEVICE_SERIAL_BLUETOOTH_SERIAL_DEVICE_ENUMERATOR_H_
#include <map>
+#include <unordered_map>
+#include <vector>
#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/threading/sequence_bound.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 {
+class BluetoothSerialDeviceEnumerator : public SerialDeviceEnumerator {
public:
- BluetoothSerialDeviceEnumerator();
+ // `adapter_runner` is the task runner with which to access the Bluetooth
+ // adapter.
+ explicit BluetoothSerialDeviceEnumerator(
+ scoped_refptr<base::SingleThreadTaskRunner> adapter_runner);
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;
+ void PortAdded(const std::string& device_address);
+ void PortRemoved(const std::string& device_address);
scoped_refptr<BluetoothAdapter> GetAdapter();
@@ -36,13 +41,30 @@ class BluetoothSerialDeviceEnumerator : public BluetoothAdapter::Observer,
absl::optional<std::string> GetAddressFromToken(
const base::UnguessableToken& token);
- protected:
- scoped_refptr<BluetoothAdapter> adapter_;
+ void OnGotAdapterForTesting(base::OnceClosure closure);
+ void DeviceAddedForTesting(BluetoothAdapter* adapter,
+ BluetoothDevice* device);
+ void SynchronouslyResetHelperForTesting();
private:
- void OnGotClassicAdapter(scoped_refptr<device::BluetoothAdapter> adapter);
+ class AdapterHelper;
+
+ // Map BluetoothDevice address to port token.
+ using DevicePortsMap =
+ std::unordered_map<std::string, base::UnguessableToken>;
- std::unordered_map<std::string, base::UnguessableToken> bluetooth_ports_;
+ // Set the "classic" `adapter`. `port_device_addresses` is a collection of
+ // all known ports device addresses at the time the adapter is detected.
+ // Called once during initialization.
+ void SetClassicAdapter(scoped_refptr<device::BluetoothAdapter> adapter,
+ std::vector<std::string> port_device_addresses);
+
+ base::OnceClosure got_adapter_callback_;
+ scoped_refptr<BluetoothAdapter> adapter_;
+ DevicePortsMap device_ports_;
+ base::SequenceBound<AdapterHelper> helper_;
+ SEQUENCE_CHECKER(sequence_checker_);
+ base::WeakPtrFactory<BluetoothSerialDeviceEnumerator> weak_ptr_factory_{this};
};
} // namespace device
diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl.cc b/chromium/services/device/serial/bluetooth_serial_port_impl.cc
index 8c94fd0c52f..a633d08f08a 100644
--- a/chromium/services/device/serial/bluetooth_serial_port_impl.cc
+++ b/chromium/services/device/serial/bluetooth_serial_port_impl.cc
@@ -61,6 +61,7 @@ BluetoothSerialPortImpl::~BluetoothSerialPortImpl() {
}
void BluetoothSerialPortImpl::OpenSocket(OpenCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
BluetoothDevice* device = bluetooth_adapter_->GetDevice(address_);
if (!device) {
std::move(callback).Run(mojo::NullRemote());
@@ -89,6 +90,7 @@ void BluetoothSerialPortImpl::OpenSocket(OpenCallback callback) {
void BluetoothSerialPortImpl::OnSocketConnected(
OpenCallback callback,
scoped_refptr<BluetoothSocket> socket) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(socket);
bluetooth_socket_ = std::move(socket);
mojo::PendingRemote<mojom::SerialPort> port =
@@ -102,13 +104,14 @@ void BluetoothSerialPortImpl::OnSocketConnected(
void BluetoothSerialPortImpl::OnSocketConnectedError(
OpenCallback callback,
const std::string& message) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(callback).Run(mojo::NullRemote());
delete this;
}
void BluetoothSerialPortImpl::StartWriting(
mojo::ScopedDataPipeConsumerHandle consumer) {
- DCHECK(!write_pending_);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (in_stream_) {
receiver_.ReportBadMessage("Data pipe consumer still open.");
@@ -128,11 +131,13 @@ void BluetoothSerialPortImpl::StartWriting(
MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
base::BindRepeating(&BluetoothSerialPortImpl::WriteToSocket,
weak_ptr_factory_.GetWeakPtr()));
- in_stream_watcher_.ArmOrNotify();
+ if (!write_pending_)
+ in_stream_watcher_.ArmOrNotify();
}
void BluetoothSerialPortImpl::StartReading(
mojo::ScopedDataPipeProducerHandle producer) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (out_stream_) {
mojo::ReportBadMessage("Data pipe producer still open.");
return;
@@ -145,20 +150,24 @@ void BluetoothSerialPortImpl::StartReading(
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();
+ if (!read_pending_)
+ out_stream_watcher_.ArmOrNotify();
}
void BluetoothSerialPortImpl::ReadFromSocketAndWriteOut(
MojoResult result,
const mojo::HandleSignalsState& state) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (result) {
case MOJO_RESULT_OK:
+ DCHECK(!read_pending_);
ReadMore();
break;
case MOJO_RESULT_SHOULD_WAIT:
@@ -176,11 +185,22 @@ void BluetoothSerialPortImpl::ReadFromSocketAndWriteOut(
}
}
+void BluetoothSerialPortImpl::ResetPendingWriteBuffer() {
+ pending_write_buffer_ = base::span<char>();
+}
+
+void BluetoothSerialPortImpl::ResetReceiveBuffer() {
+ receive_buffer_size_ = 0;
+ receive_buffer_next_byte_pos_ = 0;
+ receive_buffer_.reset();
+}
+
void BluetoothSerialPortImpl::ReadMore() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(out_stream_.is_valid());
+ DCHECK(!read_pending_);
void* buffer = nullptr;
-
uint32_t buffer_num_bytes = 0;
// The |buffer| is owned by |out_stream_|.
MojoResult result = out_stream_->BeginWriteData(&buffer, &buffer_num_bytes,
@@ -211,92 +231,105 @@ void BluetoothSerialPortImpl::ReadMore() {
reinterpret_cast<char*>(buffer));
out_stream_->EndWriteData(bytes_to_copy);
if (bytes_to_copy == num_remaining_bytes) { // If copied the last byte.
- receive_buffer_size_ = 0;
- receive_buffer_next_byte_pos_ = 0;
- receive_buffer_.reset();
+ ResetReceiveBuffer();
} else {
receive_buffer_next_byte_pos_ += buffer_num_bytes;
}
out_stream_watcher_.ArmOrNotify();
return;
}
- if (read_pending_)
- return;
read_pending_ = true;
+ pending_write_buffer_ =
+ base::make_span(reinterpret_cast<char*>(buffer), buffer_num_bytes);
bluetooth_socket_->Receive(
buffer_num_bytes,
- base::BindOnce(
- &BluetoothSerialPortImpl::OnBluetoothSocketReceive,
- weak_ptr_factory_.GetWeakPtr(),
- base::make_span(reinterpret_cast<char*>(buffer), buffer_num_bytes)),
+ base::BindOnce(&BluetoothSerialPortImpl::OnBluetoothSocketReceive,
+ weak_ptr_factory_.GetWeakPtr()),
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) {
+ scoped_refptr<net::IOBuffer> receive_buffer) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(num_bytes_received, 0);
- DCHECK(io_buffer->data());
- DCHECK(out_stream_.is_valid());
+ DCHECK(receive_buffer->data());
+ const bool receive_completed_after_flush = pending_write_buffer_.empty();
read_pending_ = false;
+
+ if (receive_completed_after_flush) {
+ if (out_stream_) {
+ // The prior pipe was flushed while a read was in-flight. Now that
+ // StartReading() has been called, put this received data in the receive
+ // buffer which will prepend to the next read output and call ReadMore()
+ // to start consuming receive_buffer_.
+ receive_buffer_size_ = num_bytes_received;
+ receive_buffer_next_byte_pos_ = 0;
+ receive_buffer_ = std::move(receive_buffer);
+ ReadMore();
+ }
+ return;
+ }
+
// Note: Some platform implementations of BluetoothSocket::Receive ignore the
// buffer size parameter. This means that |num_bytes_received| could be
- // larger than |pending_write_buffer|. Check to avoid buffer overflow.
- size_t bytes_to_copy = std::min(pending_write_buffer.size(),
+ // larger than |pending_write_buffer_|. Check to avoid buffer overflow.
+ DCHECK(out_stream_);
+ size_t bytes_to_copy = std::min(pending_write_buffer_.size(),
static_cast<size_t>(num_bytes_received));
- std::copy(io_buffer->data(), io_buffer->data() + bytes_to_copy,
- pending_write_buffer.data());
+ std::copy(receive_buffer->data(), receive_buffer->data() + bytes_to_copy,
+ pending_write_buffer_.data());
out_stream_->EndWriteData(bytes_to_copy);
- if (pending_write_buffer.size() < static_cast<size_t>(num_bytes_received)) {
+ if (pending_write_buffer_.size() < static_cast<size_t>(num_bytes_received)) {
receive_buffer_size_ = num_bytes_received;
- receive_buffer_next_byte_pos_ = pending_write_buffer.size();
- receive_buffer_ = std::move(io_buffer);
+ receive_buffer_next_byte_pos_ = pending_write_buffer_.size();
+ receive_buffer_ = std::move(receive_buffer);
}
+ ResetPendingWriteBuffer();
- 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());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
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;
+ ResetPendingWriteBuffer();
+
+ if (out_stream_) {
+ 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;
+ }
}
+
+ out_stream_->EndWriteData(0);
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ ResetReceiveBuffer();
}
- 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) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (result) {
case MOJO_RESULT_OK:
+ DCHECK(!write_pending_);
WriteMore();
break;
case MOJO_RESULT_SHOULD_WAIT:
@@ -318,7 +351,9 @@ void BluetoothSerialPortImpl::WriteToSocket(
}
void BluetoothSerialPortImpl::WriteMore() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(in_stream_.is_valid());
+ DCHECK(!write_pending_);
const void* buffer = nullptr;
uint32_t buffer_size = 0;
@@ -329,6 +364,13 @@ void BluetoothSerialPortImpl::WriteMore() {
in_stream_watcher_.ArmOrNotify();
return;
}
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+ if (drain_callback_)
+ std::move(drain_callback_).Run();
+ return;
+ }
if (result != MOJO_RESULT_OK) {
in_stream_watcher_.Cancel();
in_stream_.reset();
@@ -341,10 +383,15 @@ void BluetoothSerialPortImpl::WriteMore() {
}
write_pending_ = true;
+ // Copying the buffer because we might want to close in_stream_, thus
+ // invalidating |buffer|, which is passed to Send().
+ auto io_buffer = base::MakeRefCounted<net::IOBuffer>(buffer_size);
+ std::copy(static_cast<const char*>(buffer),
+ static_cast<const char*>(buffer) + buffer_size, io_buffer->data());
+
+ // The call to EndReadData() will be delayed until after Send() completes.
bluetooth_socket_->Send(
- base::MakeRefCounted<net::WrappedIOBuffer>(
- reinterpret_cast<const char*>(buffer)),
- buffer_size,
+ io_buffer, buffer_size,
base::BindOnce(&BluetoothSerialPortImpl::OnBluetoothSocketSend,
weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&BluetoothSerialPortImpl::OnBluetoothSocketSendError,
@@ -352,37 +399,42 @@ void BluetoothSerialPortImpl::WriteMore() {
}
void BluetoothSerialPortImpl::OnBluetoothSocketSend(int num_bytes_sent) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
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 (!flush_next_write_) {
+ DCHECK(in_stream_);
+ in_stream_->EndReadData(static_cast<uint32_t>(num_bytes_sent));
+ }
+ flush_next_write_ = false;
- if (write_flush_callback_) {
- std::move(write_flush_callback_).Run();
- in_stream_->EndReadData(0);
- in_stream_watcher_.Cancel();
- in_stream_.reset();
- return;
+ // If |in_stream_| is valid then StartWriting() has been called.
+ if (in_stream_) {
+ WriteMore();
}
- WriteMore();
}
void BluetoothSerialPortImpl::OnBluetoothSocketSendError(
const std::string& error_message) {
- DCHECK(in_stream_.is_valid());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
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();
+ flush_next_write_ = false;
+
+ if (in_stream_) {
+ if (client_)
+ client_->OnSendError(mojom::SerialSendError::SYSTEM_ERROR);
+
+ in_stream_->EndReadData(0);
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+ }
}
void BluetoothSerialPortImpl::OnSocketDisconnected(CloseCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(callback).Run();
bluetooth_socket_.reset(); // Avoid calling Disconnect() twice.
delete this;
@@ -390,10 +442,35 @@ void BluetoothSerialPortImpl::OnSocketDisconnected(CloseCallback callback) {
void BluetoothSerialPortImpl::Flush(mojom::SerialPortFlushMode mode,
FlushCallback callback) {
- NOTIMPLEMENTED();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ switch (mode) {
+ case mojom::SerialPortFlushMode::kReceiveAndTransmit:
+ // Do nothing. This case exists to support the chrome.serial.flush()
+ // method and is not used by the Web Serial API.
+ break;
+ case mojom::SerialPortFlushMode::kReceive:
+ if (read_pending_)
+ out_stream_->EndWriteData(0);
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ ResetReceiveBuffer();
+ ResetPendingWriteBuffer();
+ break;
+ case mojom::SerialPortFlushMode::kTransmit:
+ if (write_pending_) {
+ flush_next_write_ = true;
+ in_stream_->EndReadData(0);
+ }
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+ break;
+ }
+
+ std::move(callback).Run();
}
void BluetoothSerialPortImpl::Drain(DrainCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!in_stream_) {
std::move(callback).Run();
return;
@@ -404,6 +481,7 @@ void BluetoothSerialPortImpl::Drain(DrainCallback callback) {
void BluetoothSerialPortImpl::GetControlSignals(
GetControlSignalsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto signals = mojom::SerialPortControlSignals::New();
std::move(callback).Run(std::move(signals));
}
@@ -411,17 +489,20 @@ void BluetoothSerialPortImpl::GetControlSignals(
void BluetoothSerialPortImpl::SetControlSignals(
mojom::SerialHostControlSignalsPtr signals,
SetControlSignalsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(callback).Run(true);
}
void BluetoothSerialPortImpl::ConfigurePort(
mojom::SerialConnectionOptionsPtr options,
ConfigurePortCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
options_ = std::move(options);
std::move(callback).Run(true);
}
void BluetoothSerialPortImpl::GetPortInfo(GetPortInfoCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto info = mojom::SerialConnectionInfo::New(
/*bitrate=*/options_->bitrate, /*data_bits=*/options_->data_bits,
/*parity_bit=*/options_->parity_bit, /*stop_bits=*/options_->stop_bits,
@@ -430,6 +511,7 @@ void BluetoothSerialPortImpl::GetPortInfo(GetPortInfoCallback callback) {
}
void BluetoothSerialPortImpl::Close(CloseCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bluetooth_socket_->Disconnect(
base::BindOnce(&BluetoothSerialPortImpl::OnSocketDisconnected,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl.h b/chromium/services/device/serial/bluetooth_serial_port_impl.h
index 46d675de4e2..11e6f082242 100644
--- a/chromium/services/device/serial/bluetooth_serial_port_impl.h
+++ b/chromium/services/device/serial/bluetooth_serial_port_impl.h
@@ -5,10 +5,11 @@
#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/containers/span.h"
+#include "base/sequence_checker.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "device/bluetooth/bluetooth_adapter.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"
@@ -65,6 +66,9 @@ class BluetoothSerialPortImpl : public mojom::SerialPort {
void ReadFromSocketAndWriteOut(MojoResult result,
const mojo::HandleSignalsState& state);
+ void ResetPendingWriteBuffer();
+ void ResetReceiveBuffer();
+
void ReadMore();
void WriteMore();
@@ -73,9 +77,8 @@ class BluetoothSerialPortImpl : public mojom::SerialPort {
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 OnBluetoothSocketReceive(int num_bytes_received,
+ scoped_refptr<net::IOBuffer> receive_buffer);
void OnBluetoothSocketReceiveError(
device::BluetoothSocket::ErrorReason error_reason,
const std::string& error_message);
@@ -93,10 +96,12 @@ class BluetoothSerialPortImpl : 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
+ // Used for pending writes to |out_stream_|. When empty this indicates that
+ // |out_stream_| has been closed (and possibly replaced).
+ base::span<char> pending_write_buffer_;
+
+ // Holds the callback for a drain until pending operations have been
// completed.
- FlushCallback read_flush_callback_;
- FlushCallback write_flush_callback_;
DrainCallback drain_callback_;
scoped_refptr<BluetoothSocket> bluetooth_socket_;
@@ -106,15 +111,20 @@ class BluetoothSerialPortImpl : public mojom::SerialPort {
bool read_pending_ = false;
bool write_pending_ = false;
- // If the data being received from BluetoothSocket::Receive
- // is too large, these fields will be used to save the data
- // so a single write can be broken up into multiple.
+ // Field to track whether the a write had a Flush call.
+ bool flush_next_write_ = false;
+
+ // |receive_buffer_| is used to temporarily hold larger than expected
+ // BluetoothSocket::Receive() responses, or responses received on a replaced
+ // |out_stream_|.
size_t receive_buffer_size_ = 0;
size_t receive_buffer_next_byte_pos_ = 0;
scoped_refptr<net::IOBuffer> receive_buffer_;
mojom::SerialConnectionOptionsPtr options_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
base::WeakPtrFactory<BluetoothSerialPortImpl> weak_ptr_factory_{this};
};
diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc b/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc
index 5c650a5431f..1520ae2200c 100644
--- a/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc
+++ b/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc
@@ -40,6 +40,7 @@ using ::testing::WithArgs;
constexpr char kBuffer[] = "test";
const size_t kBufferNumBytes = std::char_traits<char>::length(kBuffer);
+constexpr char kDiscardedBuffer[] = "discarded";
constexpr char kDeviceAddress[] = "00:00:00:00:00:00";
constexpr uint32_t kElementNumBytes = 1;
constexpr uint32_t kCapacityNumBytes = 64;
@@ -51,6 +52,46 @@ std::string CreateTestData(size_t buffer_size) {
return test_data;
}
+// Read all readable data from |consumer| into |read_data|.
+MojoResult ReadConsumerData(mojo::ScopedDataPipeConsumerHandle& consumer,
+ std::vector<char>* read_data) {
+ base::RunLoop run_loop;
+ mojo::SimpleWatcher consumer_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ MojoResult result = consumer_watcher.Watch(
+ consumer.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_WATCH_CONDITION_SATISFIED,
+ base::BindLambdaForTesting(
+ [&](MojoResult watch_result, const mojo::HandleSignalsState& state) {
+ EXPECT_EQ(watch_result, MOJO_RESULT_OK);
+ if (watch_result != MOJO_RESULT_OK) {
+ result = watch_result;
+ run_loop.Quit();
+ return;
+ }
+ if (state.readable()) {
+ char read_buffer[32];
+ uint32_t bytes_read = sizeof(read_buffer);
+ result = consumer->ReadData(read_buffer, &bytes_read,
+ MOJO_READ_DATA_FLAG_NONE);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ if (result != MOJO_RESULT_OK) {
+ run_loop.Quit();
+ return;
+ }
+ read_data->insert(read_data->end(), read_buffer,
+ read_buffer + bytes_read);
+ }
+ if (state.peer_closed())
+ run_loop.Quit();
+ }));
+ if (result != MOJO_RESULT_OK)
+ return result;
+ run_loop.Run();
+ return result;
+}
+
class BluetoothSerialPortImplTest : public testing::Test {
public:
BluetoothSerialPortImplTest() {
@@ -202,33 +243,19 @@ TEST_F(BluetoothSerialPortImplTest, StartReadingTest) {
mojo::ScopedDataPipeConsumerHandle consumer;
CreateDataPipe(&producer, &consumer);
- auto producer_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
-
- uint32_t producer_buffer_num_bytes = static_cast<uint32_t>(kBufferNumBytes);
- MojoResult result = producer->WriteData(&kBuffer, &producer_buffer_num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE);
- EXPECT_EQ(result, MOJO_RESULT_OK);
- EXPECT_EQ(kBufferNumBytes, static_cast<size_t>(producer_buffer->size()));
- ASSERT_EQ(kBufferNumBytes, size_t{producer_buffer_num_bytes});
+ auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
EXPECT_CALL(mock_socket(), Receive(_, _, _))
- .WillOnce(RunOnceCallback<1>(producer_buffer->size(), producer_buffer))
+ .WillOnce(RunOnceCallback<1>(write_buffer->size(), write_buffer))
.WillOnce(RunOnceCallback<2>(BluetoothSocket::kSystemError, "Error"));
EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
serial_port->StartReading(std::move(producer));
- // Intentionally try to read more than is in the pipe.
- char consumer_data[kBufferNumBytes + 10];
- uint32_t bytes_read = sizeof(consumer_data);
- result =
- consumer->ReadData(consumer_data, &bytes_read, MOJO_READ_DATA_FLAG_NONE);
- EXPECT_EQ(result, MOJO_RESULT_OK);
- ASSERT_EQ(kBufferNumBytes, size_t{bytes_read});
-
- // EXPECT_EQ only does a shallow comparison, so it's necessary to iterate
- // through both objects and compare each character.
- for (uint32_t i = 0; i < bytes_read; i++) {
+ std::vector<char> consumer_data;
+ EXPECT_EQ(MOJO_RESULT_OK, ReadConsumerData(consumer, &consumer_data));
+ ASSERT_EQ(kBufferNumBytes, consumer_data.size());
+ for (size_t i = 0; i < consumer_data.size(); i++) {
EXPECT_EQ(consumer_data[i], kBuffer[i])
<< "buffer comparison failed at index " << i;
}
@@ -312,6 +339,409 @@ TEST_F(BluetoothSerialPortImplTest, StartReadingLargeBufferTest) {
disconnect_loop.Run();
}
+TEST_F(BluetoothSerialPortImplTest, FlushWrite) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ EXPECT_CALL(mock_socket(), Send).Times(0);
+ serial_port->StartWriting(std::move(consumer));
+
+ // Calling Flush(kTransmit) should cause the data pipe to close.
+ base::RunLoop peer_closed_loop;
+ mojo::SimpleWatcher pipe_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ MojoResult result = 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());
+ peer_closed_loop.Quit();
+ }));
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+
+ base::RunLoop flush_loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
+ flush_loop.QuitClosure());
+ peer_closed_loop.Run();
+ flush_loop.Run();
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, FlushWriteWithDataInPipe) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
+
+ MojoResult result =
+ producer->WriteData(&kBuffer, &bytes_read, MOJO_WRITE_DATA_FLAG_NONE);
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+ EXPECT_EQ(bytes_read, std::char_traits<char>::length(kBuffer));
+
+ EXPECT_CALL(mock_socket(), Send).Times(1);
+ serial_port->StartWriting(std::move(consumer));
+
+ // 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 flush_loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
+ flush_loop.QuitClosure());
+ flush_loop.Run();
+ watcher_loop.Run();
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, FlushWriteAndWriteNewPipe) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ // The data to be written to the serial port in this test.
+ constexpr size_t kBufferSize = kCapacityNumBytes;
+ constexpr size_t kBufferMidpointPos = kBufferSize / 2;
+ const std::string write_data = CreateTestData(kBufferSize);
+ uint32_t bytes_written;
+ MojoResult result;
+
+ const std::string pre_flush_data =
+ write_data.substr(/*pos=*/0, /*count=*/kBufferMidpointPos);
+
+ const std::string post_flush_data = write_data.substr(
+ kBufferMidpointPos, write_data.size() - kBufferMidpointPos);
+
+ /*******************************************************************/
+ /* Start writing a first time, which calls Send(...), but save the */
+ /* completion callback so that it can be called after the Flush() */
+ /*******************************************************************/
+ MockBluetoothSocket::SendCompletionCallback pre_flush_send_callback;
+ {
+ mojo::ScopedDataPipeProducerHandle pre_flush_producer;
+ mojo::ScopedDataPipeConsumerHandle pre_flush_consumer;
+ CreateDataPipe(&pre_flush_producer, &pre_flush_consumer);
+
+ EXPECT_CALL(mock_socket(), Send)
+ .WillOnce(WithArgs<0, 1, 2>(
+ Invoke([&](scoped_refptr<net::IOBuffer> buf, int buffer_size,
+ MockBluetoothSocket::SendCompletionCallback callback) {
+ EXPECT_EQ(buffer_size, static_cast<int>(bytes_written));
+ DCHECK(!pre_flush_send_callback);
+ for (int i = 0; i < buffer_size; i++) {
+ EXPECT_EQ(buf->data()[i], pre_flush_data[i])
+ << "buffer comparison failed at index " << i;
+ }
+ pre_flush_send_callback = std::move(callback);
+ })));
+
+ bytes_written = pre_flush_data.size();
+ result = pre_flush_producer->WriteData(
+ pre_flush_data.data(), &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+ EXPECT_EQ(bytes_written, pre_flush_data.size());
+
+ serial_port->StartWriting(std::move(pre_flush_consumer));
+
+ // Calling Flush(kTransmit) causes the data pipe to close.
+ base::RunLoop watcher_loop;
+ mojo::SimpleWatcher pipe_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ result = pipe_watcher.Watch(
+ pre_flush_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();
+ }));
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+
+ base::RunLoop flush_loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
+ flush_loop.QuitClosure());
+ flush_loop.Run();
+ watcher_loop.Run();
+ }
+
+ /***************************************************************************/
+ /* Start writing a second time after flushing. Call the send callback for */
+ /* the first write. This simulates a pre flush in-flight Send() completing */
+ /* after flushing and restarting writing. */
+ /***************************************************************************/
+ mojo::ScopedDataPipeProducerHandle post_flush_producer;
+ mojo::ScopedDataPipeConsumerHandle post_flush_consumer;
+ CreateDataPipe(&post_flush_producer, &post_flush_consumer);
+
+ bytes_written = post_flush_data.size();
+ result = post_flush_producer->WriteData(
+ post_flush_data.data(), &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+ EXPECT_EQ(bytes_written, post_flush_data.size());
+
+ base::RunLoop post_flush_send_run_loop;
+
+ EXPECT_CALL(mock_socket(), Send)
+ .WillOnce(WithArgs<0, 1, 2>(
+ Invoke([&](scoped_refptr<net::IOBuffer> buf, int buffer_size,
+ MockBluetoothSocket::SendCompletionCallback callback) {
+ EXPECT_EQ(buffer_size, static_cast<int>(bytes_written));
+ DCHECK(!pre_flush_send_callback);
+ for (int i = 0; i < buffer_size; i++) {
+ EXPECT_EQ(buf->data()[i], post_flush_data[i])
+ << "buffer comparison failed at index " << i;
+ }
+ std::move(callback).Run(buffer_size);
+ post_flush_send_run_loop.Quit();
+ })));
+
+ serial_port->StartWriting(std::move(post_flush_consumer));
+ // Wait for StartWriting to start on the remote end before directly calling
+ // the receive callback - which executes on the remote end.
+ serial_port.FlushForTesting();
+
+ // Write the first half of the data to the pre-flush receive callback.
+ ASSERT_TRUE(pre_flush_send_callback);
+ std::move(pre_flush_send_callback).Run(pre_flush_data.size());
+
+ post_flush_send_run_loop.Run();
+
+ /************/
+ /* Cleanup. */
+ /************/
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, FlushRead) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ const std::string test_data = CreateTestData(4);
+
+ auto discarded_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(kDiscardedBuffer);
+
+ MockBluetoothSocket::ReceiveCompletionCallback pre_flush_receive_callback;
+ EXPECT_CALL(mock_socket(), Receive)
+ .WillOnce(
+ [&](int buffer_size,
+ MockBluetoothSocket::ReceiveCompletionCallback success_callback,
+ MockBluetoothSocket::ReceiveErrorCompletionCallback
+ error_callback) {
+ pre_flush_receive_callback = std::move(success_callback);
+ });
+ serial_port->StartReading(std::move(producer));
+
+ // Calling Flush(kReceive) should cause the data pipe to close.
+ {
+ base::RunLoop watcher_loop;
+ mojo::SimpleWatcher pipe_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ MojoResult result = pipe_watcher.Watch(
+ consumer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindLambdaForTesting([&](MojoResult watcher_result,
+ const mojo::HandleSignalsState& state) {
+ EXPECT_EQ(watcher_result, MOJO_RESULT_OK);
+ EXPECT_TRUE(state.peer_closed());
+ watcher_loop.Quit();
+ }));
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+
+ base::RunLoop flush_loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kReceive,
+ flush_loop.QuitClosure());
+ flush_loop.Run();
+ watcher_loop.Run();
+ }
+
+ // Running the Receive callback before StartReading() is called should result
+ // in this data being discarded.
+ ASSERT_TRUE(pre_flush_receive_callback);
+ std::move(pre_flush_receive_callback)
+ .Run(discarded_buffer->size(), discarded_buffer);
+
+ mojo::ScopedDataPipeProducerHandle new_producer;
+ mojo::ScopedDataPipeConsumerHandle new_consumer;
+ CreateDataPipe(&new_producer, &new_consumer);
+
+ auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(test_data);
+ EXPECT_CALL(mock_socket(), Receive(_, _, _))
+ .WillOnce(RunOnceCallback<1>(write_buffer->size(), write_buffer))
+ .WillOnce(RunOnceCallback<2>(BluetoothSocket::kSystemError, "Error"));
+ serial_port->StartReading(std::move(new_producer));
+
+ std::vector<char> consumer_data;
+ EXPECT_EQ(MOJO_RESULT_OK, ReadConsumerData(new_consumer, &consumer_data));
+ ASSERT_EQ(test_data.size(), consumer_data.size());
+ for (size_t i = 0; i < consumer_data.size(); i++) {
+ EXPECT_EQ(consumer_data[i], test_data[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, FlushReadAndReadNewPipe) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ // The data to be written to the serial port.
+ constexpr size_t kBufferSize = kCapacityNumBytes - 1;
+ constexpr size_t kBufferMidpointPos = kBufferSize / 2;
+ const std::string write_data = CreateTestData(kBufferSize);
+
+ // First half of data.
+ auto pre_flush_buffer = base::MakeRefCounted<net::StringIOBuffer>(
+ write_data.substr(/*pos=*/0, /*count=*/kBufferMidpointPos));
+
+ // Second half of data.
+ const std::string post_flush_data =
+ write_data.substr(kBufferMidpointPos, kBufferSize - kBufferMidpointPos);
+
+ MockBluetoothSocket::ReceiveCompletionCallback pre_flush_receive_callback;
+
+ // Calling Flush(kReceive) will cause the data pipe to close.
+ {
+ mojo::ScopedDataPipeProducerHandle pre_flush_producer;
+ mojo::ScopedDataPipeConsumerHandle pre_flush_consumer;
+ CreateDataPipe(&pre_flush_producer, &pre_flush_consumer);
+
+ EXPECT_CALL(mock_socket(), Receive)
+ .WillOnce(
+ [&](int buffer_size,
+ MockBluetoothSocket::ReceiveCompletionCallback success_callback,
+ MockBluetoothSocket::ReceiveErrorCompletionCallback
+ error_callback) {
+ EXPECT_FALSE(pre_flush_receive_callback);
+ pre_flush_receive_callback = std::move(success_callback);
+ });
+
+ base::RunLoop watcher_loop;
+ mojo::SimpleWatcher write_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ MojoResult result = result = write_watcher.Watch(
+ pre_flush_consumer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindLambdaForTesting(
+ [&watcher_loop](MojoResult result,
+ const mojo::HandleSignalsState& state) {
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+ EXPECT_TRUE(state.peer_closed());
+ watcher_loop.Quit();
+ }));
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+
+ serial_port->StartReading(std::move(pre_flush_producer));
+
+ base::RunLoop flush_loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kReceive,
+ flush_loop.QuitClosure());
+ flush_loop.Run();
+ watcher_loop.Run();
+ EXPECT_TRUE(pre_flush_receive_callback);
+ }
+
+ mojo::ScopedDataPipeProducerHandle post_flush_producer;
+ mojo::ScopedDataPipeConsumerHandle post_flush_consumer;
+ CreateDataPipe(&post_flush_producer, &post_flush_consumer);
+
+ size_t num_write_bytes = 0;
+ EXPECT_CALL(mock_socket(), Receive)
+ .Times(2)
+ .WillRepeatedly([&](int buffer_size,
+ MockBluetoothSocket::ReceiveCompletionCallback
+ success_callback,
+ MockBluetoothSocket::ReceiveErrorCompletionCallback
+ error_callback) {
+ EXPECT_FALSE(pre_flush_receive_callback);
+ if (!num_write_bytes) {
+ num_write_bytes = post_flush_data.size();
+ std::move(success_callback)
+ .Run(post_flush_data.size(),
+ base::MakeRefCounted<net::StringIOBuffer>(post_flush_data));
+ } else {
+ std::move(error_callback).Run(BluetoothSocket::kSystemError, "Error");
+ }
+ });
+
+ // Write the second half of the data after the flush.
+ serial_port->StartReading(std::move(post_flush_producer));
+ // Wait for StartReading to start on the remote end before directly calling
+ // the receive callback - which executes on the remote end.
+ serial_port.FlushForTesting();
+
+ // Write the first half of the data to the pre-flush receive callback.
+ ASSERT_TRUE(pre_flush_receive_callback);
+ std::move(pre_flush_receive_callback)
+ .Run(pre_flush_buffer->size(), pre_flush_buffer);
+
+ std::vector<char> consumer_data;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ ReadConsumerData(post_flush_consumer, &consumer_data));
+
+ // Verify post flush receive data is received by the consumer in the correct
+ // order.
+ ASSERT_EQ(write_data.size(), consumer_data.size());
+ for (size_t i = 0; i < consumer_data.size(); i++) {
+ EXPECT_EQ(consumer_data[i], write_data[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;
diff --git a/chromium/services/device/serial/fake_serial_device_enumerator.h b/chromium/services/device/serial/fake_serial_device_enumerator.h
index 5904b42b3be..956a41a4423 100644
--- a/chromium/services/device/serial/fake_serial_device_enumerator.h
+++ b/chromium/services/device/serial/fake_serial_device_enumerator.h
@@ -8,7 +8,6 @@
#include <map>
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "services/device/serial/serial_device_enumerator.h"
namespace device {
diff --git a/chromium/services/device/serial/serial_device_enumerator_linux.h b/chromium/services/device/serial/serial_device_enumerator_linux.h
index a7c4f3b569a..96382f1e748 100644
--- a/chromium/services/device/serial/serial_device_enumerator_linux.h
+++ b/chromium/services/device/serial/serial_device_enumerator_linux.h
@@ -9,7 +9,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "device/udev_linux/udev_watcher.h"
#include "services/device/serial/serial_device_enumerator.h"
diff --git a/chromium/services/device/serial/serial_device_enumerator_mac.h b/chromium/services/device/serial/serial_device_enumerator_mac.h
index 3c868f8538d..99d1a8647df 100644
--- a/chromium/services/device/serial/serial_device_enumerator_mac.h
+++ b/chromium/services/device/serial/serial_device_enumerator_mac.h
@@ -12,7 +12,6 @@
#include "base/mac/scoped_ionotificationportref.h"
#include "base/mac/scoped_ioobject.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/unguessable_token.h"
#include "services/device/serial/serial_device_enumerator.h"
diff --git a/chromium/services/device/serial/serial_device_enumerator_win.cc b/chromium/services/device/serial/serial_device_enumerator_win.cc
index 954e785d278..82e1e6ef0d8 100644
--- a/chromium/services/device/serial/serial_device_enumerator_win.cc
+++ b/chromium/services/device/serial/serial_device_enumerator_win.cc
@@ -6,19 +6,19 @@
#include <windows.h> // Must be in front of other Windows header files.
+#define INITGUID
#include <devguid.h>
+#include <devpkey.h>
#include <ntddser.h>
#include <setupapi.h>
#include <stdint.h>
-#define INITGUID
-#include <devpkey.h>
-
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
+#include "base/containers/contains.h"
#include "base/metrics/histogram_functions.h"
#include "base/scoped_generic.h"
#include "base/scoped_observation.h"
@@ -27,6 +27,7 @@
#include "base/strings/string_piece.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/threading/scoped_blocking_call.h"
#include "base/win/registry.h"
@@ -67,26 +68,38 @@ absl::optional<std::string> GetProperty(HDEVINFO dev_info,
return base::WideToUTF8(buffer);
}
-base::FilePath FixUpPortName(base::StringPiece port_name) {
+// Get the port name from the registry.
+absl::optional<std::string> GetPortName(HDEVINFO dev_info,
+ SP_DEVINFO_DATA* dev_info_data) {
+ HKEY key = SetupDiOpenDevRegKey(dev_info, dev_info_data, DICS_FLAG_GLOBAL, 0,
+ DIREG_DEV, KEY_READ);
+ if (key == INVALID_HANDLE_VALUE) {
+ SERIAL_PLOG(ERROR) << "Could not open device registry key";
+ return absl::nullopt;
+ }
+ base::win::RegKey scoped_key(key);
+
+ std::wstring port_name;
+ LONG result = scoped_key.ReadValue(L"PortName", &port_name);
+ if (result != ERROR_SUCCESS) {
+ SERIAL_LOG(ERROR) << "Failed to read port name: "
+ << logging::SystemErrorCodeToString(result);
+ return absl::nullopt;
+ }
+
+ return base::SysWideToUTF8(port_name);
+}
+
+// Deduce the path for the device from the port name.
+base::FilePath GetPath(std::string port_name) {
// For COM numbers less than 9, CreateFile is called with a string such as
// "COM1". For numbers greater than 9, a prefix of "\\.\" must be added.
- if (port_name.length() > std::string("COM9").length())
+ if (port_name.length() > base::StringPiece("COM9").length())
return base::FilePath(LR"(\\.\)").AppendASCII(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.
-absl::optional<base::FilePath> GetPath(const std::string& friendly_name) {
- std::string com_port;
- if (!RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", &com_port))
- return absl::nullopt;
-
- return FixUpPortName(com_port);
-}
-
// Searches for the display name in the device's friendly name. Returns nullopt
// if the name does not match the expected pattern.
absl::optional<std::string> GetDisplayName(const std::string& friendly_name) {
@@ -217,7 +230,7 @@ void SerialDeviceEnumeratorWin::OnPathAdded(const std::wstring& device_path) {
if (!SetupDiEnumDeviceInfo(dev_info.get(), 0, &dev_info_data))
return;
- EnumeratePort(dev_info.get(), &dev_info_data);
+ EnumeratePort(dev_info.get(), &dev_info_data, /*check_port_name=*/false);
}
void SerialDeviceEnumeratorWin::OnPathRemoved(const std::wstring& device_path) {
@@ -236,19 +249,12 @@ void SerialDeviceEnumeratorWin::OnPathRemoved(const std::wstring& device_path) {
if (!SetupDiEnumDeviceInfo(dev_info.get(), 0, &dev_info_data))
return;
- // The friendly name looks like "USB_SERIAL_PORT (COM3)".
- // In Windows, the COM port is the path used to uniquely identify the
- // serial device. If the COM can't be found, ignore the device.
- absl::optional<std::string> friendly_name =
- GetProperty(dev_info.get(), &dev_info_data, DEVPKEY_Device_FriendlyName);
- if (!friendly_name)
+ absl::optional<std::string> port_name =
+ GetPortName(dev_info.get(), &dev_info_data);
+ if (!port_name)
return;
- absl::optional<base::FilePath> path = GetPath(*friendly_name);
- if (!path)
- return;
-
- auto it = paths_.find(*path);
+ auto it = paths_.find(GetPath(*port_name));
if (it == paths_.end())
return;
@@ -261,38 +267,57 @@ void SerialDeviceEnumeratorWin::OnPathRemoved(const std::wstring& device_path) {
void SerialDeviceEnumeratorWin::DoInitialEnumeration() {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
- // Make a device interface query to find all serial devices.
- //
- // By using this GUID without passing DIGCF_DEVICEINTERFACE we get to
- // enumerate all of the devices matching this GUID as a class, which is
- // different from an interface and seems to find some otherwise unenumerable
- // devices. https://crbug.com/1119497
- base::win::ScopedDevInfo dev_info;
- dev_info.reset(SetupDiGetClassDevs(&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
- nullptr, 0, DIGCF_PRESENT));
- if (!dev_info.is_valid())
- return;
- SP_DEVINFO_DATA dev_info_data = {};
- dev_info_data.cbSize = sizeof(dev_info_data);
- for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info.get(), i, &dev_info_data);
- i++) {
- EnumeratePort(dev_info.get(), &dev_info_data);
+ // On Windows 10 and above most COM port drivers register using the COMPORT
+ // device interface class. Try to enumerate these first.
+ {
+ base::win::ScopedDevInfo dev_info;
+ dev_info.reset(SetupDiGetClassDevs(&GUID_DEVINTERFACE_COMPORT, nullptr, 0,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+ if (!dev_info.is_valid())
+ return;
+
+ SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(dev_info_data)};
+ for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info.get(), i, &dev_info_data);
+ i++) {
+ EnumeratePort(dev_info.get(), &dev_info_data, /*check_port_name=*/false);
+ }
+ }
+
+ // To detect devices which don't register with GUID_DEVINTERFACE_COMPORT also
+ // enuerate all devices in the "Ports" and "Modems" device classes. These must
+ // be checked to see if the port name starts with "COM" because it also
+ // includes LPT ports.
+ constexpr const GUID* kDeviceClasses[] = {&GUID_DEVCLASS_MODEM,
+ &GUID_DEVCLASS_PORTS};
+ for (const GUID* guid : kDeviceClasses) {
+ base::win::ScopedDevInfo dev_info;
+ dev_info.reset(SetupDiGetClassDevs(guid, nullptr, 0, DIGCF_PRESENT));
+ if (!dev_info.is_valid())
+ return;
+
+ SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(dev_info_data)};
+ for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info.get(), i, &dev_info_data);
+ i++) {
+ EnumeratePort(dev_info.get(), &dev_info_data, /*check_port_name=*/true);
+ }
}
}
void SerialDeviceEnumeratorWin::EnumeratePort(HDEVINFO dev_info,
- SP_DEVINFO_DATA* dev_info_data) {
- // The friendly name looks like "USB_SERIAL_PORT (COM3)".
- // In Windows, the COM port is the path used to uniquely identify the
- // serial device. If the COM can't be found, ignore the device.
- absl::optional<std::string> friendly_name =
- GetProperty(dev_info, dev_info_data, DEVPKEY_Device_FriendlyName);
- if (!friendly_name)
+ SP_DEVINFO_DATA* dev_info_data,
+ bool check_port_name) {
+ absl::optional<std::string> port_name = GetPortName(dev_info, dev_info_data);
+ if (!port_name)
return;
- absl::optional<base::FilePath> path = GetPath(*friendly_name);
- if (!path)
+ if (check_port_name && !base::StartsWith(*port_name, "COM"))
+ return;
+
+ // Check whether the currently enumerating port has been seen before since
+ // the method above will generate duplicate enumerations for some ports.
+ base::FilePath path = GetPath(*port_name);
+ if (base::Contains(paths_, path))
return;
absl::optional<std::string> instance_id =
@@ -308,7 +333,7 @@ void SerialDeviceEnumeratorWin::EnumeratePort(HDEVINFO dev_info,
base::UnguessableToken token = base::UnguessableToken::Create();
auto info = mojom::SerialPortInfo::New();
info->token = token;
- info->path = *path;
+ info->path = path;
info->device_instance_id = *instance_id;
// TODO(https://crbug.com/1015074): While the "bus reported device
@@ -326,6 +351,11 @@ void SerialDeviceEnumeratorWin::EnumeratePort(HDEVINFO dev_info,
// Fall back to the "friendly name" if no "bus reported device description"
// is available. This name will likely be the same for all devices using the
// same driver.
+ absl::optional<std::string> friendly_name =
+ GetProperty(dev_info, dev_info_data, DEVPKEY_Device_FriendlyName);
+ if (!friendly_name)
+ return;
+
info->display_name = GetDisplayName(*friendly_name);
}
@@ -349,7 +379,7 @@ void SerialDeviceEnumeratorWin::EnumeratePort(HDEVINFO dev_info,
<< " vid=" << vendor_id_str.value_or("(none)")
<< " pid=" << product_id_str.value_or("(none)");
- paths_.insert(std::make_pair(*path, token));
+ paths_.insert(std::make_pair(path, token));
AddPort(std::move(info));
}
diff --git a/chromium/services/device/serial/serial_device_enumerator_win.h b/chromium/services/device/serial/serial_device_enumerator_win.h
index 2909a532de5..f917b08aec9 100644
--- a/chromium/services/device/serial/serial_device_enumerator_win.h
+++ b/chromium/services/device/serial/serial_device_enumerator_win.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_SERIAL_SERIAL_DEVICE_ENUMERATOR_WIN_H_
#define SERVICES_DEVICE_SERIAL_SERIAL_DEVICE_ENUMERATOR_WIN_H_
-#include "base/macros.h"
#include "base/win/windows_types.h"
#include "device/base/device_monitor_win.h"
#include "services/device/serial/serial_device_enumerator.h"
@@ -34,7 +33,9 @@ class SerialDeviceEnumeratorWin : public SerialDeviceEnumerator {
class UiThreadHelper;
void DoInitialEnumeration();
- void EnumeratePort(HDEVINFO dev_info, SP_DEVINFO_DATA* dev_info_data);
+ void EnumeratePort(HDEVINFO dev_info,
+ SP_DEVINFO_DATA* dev_info_data,
+ bool check_port_name);
std::map<base::FilePath, base::UnguessableToken> paths_;
diff --git a/chromium/services/device/serial/serial_io_handler.cc b/chromium/services/device/serial/serial_io_handler.cc
index f6d87157ce3..d9e9124f3a2 100644
--- a/chromium/services/device/serial/serial_io_handler.cc
+++ b/chromium/services/device/serial/serial_io_handler.cc
@@ -132,8 +132,8 @@ void SerialIoHandler::StartOpen(
DCHECK(open_complete_);
DCHECK(!file_.IsValid());
int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
- base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE |
- base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC |
+ base::File::FLAG_WIN_EXCLUSIVE_READ | base::File::FLAG_WRITE |
+ base::File::FLAG_WIN_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC |
base::File::FLAG_TERMINAL_DEVICE;
base::File file(port_, flags);
io_task_runner->PostTask(
@@ -190,10 +190,17 @@ void SerialIoHandler::Read(base::span<uint8_t> buffer,
ReadCompleteCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!IsReadPending());
+
pending_read_buffer_ = buffer;
pending_read_callback_ = std::move(callback);
read_canceled_ = false;
AddRef();
+
+ if (!file().IsValid()) {
+ ReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
+ return;
+ }
+
ReadImpl();
}
@@ -201,10 +208,17 @@ void SerialIoHandler::Write(base::span<const uint8_t> buffer,
WriteCompleteCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!IsWritePending());
+
pending_write_buffer_ = buffer;
pending_write_callback_ = std::move(callback);
write_canceled_ = false;
AddRef();
+
+ if (!file().IsValid()) {
+ WriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ return;
+ }
+
WriteImpl();
}
@@ -260,18 +274,4 @@ bool SerialIoHandler::ConfigurePort(
return ConfigurePortImpl();
}
-void SerialIoHandler::QueueReadCompleted(int bytes_read,
- mojom::SerialReceiveError error) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
-}
-
-void SerialIoHandler::QueueWriteCompleted(int bytes_written,
- mojom::SerialSendError error) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&SerialIoHandler::WriteCompleted, this,
- bytes_written, error));
-}
-
} // namespace device
diff --git a/chromium/services/device/serial/serial_io_handler.h b/chromium/services/device/serial/serial_io_handler.h
index 118e0ef24b4..396f46393f5 100644
--- a/chromium/services/device/serial/serial_io_handler.h
+++ b/chromium/services/device/serial/serial_io_handler.h
@@ -12,10 +12,9 @@
#include "base/callback.h"
#include "base/files/file.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -34,6 +33,9 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
const base::FilePath& port,
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
+ SerialIoHandler(const SerialIoHandler&) = delete;
+ SerialIoHandler& operator=(const SerialIoHandler&) = delete;
+
using OpenCompleteCallback = base::OnceCallback<void(bool success)>;
using ReadCompleteCallback =
base::OnceCallback<void(uint32_t bytes_read, mojom::SerialReceiveError)>;
@@ -62,13 +64,15 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
// Performs an async read operation. Behavior is undefined if this is called
- // while a read is already pending. Otherwise, |callback| will eventually be
- // called with a result. |buffer| must remain valid until |callback| is run.
+ // while a read is already pending. Otherwise, |callback| will be called
+ // (potentially synchronously) with a result. |buffer| must remain valid until
+ // |callback| is run.
void Read(base::span<uint8_t> buffer, ReadCompleteCallback callback);
// Performs an async write operation. Behavior is undefined if this is called
- // while a write is already pending. Otherwise, |callback| will eventually be
- // called with a result. |buffer| must remain valid until |callback| is run.
+ // while a write is already pending. Otherwise, |callback| will be called
+ // (potentially synchronously) with a result. |buffer| must remain valid until
+ // |callback| is run.
void Write(base::span<const uint8_t> buffer, WriteCompleteCallback callback);
// Indicates whether or not a read is currently pending.
@@ -120,15 +124,13 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
// Performs a platform-specific read operation. This must guarantee that
// ReadCompleted is called when the underlying async operation is completed
// or the SerialIoHandler instance will leak.
- // NOTE: Implementations of ReadImpl should never call ReadCompleted directly.
- // Use QueueReadCompleted instead to avoid reentrancy.
+ // NOTE: Implementations of ReadImpl may call ReadCompleted directly.
virtual void ReadImpl() = 0;
// Performs a platform-specific write operation. This must guarantee that
// WriteCompleted is called when the underlying async operation is completed
// or the SerialIoHandler instance will leak.
- // NOTE: Implementations of WriteImpl should never call WriteCompleted
- // directly. Use QueueWriteCompleted instead to avoid reentrancy.
+ // NOTE: Implementations of WriteImpl may call WriteCompleted directly.
virtual void WriteImpl() = 0;
// Platform-specific read cancelation.
@@ -156,16 +158,6 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
// if the associated I/O operation was the only thing keeping it alive.
void WriteCompleted(int bytes_written, mojom::SerialSendError error);
- // Queues a ReadCompleted call on the current thread. This is used to allow
- // ReadImpl to immediately signal completion with 0 bytes and an error,
- // without being reentrant.
- void QueueReadCompleted(int bytes_read, mojom::SerialReceiveError error);
-
- // Queues a WriteCompleted call on the current thread. This is used to allow
- // WriteImpl to immediately signal completion with 0 bytes and an error,
- // without being reentrant.
- void QueueWriteCompleted(int bytes_written, mojom::SerialSendError error);
-
const base::File& file() const { return file_; }
base::span<uint8_t> pending_read_buffer() const {
@@ -236,8 +228,6 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
// On Chrome OS, PermissionBrokerClient should be called on the UI thread.
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(SerialIoHandler);
};
} // namespace device
diff --git a/chromium/services/device/serial/serial_io_handler_posix.cc b/chromium/services/device/serial/serial_io_handler_posix.cc
index 8236b0266a5..4c99b689bc0 100644
--- a/chromium/services/device/serial/serial_io_handler_posix.cc
+++ b/chromium/services/device/serial/serial_io_handler_posix.cc
@@ -129,40 +129,30 @@ void SerialIoHandlerPosix::ReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(IsReadPending());
- if (!file().IsValid()) {
- QueueReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
- return;
- }
-
// Try to read immediately. This is needed because on some platforms
// (e.g., OSX) there may not be a notification from the message loop
// when the fd is ready to read immediately after it is opened. There
// is no danger of blocking because the fd is opened with async flag.
- AttemptRead(true);
+ AttemptRead();
}
void SerialIoHandlerPosix::WriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(IsWritePending());
- if (!file().IsValid()) {
- QueueWriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
- return;
- }
-
EnsureWatchingWrites();
}
void SerialIoHandlerPosix::CancelReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
StopWatchingFileRead();
- QueueReadCompleted(0, read_cancel_reason());
+ ReadCompleted(0, read_cancel_reason());
}
void SerialIoHandlerPosix::CancelWriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
StopWatchingFileWrite();
- QueueWriteCompleted(0, write_cancel_reason());
+ WriteCompleted(0, write_cancel_reason());
}
bool SerialIoHandlerPosix::ConfigurePortImpl() {
@@ -297,7 +287,7 @@ bool SerialIoHandlerPosix::ConfigurePortImpl() {
}
bool SerialIoHandlerPosix::PostOpen() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
// The Chrome OS permission broker does not open devices in async mode.
return base::SetNonBlocking(file().GetPlatformFile());
#else
@@ -317,7 +307,7 @@ SerialIoHandlerPosix::SerialIoHandlerPosix(
SerialIoHandlerPosix::~SerialIoHandlerPosix() = default;
-void SerialIoHandlerPosix::AttemptRead(bool within_read) {
+void SerialIoHandlerPosix::AttemptRead() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsReadPending()) {
int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(),
@@ -328,17 +318,15 @@ void SerialIoHandlerPosix::AttemptRead(bool within_read) {
// The fd does not have data to read yet so continue waiting.
EnsureWatchingReads();
} else if (errno == ENXIO) {
- RunReadCompleted(within_read, 0,
- mojom::SerialReceiveError::DEVICE_LOST);
StopWatchingFileRead();
+ ReadCompleted(0, mojom::SerialReceiveError::DEVICE_LOST);
} else {
SERIAL_PLOG(DEBUG) << "Read failed";
- RunReadCompleted(within_read, 0,
- mojom::SerialReceiveError::SYSTEM_ERROR);
+ ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
}
} else if (bytes_read == 0) {
- RunReadCompleted(within_read, 0, mojom::SerialReceiveError::DEVICE_LOST);
StopWatchingFileRead();
+ ReadCompleted(0, mojom::SerialReceiveError::DEVICE_LOST);
} else {
bool break_detected = false;
bool parity_error_detected = false;
@@ -347,14 +335,11 @@ void SerialIoHandlerPosix::AttemptRead(bool within_read) {
parity_error_detected);
if (break_detected) {
- RunReadCompleted(within_read, new_bytes_read,
- mojom::SerialReceiveError::BREAK);
+ ReadCompleted(new_bytes_read, mojom::SerialReceiveError::BREAK);
} else if (parity_error_detected) {
- RunReadCompleted(within_read, new_bytes_read,
- mojom::SerialReceiveError::PARITY_ERROR);
+ ReadCompleted(new_bytes_read, mojom::SerialReceiveError::PARITY_ERROR);
} else {
- RunReadCompleted(within_read, new_bytes_read,
- mojom::SerialReceiveError::NONE);
+ ReadCompleted(new_bytes_read, mojom::SerialReceiveError::NONE);
}
}
} else {
@@ -364,20 +349,6 @@ void SerialIoHandlerPosix::AttemptRead(bool within_read) {
}
}
-void SerialIoHandlerPosix::RunReadCompleted(bool within_read,
- int bytes_read,
- mojom::SerialReceiveError error) {
- if (within_read) {
- // Stop watching the fd to avoid more reads until the queued ReadCompleted()
- // completes and releases the pending_read_buffer.
- StopWatchingFileRead();
-
- QueueReadCompleted(bytes_read, error);
- } else {
- ReadCompleted(bytes_read, error);
- }
-}
-
void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsWritePending()) {
@@ -385,9 +356,9 @@ void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking() {
pending_write_buffer().data(),
pending_write_buffer().size()));
if (bytes_written < 0) {
- if (errno == ENXIO) {
- WriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ if (errno == EIO || errno == ENXIO) {
StopWatchingFileWrite();
+ WriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
} else {
SERIAL_PLOG(DEBUG) << "Write failed";
WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
@@ -409,7 +380,7 @@ void SerialIoHandlerPosix::EnsureWatchingReads() {
file_read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
file().GetPlatformFile(),
base::BindRepeating(&SerialIoHandlerPosix::AttemptRead,
- base::Unretained(this), false));
+ base::Unretained(this)));
}
}
diff --git a/chromium/services/device/serial/serial_io_handler_posix.h b/chromium/services/device/serial/serial_io_handler_posix.h
index e5953cbca6c..a8190cd37c0 100644
--- a/chromium/services/device/serial/serial_io_handler_posix.h
+++ b/chromium/services/device/serial/serial_io_handler_posix.h
@@ -8,8 +8,7 @@
#include <memory>
#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "services/device/serial/serial_io_handler.h"
@@ -21,6 +20,10 @@ namespace device {
enum class ErrorDetectState { NO_ERROR, MARK_377_SEEN, MARK_0_SEEN };
class SerialIoHandlerPosix : public SerialIoHandler {
+ public:
+ SerialIoHandlerPosix(const SerialIoHandlerPosix&) = delete;
+ SerialIoHandlerPosix& operator=(const SerialIoHandlerPosix&) = delete;
+
protected:
// SerialIoHandler impl.
void ReadImpl() override;
@@ -50,10 +53,7 @@ class SerialIoHandlerPosix : public SerialIoHandler {
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
~SerialIoHandlerPosix() override;
- void AttemptRead(bool within_read);
- void RunReadCompleted(bool within_read,
- int bytes_read,
- mojom::SerialReceiveError error);
+ void AttemptRead();
// Called when file() is writable without blocking.
void OnFileCanWriteWithoutBlocking();
@@ -71,8 +71,6 @@ class SerialIoHandlerPosix : public SerialIoHandler {
bool parity_check_enabled_;
uint8_t chars_stashed_[2];
int num_chars_stashed_;
-
- DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerPosix);
};
} // namespace device
diff --git a/chromium/services/device/serial/serial_io_handler_posix_unittest.cc b/chromium/services/device/serial/serial_io_handler_posix_unittest.cc
index 94f111d6c34..ff32560a923 100644
--- a/chromium/services/device/serial/serial_io_handler_posix_unittest.cc
+++ b/chromium/services/device/serial/serial_io_handler_posix_unittest.cc
@@ -4,7 +4,6 @@
#include "services/device/serial/serial_io_handler_posix.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
@@ -13,6 +12,9 @@ class SerialIoHandlerPosixTest : public testing::Test {
public:
SerialIoHandlerPosixTest() = default;
+ SerialIoHandlerPosixTest(const SerialIoHandlerPosixTest&) = delete;
+ SerialIoHandlerPosixTest& operator=(const SerialIoHandlerPosixTest&) = delete;
+
void SetUp() override {
serial_io_handler_posix_ =
new SerialIoHandlerPosix(base::FilePath("dummy-port"), nullptr);
@@ -63,9 +65,6 @@ class SerialIoHandlerPosixTest : public testing::Test {
protected:
scoped_refptr<SerialIoHandlerPosix> serial_io_handler_posix_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerPosixTest);
};
// 'a' 'b' 'c'
diff --git a/chromium/services/device/serial/serial_io_handler_win.cc b/chromium/services/device/serial/serial_io_handler_win.cc
index db6ae62c0cf..6d73dab0e30 100644
--- a/chromium/services/device/serial/serial_io_handler_win.cc
+++ b/chromium/services/device/serial/serial_io_handler_win.cc
@@ -185,11 +185,6 @@ void SerialIoHandlerWin::ReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(IsReadPending());
- if (!file().IsValid()) {
- QueueReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
- return;
- }
-
ClearPendingError();
if (!IsReadPending())
return;
@@ -206,11 +201,6 @@ void SerialIoHandlerWin::WriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(IsWritePending());
- if (!file().IsValid()) {
- QueueWriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
- return;
- }
-
if (!WriteFile(file().GetPlatformFile(), pending_write_buffer().data(),
pending_write_buffer().size(), nullptr,
&write_context_->overlapped) &&
@@ -317,7 +307,6 @@ void SerialIoHandlerWin::OnIOCompleted(
} else {
SERIAL_LOG(DEBUG) << "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 |read_context_| and the error is
@@ -330,6 +319,7 @@ void SerialIoHandlerWin::OnIOCompleted(
// disconnection.
CancelRead(mojom::SerialReceiveError::SYSTEM_ERROR);
}
+ WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
}
} else {
NOTREACHED() << "Invalid IOContext";
diff --git a/chromium/services/device/serial/serial_io_handler_win.h b/chromium/services/device/serial/serial_io_handler_win.h
index 6a3dfea933f..db78dff38d1 100644
--- a/chromium/services/device/serial/serial_io_handler_win.h
+++ b/chromium/services/device/serial/serial_io_handler_win.h
@@ -8,9 +8,9 @@
#include <memory>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/message_loop/message_pump_for_io.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "services/device/serial/serial_io_handler.h"
@@ -18,6 +18,10 @@ namespace device {
class SerialIoHandlerWin : public SerialIoHandler,
public base::MessagePumpForIO::IOHandler {
+ public:
+ SerialIoHandlerWin(const SerialIoHandlerWin&) = delete;
+ SerialIoHandlerWin& operator=(const SerialIoHandlerWin&) = delete;
+
protected:
// SerialIoHandler implementation.
void ReadImpl() override;
@@ -58,10 +62,8 @@ class SerialIoHandlerWin : public SerialIoHandler,
// The helper lives on the UI thread and holds a weak reference back to the
// handler that owns it.
- UiThreadHelper* helper_ = nullptr;
+ raw_ptr<UiThreadHelper> helper_ = nullptr;
base::WeakPtrFactory<SerialIoHandlerWin> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerWin);
};
} // namespace device
diff --git a/chromium/services/device/serial/serial_port_impl.cc b/chromium/services/device/serial/serial_port_impl.cc
index 95844f05253..bbc0b5a71c1 100644
--- a/chromium/services/device/serial/serial_port_impl.cc
+++ b/chromium/services/device/serial/serial_port_impl.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "services/device/serial/serial_io_handler.h"
namespace device {
diff --git a/chromium/services/device/serial/serial_port_impl.h b/chromium/services/device/serial/serial_port_impl.h
index 95a4a123020..eef04fe8103 100644
--- a/chromium/services/device/serial/serial_port_impl.h
+++ b/chromium/services/device/serial/serial_port_impl.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_SERIAL_SERIAL_PORT_IMPL_H_
#define SERVICES_DEVICE_SERIAL_SERIAL_PORT_IMPL_H_
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -48,6 +47,9 @@ class SerialPortImpl : public mojom::SerialPort {
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
OpenCallback callback);
+ SerialPortImpl(const SerialPortImpl&) = delete;
+ SerialPortImpl& operator=(const SerialPortImpl&) = delete;
+
private:
SerialPortImpl(
scoped_refptr<SerialIoHandler> io_handler,
@@ -102,7 +104,6 @@ class SerialPortImpl : public mojom::SerialPort {
DrainCallback drain_callback_;
base::WeakPtrFactory<SerialPortImpl> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(SerialPortImpl);
};
} // namespace device
diff --git a/chromium/services/device/serial/serial_port_impl_unittest.cc b/chromium/services/device/serial/serial_port_impl_unittest.cc
index 35010438da7..fa74fc36911 100644
--- a/chromium/services/device/serial/serial_port_impl_unittest.cc
+++ b/chromium/services/device/serial/serial_port_impl_unittest.cc
@@ -67,11 +67,11 @@ class FakeSerialIoHandler : public SerialIoHandler {
void WriteImpl() override {}
void CancelReadImpl() override {
- QueueReadCompleted(/*bytes_read=*/0, mojom::SerialReceiveError::NONE);
+ ReadCompleted(/*bytes_read=*/0, mojom::SerialReceiveError::NONE);
}
void CancelWriteImpl() override {
- QueueWriteCompleted(/*bytes_written=*/0, mojom::SerialSendError::NONE);
+ WriteCompleted(/*bytes_written=*/0, mojom::SerialSendError::NONE);
}
bool ConfigurePortImpl() override {
diff --git a/chromium/services/device/serial/serial_port_manager_impl.cc b/chromium/services/device/serial/serial_port_manager_impl.cc
index ae5c301ba1b..022c8b367ac 100644
--- a/chromium/services/device/serial/serial_port_manager_impl.cc
+++ b/chromium/services/device/serial/serial_port_manager_impl.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.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"
@@ -35,9 +35,13 @@ SerialPortManagerImpl::SerialPortManagerImpl(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
: io_task_runner_(std::move(io_task_runner)),
- ui_task_runner_(std::move(ui_task_runner)) {}
+ ui_task_runner_(std::move(ui_task_runner)) {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
-SerialPortManagerImpl::~SerialPortManagerImpl() = default;
+SerialPortManagerImpl::~SerialPortManagerImpl() {
+ // Intentionally do not check sequence. See class comment doc for more info.
+}
void SerialPortManagerImpl::Bind(
mojo::PendingReceiver<mojom::SerialPortManager> receiver) {
@@ -47,6 +51,7 @@ void SerialPortManagerImpl::Bind(
void SerialPortManagerImpl::SetSerialEnumeratorForTesting(
std::unique_ptr<SerialDeviceEnumerator> fake_enumerator) {
DCHECK(fake_enumerator);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
enumerator_ = std::move(fake_enumerator);
observed_enumerator_.AddObservation(enumerator_.get());
}
@@ -55,16 +60,19 @@ void SerialPortManagerImpl::SetBluetoothSerialEnumeratorForTesting(
std::unique_ptr<BluetoothSerialDeviceEnumerator>
fake_bluetooth_enumerator) {
DCHECK(fake_bluetooth_enumerator);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bluetooth_enumerator_ = std::move(fake_bluetooth_enumerator);
observed_enumerator_.AddObservation(bluetooth_enumerator_.get());
}
void SerialPortManagerImpl::SetClient(
mojo::PendingRemote<mojom::SerialPortManagerClient> client) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
clients_.Add(std::move(client));
}
void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!enumerator_) {
enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
observed_enumerator_.AddObservation(enumerator_.get());
@@ -74,7 +82,7 @@ void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) {
switches::kEnableBluetoothSerialPortProfileInSerialApi)) {
if (!bluetooth_enumerator_) {
bluetooth_enumerator_ =
- std::make_unique<BluetoothSerialDeviceEnumerator>();
+ std::make_unique<BluetoothSerialDeviceEnumerator>(ui_task_runner_);
observed_enumerator_.AddObservation(bluetooth_enumerator_.get());
}
auto bluetooth_devices = bluetooth_enumerator_->GetDevices();
@@ -93,6 +101,7 @@ void SerialPortManagerImpl::OpenPort(
mojo::PendingRemote<mojom::SerialPortClient> client,
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
OpenPortCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!enumerator_) {
enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
observed_enumerator_.AddObservation(enumerator_.get());
@@ -113,7 +122,7 @@ void SerialPortManagerImpl::OpenPort(
switches::kEnableBluetoothSerialPortProfileInSerialApi)) {
if (!bluetooth_enumerator_) {
bluetooth_enumerator_ =
- std::make_unique<BluetoothSerialDeviceEnumerator>();
+ std::make_unique<BluetoothSerialDeviceEnumerator>(ui_task_runner_);
observed_enumerator_.AddObservation(bluetooth_enumerator_.get());
}
absl::optional<std::string> address =
@@ -122,8 +131,8 @@ void SerialPortManagerImpl::OpenPort(
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
- &BluetoothSerialPortImpl::Open,
- bluetooth_enumerator_->GetAdapter(), *address, std::move(options),
+ &SerialPortManagerImpl::OpenBluetoothSerialPortOnUI,
+ weak_factory_.GetWeakPtr(), *address, std::move(options),
std::move(client), std::move(watcher),
base::BindOnce(&OnPortOpened, std::move(callback),
base::SequencedTaskRunnerHandle::Get())));
@@ -134,12 +143,25 @@ void SerialPortManagerImpl::OpenPort(
std::move(callback).Run(mojo::NullRemote());
}
+void SerialPortManagerImpl::OpenBluetoothSerialPortOnUI(
+ const std::string& address,
+ mojom::SerialConnectionOptionsPtr options,
+ mojo::PendingRemote<mojom::SerialPortClient> client,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
+ BluetoothSerialPortImpl::OpenCallback callback) {
+ BluetoothSerialPortImpl::Open(bluetooth_enumerator_->GetAdapter(), address,
+ std::move(options), std::move(client),
+ std::move(watcher), std::move(callback));
+}
+
void SerialPortManagerImpl::OnPortAdded(const mojom::SerialPortInfo& port) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (auto& client : clients_)
client->OnPortAdded(port.Clone());
}
void SerialPortManagerImpl::OnPortRemoved(const mojom::SerialPortInfo& port) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (auto& client : clients_)
client->OnPortRemoved(port.Clone());
}
diff --git a/chromium/services/device/serial/serial_port_manager_impl.h b/chromium/services/device/serial/serial_port_manager_impl.h
index 492b5e26c4b..8cb5109c0ce 100644
--- a/chromium/services/device/serial/serial_port_manager_impl.h
+++ b/chromium/services/device/serial/serial_port_manager_impl.h
@@ -7,27 +7,37 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/scoped_multi_source_observation.h"
+#include "base/sequence_checker.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 "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/bluetooth_serial_port_impl.h"
#include "services/device/serial/serial_device_enumerator.h"
namespace base {
class SingleThreadTaskRunner;
class UnguessableToken;
-}
+} // namespace base
namespace device {
// TODO(leonhsl): Merge this class with SerialDeviceEnumerator if/once
// SerialDeviceEnumerator is exposed only via the Device Service.
// crbug.com/748505
+//
+// Threading notes:
+// 1. Created on the UI thread.
+// 2. Used on the UI thread runner (macOS only), otherwise on a blocking task
+// runner.
+// 3. Deleted on the same runner on which it is used *except* sometimes
+// during shutdown when the runner threadpool is already shutdown.
+// See crbug.com/1263149#c20 for details.
class SerialPortManagerImpl : public mojom::SerialPortManager,
public SerialDeviceEnumerator::Observer {
public:
@@ -63,6 +73,13 @@ class SerialPortManagerImpl : public mojom::SerialPortManager,
void OnPortAdded(const mojom::SerialPortInfo& port) override;
void OnPortRemoved(const mojom::SerialPortInfo& port) override;
+ void OpenBluetoothSerialPortOnUI(
+ const std::string& address,
+ mojom::SerialConnectionOptionsPtr options,
+ mojo::PendingRemote<mojom::SerialPortClient> client,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
+ BluetoothSerialPortImpl::OpenCallback callback);
+
std::unique_ptr<SerialDeviceEnumerator> enumerator_;
std::unique_ptr<BluetoothSerialDeviceEnumerator> bluetooth_enumerator_;
base::ScopedMultiSourceObservation<SerialDeviceEnumerator,
@@ -74,6 +91,9 @@ class SerialPortManagerImpl : public mojom::SerialPortManager,
mojo::ReceiverSet<SerialPortManager> receivers_;
mojo::RemoteSet<mojom::SerialPortManagerClient> clients_;
+ // See threading notes above for guidelines for checking sequence.
+ SEQUENCE_CHECKER(sequence_checker_);
+ base::WeakPtrFactory<SerialPortManagerImpl> weak_factory_{this};
};
} // namespace device
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 8e45fd8e247..b8c0f14af96 100644
--- a/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
+++ b/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/task/post_task.h"
#include "base/test/bind.h"
#include "base/test/gmock_callback_support.h"
@@ -69,6 +69,15 @@ class MockSerialPortManagerClient : public mojom::SerialPortManagerClient {
mojo::Receiver<mojom::SerialPortManagerClient> receiver_{this};
};
+class TestingBluetoothAdapter : public device::MockBluetoothAdapter {
+ public:
+ bool IsInitialized() const override { return false; }
+ MOCK_METHOD1(Initialize, void(base::OnceClosure callback));
+
+ private:
+ ~TestingBluetoothAdapter() override = default;
+};
+
} // namespace
class SerialPortManagerImplTest : public DeviceServiceTestBase {
@@ -90,6 +99,17 @@ class SerialPortManagerImplTest : public DeviceServiceTestBase {
~SerialPortManagerImplTest() override = default;
+ void TearDown() override {
+ // Resetting `manager_` will delete the BluetoothSerialDeviceEnumerator
+ // which will enqueue the deletion of a `SequenceBound` helper.
+ manager_.reset();
+ // Wait for any `SequenceBound` objects have been destroyed
+ // to avoid tripping leak detection.
+ base::RunLoop run_loop;
+ adapter_task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
// Since not all functions need to use a MockBluetoothAdapter, this function
// is called at the beginning of test cases that do require a
// MockBluetoothAdapter.
@@ -108,11 +128,16 @@ class SerialPortManagerImplTest : public DeviceServiceTestBase {
adapter_->AddMockDevice(std::move(mock_device));
auto bluetooth_enumerator =
- std::make_unique<BluetoothSerialDeviceEnumerator>();
+ std::make_unique<BluetoothSerialDeviceEnumerator>(
+ adapter_task_runner());
bluetooth_enumerator_ = bluetooth_enumerator.get();
manager_->SetBluetoothSerialEnumeratorForTesting(
std::move(bluetooth_enumerator));
+
+ base::RunLoop run_loop;
+ bluetooth_enumerator_->OnGotAdapterForTesting(run_loop.QuitClosure());
+ run_loop.Run();
}
void SetupBluetoothEnumeratorWithExpectations() {
@@ -137,16 +162,25 @@ class SerialPortManagerImplTest : public DeviceServiceTestBase {
.WillOnce(RunOnceCallback<1>(mock_socket_));
auto bluetooth_enumerator =
- std::make_unique<BluetoothSerialDeviceEnumerator>();
+ std::make_unique<BluetoothSerialDeviceEnumerator>(
+ adapter_task_runner());
bluetooth_enumerator_ = bluetooth_enumerator.get();
manager_->SetBluetoothSerialEnumeratorForTesting(
std::move(bluetooth_enumerator));
+
+ base::RunLoop run_loop;
+ bluetooth_enumerator_->OnGotAdapterForTesting(run_loop.QuitClosure());
+ run_loop.Run();
}
protected:
- FakeSerialEnumerator* enumerator_;
- BluetoothSerialDeviceEnumerator* bluetooth_enumerator_;
+ scoped_refptr<base::SingleThreadTaskRunner> adapter_task_runner() {
+ return base::ThreadTaskRunnerHandle::Get();
+ }
+
+ raw_ptr<FakeSerialEnumerator> enumerator_;
+ raw_ptr<BluetoothSerialDeviceEnumerator> bluetooth_enumerator_;
scoped_refptr<MockBluetoothAdapter> adapter_ =
base::MakeRefCounted<MockBluetoothAdapter>();
scoped_refptr<MockBluetoothSocket> mock_socket_ =
@@ -171,9 +205,7 @@ TEST_F(SerialPortManagerImplTest, SimpleEnumerationTest) {
base::RunLoop loop;
port_manager->GetDevices(base::BindLambdaForTesting(
- [&](std::vector<mojom::SerialPortInfoPtr> results) {
- loop.Quit();
- }));
+ [&](std::vector<mojom::SerialPortInfoPtr> results) { loop.Quit(); }));
loop.Run();
}
@@ -340,8 +372,7 @@ TEST_F(SerialPortManagerImplTest, BluetoothPortRemovedAndAdded) {
}
ASSERT_FALSE(port1_token.is_empty());
- bluetooth_enumerator_->DeviceRemoved(
- adapter_.get(), adapter_->RemoveMockDevice(kDeviceAddress).get());
+ bluetooth_enumerator_->PortRemoved(kDeviceAddress);
{
base::RunLoop run_loop;
EXPECT_CALL(client, OnPortRemoved(_))
@@ -361,7 +392,7 @@ TEST_F(SerialPortManagerImplTest, BluetoothPortRemovedAndAdded) {
MockBluetoothDevice* mock_device_ptr = mock_device.get();
adapter_->AddMockDevice(std::move(mock_device));
- bluetooth_enumerator_->DeviceAdded(adapter_.get(), mock_device_ptr);
+ bluetooth_enumerator_->DeviceAddedForTesting(adapter_.get(), mock_device_ptr);
{
base::RunLoop run_loop;
EXPECT_CALL(client, OnPortAdded(_))
@@ -375,4 +406,37 @@ TEST_F(SerialPortManagerImplTest, BluetoothPortRemovedAndAdded) {
}
}
+TEST_F(SerialPortManagerImplTest,
+ BluetoothSerialDeviceEnumerator_DeleteBeforeAdapterInit) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi);
+
+ auto adapter = base::MakeRefCounted<TestingBluetoothAdapter>();
+ BluetoothAdapterFactory::SetAdapterForTesting(adapter);
+
+ // BluetoothAdapterFactory does not initialize the test adapter. Instead it
+ // holds on to the GetAdapter callback until adapter initialization is
+ // complete.
+ EXPECT_CALL(*adapter, Initialize).Times(0);
+
+ // Create the enumerator, which calls GetAdapter(), which is blocked waiting
+ // on adapter initialization.
+ auto enumerator =
+ std::make_unique<BluetoothSerialDeviceEnumerator>(adapter_task_runner());
+
+ // Delete the enumerator before adapter initialization completes.
+ // Explicitly delete its helper. This workaround is needed because this test
+ // does not mock out the BluetoothAdapterFactory singleton, which (on Linux)
+ // calls bluez::BluezDBusManager::Get() - failing a CHECK.
+ enumerator->SynchronouslyResetHelperForTesting();
+ enumerator.reset();
+
+ // Directly call the adapter initialization callback, which calls any saved
+ // GetAdapter() callbacks - i.e. the one made by the
+ // BluetoothSerialDeviceEnumerator constructor.
+ BluetoothAdapterFactory::Get()->AdapterInitialized();
+
+ // We didn't crash? yay \o/ test passed.
+}
+
} // namespace device
diff --git a/chromium/services/device/time_zone_monitor/BUILD.gn b/chromium/services/device/time_zone_monitor/BUILD.gn
index c56a9bb4f9e..67c6fdc1fbb 100644
--- a/chromium/services/device/time_zone_monitor/BUILD.gn
+++ b/chromium/services/device/time_zone_monitor/BUILD.gn
@@ -46,7 +46,7 @@ source_set("time_zone_monitor") {
if (is_chromeos_ash) {
sources += [ "time_zone_monitor_chromeos.cc" ]
- deps += [ "//chromeos/settings" ]
+ deps += [ "//ash/components/settings" ]
}
if (is_mac) {
diff --git a/chromium/services/device/time_zone_monitor/DEPS b/chromium/services/device/time_zone_monitor/DEPS
index 2ebcba38758..05b049975fc 100644
--- a/chromium/services/device/time_zone_monitor/DEPS
+++ b/chromium/services/device/time_zone_monitor/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+chromeos/settings",
+ "+ash/components/settings",
"+mojo/public/cpp/bindings",
"+ui/gfx/win",
] \ No newline at end of file
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc
index 91708b41f1b..7ff4040cb61 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc
@@ -9,7 +9,7 @@
#include "base/android/jni_android.h"
#include "base/android/timezone_utils.h" // nogncheck
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "services/device/time_zone_monitor/time_zone_monitor_jni_headers/TimeZoneMonitor_jni.h"
#include "third_party/icu/source/common/unicode/unistr.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_android.h b/chromium/services/device/time_zone_monitor/time_zone_monitor_android.h
index d29822c3836..2d711c1973c 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_android.h
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_android.h
@@ -10,7 +10,6 @@
#include <jni.h>
#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
namespace device {
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_chromeos.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_chromeos.cc
index 5c57d73c6b7..2254e3e604b 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_chromeos.cc
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_chromeos.cc
@@ -6,28 +6,26 @@
#include <memory>
-#include "base/macros.h"
-#include "chromeos/settings/timezone_settings.h"
+#include "ash/components/settings/timezone_settings.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace device {
-class TimeZoneMonitorChromeOS
- : public TimeZoneMonitor,
- public chromeos::system::TimezoneSettings::Observer {
+class TimeZoneMonitorChromeOS : public TimeZoneMonitor,
+ public ash::system::TimezoneSettings::Observer {
public:
TimeZoneMonitorChromeOS() : TimeZoneMonitor() {
- chromeos::system::TimezoneSettings::GetInstance()->AddObserver(this);
+ ash::system::TimezoneSettings::GetInstance()->AddObserver(this);
}
TimeZoneMonitorChromeOS(const TimeZoneMonitorChromeOS&) = delete;
TimeZoneMonitorChromeOS& operator=(const TimeZoneMonitorChromeOS&) = delete;
~TimeZoneMonitorChromeOS() override {
- chromeos::system::TimezoneSettings::GetInstance()->RemoveObserver(this);
+ ash::system::TimezoneSettings::GetInstance()->RemoveObserver(this);
}
- // chromeos::system::TimezoneSettings::Observer implementation.
+ // ash::system::TimezoneSettings::Observer implementation.
void TimezoneChanged(const icu::TimeZone& time_zone) override {
// ICU's default time zone is already set to a new zone. No need to redetect
// it with detectHostTimeZone() or to update ICU.
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc
index 91106e41896..3f04c8c4580 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc
@@ -15,7 +15,7 @@
#include "base/files/file_path.h"
#include "base/files/file_path_watcher.h"
#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -85,6 +85,9 @@ class TimeZoneMonitorLinuxImpl
return impl;
}
+ TimeZoneMonitorLinuxImpl(const TimeZoneMonitorLinuxImpl&) = delete;
+ TimeZoneMonitorLinuxImpl& operator=(const TimeZoneMonitorLinuxImpl&) = delete;
+
void StopWatching() {
DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
owner_ = nullptr;
@@ -163,8 +166,6 @@ class TimeZoneMonitorLinuxImpl
scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
TimeZoneMonitorLinux* owner_;
-
- DISALLOW_COPY_AND_ASSIGN(TimeZoneMonitorLinuxImpl);
};
} // namespace
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_mac.mm b/chromium/services/device/time_zone_monitor/time_zone_monitor_mac.mm
index 8bff85f0d06..fa6ed632dec 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_mac.mm
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_mac.mm
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/macros.h"
#include "services/device/time_zone_monitor/time_zone_monitor.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc
index ef845502eed..91f4720c063 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/services/device/usb/mock_usb_device_handle.cc b/chromium/services/device/usb/mock_usb_device_handle.cc
index 321e59b4ea5..c2e1430a7cf 100644
--- a/chromium/services/device/usb/mock_usb_device_handle.cc
+++ b/chromium/services/device/usb/mock_usb_device_handle.cc
@@ -11,7 +11,7 @@ namespace device {
MockUsbDeviceHandle::MockUsbDeviceHandle(UsbDevice* device) : device_(device) {}
scoped_refptr<UsbDevice> MockUsbDeviceHandle::GetDevice() const {
- return device_;
+ return device_.get();
}
MockUsbDeviceHandle::~MockUsbDeviceHandle() = default;
diff --git a/chromium/services/device/usb/mock_usb_device_handle.h b/chromium/services/device/usb/mock_usb_device_handle.h
index e5f4dbdabee..c97f1d1f911 100644
--- a/chromium/services/device/usb/mock_usb_device_handle.h
+++ b/chromium/services/device/usb/mock_usb_device_handle.h
@@ -10,6 +10,7 @@
#include <vector>
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "services/device/usb/usb_device_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -142,7 +143,7 @@ class MockUsbDeviceHandle : public UsbDeviceHandle {
~MockUsbDeviceHandle() override;
private:
- UsbDevice* device_;
+ raw_ptr<UsbDevice> device_;
};
} // namespace device
diff --git a/chromium/services/device/usb/mojo/device_impl.h b/chromium/services/device/usb/mojo/device_impl.h
index 1a5c49e9cd9..3b59f2529c0 100644
--- a/chromium/services/device/usb/mojo/device_impl.h
+++ b/chromium/services/device/usb/mojo/device_impl.h
@@ -11,7 +11,6 @@
#include "base/callback_forward.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
diff --git a/chromium/services/device/usb/mojo/device_impl_unittest.cc b/chromium/services/device/usb/mojo/device_impl_unittest.cc
index 7dc6b570696..1bff1cdb4bc 100644
--- a/chromium/services/device/usb/mojo/device_impl_unittest.cc
+++ b/chromium/services/device/usb/mojo/device_impl_unittest.cc
@@ -20,7 +20,6 @@
#include "base/containers/contains.h"
#include "base/containers/queue.h"
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
@@ -56,6 +55,9 @@ class ConfigBuilder {
explicit ConfigBuilder(uint8_t value)
: config_(BuildUsbConfigurationInfoPtr(value, false, false, 0)) {}
+ ConfigBuilder(const ConfigBuilder&) = delete;
+ ConfigBuilder& operator=(const ConfigBuilder&) = delete;
+
ConfigBuilder& AddInterface(uint8_t interface_number,
uint8_t alternate_setting,
uint8_t class_code,
@@ -71,8 +73,6 @@ class ConfigBuilder {
private:
mojom::UsbConfigurationInfoPtr config_;
-
- DISALLOW_COPY_AND_ASSIGN(ConfigBuilder);
};
void ExpectOpenAndThen(mojom::UsbOpenDeviceError expected,
diff --git a/chromium/services/device/usb/mojo/device_manager_impl.h b/chromium/services/device/usb/mojo/device_manager_impl.h
index b07848350ce..4781e189038 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl.h
+++ b/chromium/services/device/usb/mojo/device_manager_impl.h
@@ -12,7 +12,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
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 f759b21fad7..3bc05421039 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl_unittest.cc
+++ b/chromium/services/device/usb/mojo/device_manager_impl_unittest.cc
@@ -13,7 +13,7 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -60,7 +60,7 @@ class USBDeviceManagerImplTest : public testing::Test {
~USBDeviceManagerImplTest() override = default;
protected:
- MockUsbService* mock_usb_service_;
+ raw_ptr<MockUsbService> mock_usb_service_;
std::unique_ptr<DeviceManagerImpl> device_manager_instance_;
base::test::SingleThreadTaskEnvironment task_environment_;
};
diff --git a/chromium/services/device/usb/mojo/device_manager_test.cc b/chromium/services/device/usb/mojo/device_manager_test.cc
index 079cb375c69..9f89530e5d8 100644
--- a/chromium/services/device/usb/mojo/device_manager_test.cc
+++ b/chromium/services/device/usb/mojo/device_manager_test.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "services/device/usb/usb_device.h"
#include "services/device/usb/usb_device_handle.h"
@@ -23,13 +22,14 @@ class TestUsbDevice : public UsbDevice {
const std::string& serial_number,
const GURL& landing_page);
+ TestUsbDevice(const TestUsbDevice&) = delete;
+ TestUsbDevice& operator=(const TestUsbDevice&) = delete;
+
// device::UsbDevice overrides:
void Open(OpenCallback callback) override;
private:
~TestUsbDevice() override;
-
- DISALLOW_COPY_AND_ASSIGN(TestUsbDevice);
};
TestUsbDevice::TestUsbDevice(const std::string& name,
diff --git a/chromium/services/device/usb/mojo/device_manager_test.h b/chromium/services/device/usb/mojo/device_manager_test.h
index 44e9554e228..eefd19444e7 100644
--- a/chromium/services/device/usb/mojo/device_manager_test.h
+++ b/chromium/services/device/usb/mojo/device_manager_test.h
@@ -7,7 +7,7 @@
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/device/public/mojom/usb_manager_test.mojom.h"
@@ -43,7 +43,7 @@ class DeviceManagerTest : public mojom::UsbDeviceManagerTest {
private:
mojo::ReceiverSet<mojom::UsbDeviceManagerTest> receivers_;
- UsbService* usb_service_;
+ raw_ptr<UsbService> usb_service_;
};
} // namespace usb
diff --git a/chromium/services/device/usb/scoped_libusb_device_handle.h b/chromium/services/device/usb/scoped_libusb_device_handle.h
index bd5ba047d5f..12fb4d23b3d 100644
--- a/chromium/services/device/usb/scoped_libusb_device_handle.h
+++ b/chromium/services/device/usb/scoped_libusb_device_handle.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_USB_SCOPED_LIBUSB_DEVICE_HANDLE_H_
#define SERVICES_DEVICE_USB_SCOPED_LIBUSB_DEVICE_HANDLE_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
struct libusb_device_handle;
diff --git a/chromium/services/device/usb/scoped_libusb_device_ref.h b/chromium/services/device/usb/scoped_libusb_device_ref.h
index 2d1afc551e5..9cd3427f60a 100644
--- a/chromium/services/device/usb/scoped_libusb_device_ref.h
+++ b/chromium/services/device/usb/scoped_libusb_device_ref.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
#define SERVICES_DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
struct libusb_device;
diff --git a/chromium/services/device/usb/scoped_winusb_handle.h b/chromium/services/device/usb/scoped_winusb_handle.h
index 94e1fcfeea4..47e5a10a2f2 100644
--- a/chromium/services/device/usb/scoped_winusb_handle.h
+++ b/chromium/services/device/usb/scoped_winusb_handle.h
@@ -17,6 +17,10 @@ class WinUsbHandleTraits {
public:
using Handle = WINUSB_INTERFACE_HANDLE;
+ WinUsbHandleTraits() = delete;
+ WinUsbHandleTraits(const WinUsbHandleTraits&) = delete;
+ WinUsbHandleTraits& operator=(const WinUsbHandleTraits&) = delete;
+
static bool CloseHandle(Handle handle);
static bool IsHandleValid(Handle handle) {
@@ -24,9 +28,6 @@ class WinUsbHandleTraits {
}
static Handle NullHandle() { return nullptr; }
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(WinUsbHandleTraits);
};
using ScopedWinUsbHandle =
diff --git a/chromium/services/device/usb/usb_context.cc b/chromium/services/device/usb/usb_context.cc
index 9b6a74b31b2..ccf1bf807e7 100644
--- a/chromium/services/device/usb/usb_context.cc
+++ b/chromium/services/device/usb/usb_context.cc
@@ -8,7 +8,6 @@
#include "base/atomicops.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread_restrictions.h"
#include "services/device/usb/usb_error.h"
diff --git a/chromium/services/device/usb/usb_context.h b/chromium/services/device/usb/usb_context.h
index 8e10778fe6d..027d63021c0 100644
--- a/chromium/services/device/usb/usb_context.h
+++ b/chromium/services/device/usb/usb_context.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
@@ -25,6 +24,9 @@ class UsbContext : public base::RefCountedThreadSafe<UsbContext> {
public:
explicit UsbContext(PlatformUsbContext context);
+ UsbContext(const UsbContext&) = delete;
+ UsbContext& operator=(const UsbContext&) = delete;
+
PlatformUsbContext context() const { return context_; }
protected:
@@ -37,8 +39,6 @@ class UsbContext : public base::RefCountedThreadSafe<UsbContext> {
PlatformUsbContext context_;
std::unique_ptr<UsbEventHandler> event_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(UsbContext);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_context_unittest.cc b/chromium/services/device/usb/usb_context_unittest.cc
index 2b7026a21cb..39fcafcafe7 100644
--- a/chromium/services/device/usb/usb_context_unittest.cc
+++ b/chromium/services/device/usb/usb_context_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "services/device/usb/usb_context.h"
-#include "base/macros.h"
#include "base/threading/platform_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libusb/src/libusb/libusb.h"
@@ -19,9 +18,11 @@ class UsbContextTest : public testing::Test {
explicit UsbContextForTest(PlatformUsbContext context)
: UsbContext(context) {}
+ UsbContextForTest(const UsbContextForTest&) = delete;
+ UsbContextForTest& operator=(const UsbContextForTest&) = delete;
+
private:
~UsbContextForTest() override {}
- DISALLOW_COPY_AND_ASSIGN(UsbContextForTest);
};
};
diff --git a/chromium/services/device/usb/usb_descriptors.cc b/chromium/services/device/usb/usb_descriptors.cc
index 498e8550689..7ce08843042 100644
--- a/chromium/services/device/usb/usb_descriptors.cc
+++ b/chromium/services/device/usb/usb_descriptors.cc
@@ -126,7 +126,8 @@ void OnReadConfigDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle,
UsbTransferStatus status,
scoped_refptr<base::RefCountedBytes> header,
size_t length) {
- if (status == UsbTransferStatus::COMPLETED && length == 4) {
+ if (status == UsbTransferStatus::COMPLETED &&
+ length == kConfigurationDescriptorLength) {
const uint8_t* data = header->front();
uint16_t total_length = data[2] | data[3] << 8;
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(total_length);
@@ -174,7 +175,8 @@ void OnReadDeviceDescriptor(
base::BindOnce(OnDoneReadingConfigDescriptors, device_handle,
std::move(desc), std::move(callback)));
for (uint8_t i = 0; i < num_configurations; ++i) {
- auto header = base::MakeRefCounted<base::RefCountedBytes>(4);
+ auto header = base::MakeRefCounted<base::RefCountedBytes>(
+ kConfigurationDescriptorLength);
device_handle->ControlTransfer(
UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
diff --git a/chromium/services/device/usb/usb_device.h b/chromium/services/device/usb/usb_device.h
index b2b5f653766..c1b91b8f382 100644
--- a/chromium/services/device/usb/usb_device.h
+++ b/chromium/services/device/usb/usb_device.h
@@ -13,7 +13,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/strings/string_util.h"
@@ -46,6 +45,9 @@ class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> {
virtual void OnDeviceRemoved(scoped_refptr<UsbDevice> device);
};
+ UsbDevice(const UsbDevice&) = delete;
+ UsbDevice& operator=(const UsbDevice&) = delete;
+
const mojom::UsbDeviceInfo& device_info() const { return *device_info_; }
// A unique identifier which remains stable for the lifetime of this device
@@ -161,8 +163,6 @@ class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> {
std::list<UsbDeviceHandle*> handles_;
base::ObserverList<Observer, true>::Unchecked observer_list_;
-
- DISALLOW_COPY_AND_ASSIGN(UsbDevice);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_android.h b/chromium/services/device/usb/usb_device_android.h
index 7c59918357f..0053a32c591 100644
--- a/chromium/services/device/usb/usb_device_android.h
+++ b/chromium/services/device/usb/usb_device_android.h
@@ -5,6 +5,10 @@
#ifndef SERVICES_DEVICE_USB_USB_DEVICE_ANDROID_H_
#define SERVICES_DEVICE_USB_USB_DEVICE_ANDROID_H_
+#include <list>
+#include <memory>
+#include <string>
+
#include "base/android/scoped_java_ref.h"
#include "base/memory/weak_ptr.h"
#include "services/device/usb/usb_device.h"
diff --git a/chromium/services/device/usb/usb_device_handle.h b/chromium/services/device/usb/usb_device_handle.h
index e5ccbca7498..539c10dea9c 100644
--- a/chromium/services/device/usb/usb_device_handle.h
+++ b/chromium/services/device/usb/usb_device_handle.h
@@ -12,7 +12,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/usb/usb_descriptors.h"
@@ -37,6 +36,9 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
scoped_refptr<base::RefCountedBytes>,
std::vector<mojom::UsbIsochronousPacketPtr> packets)>;
+ UsbDeviceHandle(const UsbDeviceHandle&) = delete;
+ UsbDeviceHandle& operator=(const UsbDeviceHandle&) = delete;
+
virtual scoped_refptr<UsbDevice> GetDevice() const = 0;
// Notifies UsbDevice to drop the reference of this object; cancels all the
@@ -100,9 +102,6 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
UsbDeviceHandle();
virtual ~UsbDeviceHandle();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_handle_android.cc b/chromium/services/device/usb/usb_device_handle_android.cc
index fa9eeb62250..417aeef038e 100644
--- a/chromium/services/device/usb/usb_device_handle_android.cc
+++ b/chromium/services/device/usb/usb_device_handle_android.cc
@@ -40,10 +40,8 @@ UsbDeviceHandleAndroid::UsbDeviceHandleAndroid(
UsbDeviceHandleAndroid::~UsbDeviceHandleAndroid() {}
-void UsbDeviceHandleAndroid::CloseBlocking() {
- ReleaseFileDescriptor();
- task_runner()->PostTask(
- FROM_HERE,
+void UsbDeviceHandleAndroid::FinishClose() {
+ ReleaseFileDescriptor(
base::BindOnce(&UsbDeviceHandleAndroid::CloseConnection, this));
}
diff --git a/chromium/services/device/usb/usb_device_handle_android.h b/chromium/services/device/usb/usb_device_handle_android.h
index 01430022b37..ee863ff4ba4 100644
--- a/chromium/services/device/usb/usb_device_handle_android.h
+++ b/chromium/services/device/usb/usb_device_handle_android.h
@@ -30,7 +30,7 @@ class UsbDeviceHandleAndroid : public UsbDeviceHandleUsbfs {
~UsbDeviceHandleAndroid() override;
// UsbDeviceHandleUsbfs:
- void CloseBlocking() override;
+ void FinishClose() override;
void CloseConnection();
diff --git a/chromium/services/device/usb/usb_device_handle_impl.cc b/chromium/services/device/usb/usb_device_handle_impl.cc
index cd42f20a48a..6301bab9e2b 100644
--- a/chromium/services/device/usb/usb_device_handle_impl.cc
+++ b/chromium/services/device/usb/usb_device_handle_impl.cc
@@ -14,10 +14,9 @@
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/sequence_checker.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/device_event_log/device_event_log.h"
@@ -122,6 +121,9 @@ class UsbDeviceHandleImpl::InterfaceClaimer
int interface_number,
scoped_refptr<base::SequencedTaskRunner> task_runner);
+ InterfaceClaimer(const InterfaceClaimer&) = delete;
+ InterfaceClaimer& operator=(const InterfaceClaimer&) = delete;
+
int interface_number() const { return interface_number_; }
int alternate_setting() const { return alternate_setting_; }
void set_alternate_setting(const int alternate_setting) {
@@ -142,8 +144,6 @@ class UsbDeviceHandleImpl::InterfaceClaimer
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
ResultCallback release_callback_;
base::SequenceChecker sequence_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
};
UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
diff --git a/chromium/services/device/usb/usb_device_handle_impl.h b/chromium/services/device/usb/usb_device_handle_impl.h
index c8e8c608261..17eb4029dfe 100644
--- a/chromium/services/device/usb/usb_device_handle_impl.h
+++ b/chromium/services/device/usb/usb_device_handle_impl.h
@@ -14,7 +14,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "services/device/public/mojom/usb_device.mojom.h"
@@ -42,6 +41,9 @@ typedef libusb_transfer* PlatformUsbTransferHandle;
// UsbDeviceHandle class provides basic I/O related functionalities.
class UsbDeviceHandleImpl : public UsbDeviceHandle {
public:
+ UsbDeviceHandleImpl(const UsbDeviceHandleImpl&) = delete;
+ UsbDeviceHandleImpl& operator=(const UsbDeviceHandleImpl&) = delete;
+
scoped_refptr<UsbDevice> GetDevice() const override;
void Close() override;
void SetConfiguration(int configuration_value,
@@ -159,8 +161,6 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle {
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandleImpl);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.cc b/chromium/services/device/usb/usb_device_handle_usbfs.cc
index b08622642d4..8bcee9b6ef1 100644
--- a/chromium/services/device/usb/usb_device_handle_usbfs.cc
+++ b/chromium/services/device/usb/usb_device_handle_usbfs.cc
@@ -16,6 +16,7 @@
#include "base/cancelable_callback.h"
#include "base/containers/contains.h"
#include "base/files/file_descriptor_watcher_posix.h"
+#include "base/ignore_result.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/numerics/checked_math.h"
@@ -142,7 +143,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
BlockingTaskRunnerHelper(
base::ScopedFD fd,
base::ScopedFD lifeline_fd,
- scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
+ base::WeakPtr<UsbDeviceHandleUsbfs> device_handle,
scoped_refptr<base::SequencedTaskRunner> task_runner);
BlockingTaskRunnerHelper(const BlockingTaskRunnerHelper&) = delete;
@@ -153,13 +154,11 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
void Start();
void ReleaseFileDescriptor();
- void SetConfiguration(int configuration_value, ResultCallback callback);
- void ReleaseInterface(int interface_number, ResultCallback callback);
- void SetInterface(int interface_number,
- int alternate_setting,
- ResultCallback callback);
- void ResetDevice(ResultCallback callback);
- void ClearHalt(uint8_t endpoint_address, ResultCallback callback);
+ bool SetConfiguration(int configuration_value);
+ bool ReleaseInterface(int interface_number);
+ bool SetInterface(int interface_number, int alternate_setting);
+ bool ResetDevice();
+ bool ClearHalt(uint8_t endpoint_address);
void DiscardUrb(Transfer* transfer);
private:
@@ -168,10 +167,10 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
base::ScopedFD fd_;
base::ScopedFD lifeline_fd_;
- scoped_refptr<UsbDeviceHandleUsbfs> device_handle_;
+ base::WeakPtr<UsbDeviceHandleUsbfs> device_handle_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
- base::SequenceChecker sequence_checker_;
+ SEQUENCE_CHECKER(sequence_checker_);
};
struct UsbDeviceHandleUsbfs::Transfer final {
@@ -180,6 +179,10 @@ struct UsbDeviceHandleUsbfs::Transfer final {
TransferCallback callback);
Transfer(scoped_refptr<base::RefCountedBytes> buffer,
IsochronousTransferCallback callback);
+
+ Transfer(const Transfer&) = delete;
+ Transfer& operator=(const Transfer&) = delete;
+
~Transfer();
void* operator new(std::size_t size, size_t number_of_iso_packets);
@@ -200,9 +203,6 @@ struct UsbDeviceHandleUsbfs::Transfer final {
TransferCallback callback;
IsochronousTransferCallback isoc_callback;
- private:
- DISALLOW_COPY_AND_ASSIGN(Transfer);
-
public:
// The |urb| field must be the last in the struct so that the extra space
// allocated by the overridden new function above extends the length of its
@@ -213,21 +213,12 @@ struct UsbDeviceHandleUsbfs::Transfer final {
UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::BlockingTaskRunnerHelper(
base::ScopedFD fd,
base::ScopedFD lifeline_fd,
- scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
+ base::WeakPtr<UsbDeviceHandleUsbfs> device_handle,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: fd_(std::move(fd)),
lifeline_fd_(std::move(lifeline_fd)),
device_handle_(std::move(device_handle)),
- task_runner_(std::move(task_runner)) {}
-
-UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::~BlockingTaskRunnerHelper() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-}
-
-void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::Start() {
- sequence_checker_.DetachFromSequence();
- DCHECK(sequence_checker_.CalledOnValidSequence());
-
+ task_runner_(std::move(task_runner)) {
// Linux indicates that URBs are available to reap by marking the file
// descriptor writable.
watch_controller_ = base::FileDescriptorWatcher::WatchWritable(
@@ -236,34 +227,36 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::Start() {
base::Unretained(this)));
}
+UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::~BlockingTaskRunnerHelper() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ReleaseFileDescriptor() {
// This method intentionally leaks the file descriptor.
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
watch_controller_.reset();
ignore_result(fd_.release());
}
-void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetConfiguration(
- int configuration_value,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+bool UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetConfiguration(
+ int configuration_value) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
int rc = HANDLE_EINTR(
ioctl(fd_.get(), USBDEVFS_SETCONFIGURATION, &configuration_value));
- if (rc)
+ if (rc) {
USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value;
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
- device_handle_, configuration_value, rc == 0,
- std::move(callback)));
+ return false;
+ }
+
+ return true;
}
-void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ReleaseInterface(
- int interface_number,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+bool UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ReleaseInterface(
+ int interface_number) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -271,21 +264,16 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ReleaseInterface(
ioctl(fd_.get(), USBDEVFS_RELEASEINTERFACE, &interface_number));
if (rc) {
USB_PLOG(DEBUG) << "Failed to release interface " << interface_number;
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), false));
- } else {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
- device_handle_, interface_number, std::move(callback)));
+ return false;
}
+
+ return true;
}
-void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetInterface(
+bool UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetInterface(
int interface_number,
- int alternate_setting,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ int alternate_setting) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
usbdevfs_setinterface cmd = {0};
cmd.interface = interface_number;
@@ -297,18 +285,14 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetInterface(
if (rc) {
USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
<< " to alternate setting " << alternate_setting;
+ return false;
}
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete,
- device_handle_, interface_number, alternate_setting, rc == 0,
- std::move(callback)));
+
+ return true;
}
-void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ResetDevice(
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+bool UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ResetDevice() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -316,16 +300,17 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ResetDevice(
// interfaces after a reset. We should probably do this too or document that
// callers have to call ClaimInterface as well.
int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_RESET, nullptr));
- if (rc)
+ if (rc) {
USB_PLOG(DEBUG) << "Failed to reset the device";
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), rc == 0));
+ return false;
+ }
+
+ return true;
}
-void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ClearHalt(
- uint8_t endpoint_address,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+bool UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ClearHalt(
+ uint8_t endpoint_address) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
int tmp_endpoint = endpoint_address;
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
@@ -334,27 +319,24 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ClearHalt(
if (rc) {
USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint "
<< static_cast<int>(endpoint_address);
+ return false;
}
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), rc == 0));
+
+ return true;
}
void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::DiscardUrb(
Transfer* transfer) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb));
-
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(&UsbDeviceHandleUsbfs::UrbDiscarded,
- device_handle_, transfer));
}
void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::
OnFileCanWriteWithoutBlocking() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const size_t MAX_URBS_PER_EVENT = 10;
std::vector<usbdevfs_urb*> urbs;
@@ -440,28 +422,24 @@ UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs(
base::ScopedFD fd,
base::ScopedFD lifeline_fd,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
- : device_(device),
+ : device_(std::move(device)),
fd_(fd.get()),
- task_runner_(base::ThreadTaskRunnerHandle::Get()),
- blocking_task_runner_(blocking_task_runner) {
+ task_runner_(base::ThreadTaskRunnerHandle::Get()) {
DCHECK(device_);
DCHECK(fd.is_valid());
- DCHECK(blocking_task_runner_);
- helper_ = std::make_unique<BlockingTaskRunnerHelper>(
- std::move(fd), std::move(lifeline_fd), this, task_runner_);
- blocking_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::Start,
- base::Unretained(helper_.get())));
+ helper_ = base::SequenceBound<BlockingTaskRunnerHelper>(
+ std::move(blocking_task_runner), std::move(fd), std::move(lifeline_fd),
+ weak_factory_.GetWeakPtr(), task_runner_);
}
scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return device_;
}
void UsbDeviceHandleUsbfs::Close() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_)
return; // Already closed.
@@ -472,8 +450,8 @@ void UsbDeviceHandleUsbfs::Close() {
CancelTransfer(transfer.get(), UsbTransferStatus::CANCELLED);
// On the |task_runner_| thread check |device_| to see if the handle is
- // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to
- // see if the handle is closed.
+ // closed. In |helper_| thread check |fd_.is_valid()| to see if the handle is
+ // closed.
device_->HandleClosed(this);
device_ = nullptr;
// The device is no longer attached so we don't have any endpoints either.
@@ -481,15 +459,12 @@ void UsbDeviceHandleUsbfs::Close() {
// The destruction of the |helper_| below will close the lifeline pipe if it
// exists and re-attach kernel driver.
-
- // Releases |helper_|.
- blocking_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::CloseBlocking, this));
+ FinishClose();
}
void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value,
ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), false));
@@ -499,17 +474,15 @@ void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value,
// USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request
// to the device so it must be performed on a thread where it is okay to
// block.
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetConfiguration,
- base::Unretained(helper_.get()), configuration_value,
- std::move(callback)));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::SetConfiguration)
+ .WithArgs(configuration_value)
+ .Then(base::BindOnce(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
+ this, configuration_value, std::move(callback)));
}
void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number,
ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), false));
@@ -537,7 +510,7 @@ void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number,
void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), false));
@@ -547,19 +520,17 @@ void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
// USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the
// device to restore alternate setting 0 so it must be performed on a thread
// where it is okay to block.
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ReleaseInterface,
- base::Unretained(helper_.get()), interface_number,
- std::move(callback)));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::ReleaseInterface)
+ .WithArgs(interface_number)
+ .Then(base::BindOnce(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
+ this, interface_number, std::move(callback)));
}
void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting(
int interface_number,
int alternate_setting,
ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), false));
@@ -569,16 +540,15 @@ void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting(
// USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE
// request to the device so it must be performed on a thread where it is okay
// to block.
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetInterface,
- base::Unretained(helper_.get()), interface_number, alternate_setting,
- std::move(callback)));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::SetInterface)
+ .WithArgs(interface_number, alternate_setting)
+ .Then(base::BindOnce(
+ &UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete, this,
+ interface_number, alternate_setting, std::move(callback)));
}
void UsbDeviceHandleUsbfs::ResetDevice(ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), false));
@@ -588,17 +558,14 @@ void UsbDeviceHandleUsbfs::ResetDevice(ResultCallback callback) {
// USBDEVFS_RESET is synchronous because it waits for the port to be reset
// and the device re-enumerated so it must be performed on a thread where it
// is okay to block.
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ResetDevice,
- base::Unretained(helper_.get()), std::move(callback)));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::ResetDevice)
+ .Then(std::move(callback));
}
void UsbDeviceHandleUsbfs::ClearHalt(mojom::UsbTransferDirection direction,
uint8_t endpoint_number,
ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), false));
@@ -619,11 +586,9 @@ void UsbDeviceHandleUsbfs::ClearHalt(mojom::UsbTransferDirection direction,
// USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE
// request to the device so it must be performed on a thread where it is okay
// to block.
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ClearHalt,
- base::Unretained(helper_.get()), endpoint_address,
- std::move(callback)));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::ClearHalt)
+ .WithArgs(endpoint_address)
+ .Then(std::move(callback));
}
void UsbDeviceHandleUsbfs::ControlTransfer(
@@ -636,7 +601,7 @@ void UsbDeviceHandleUsbfs::ControlTransfer(
scoped_refptr<base::RefCountedBytes> buffer,
unsigned int timeout,
TransferCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
@@ -673,7 +638,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferIn(
const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
IsochronousTransferCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
uint8_t endpoint_address = USB_DIR_IN | endpoint_number;
size_t total_length =
std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
@@ -688,7 +653,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferOut(
const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
IsochronousTransferCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
uint8_t endpoint_address = USB_DIR_OUT | endpoint_number;
size_t total_length =
std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
@@ -702,7 +667,7 @@ void UsbDeviceHandleUsbfs::GenericTransfer(
scoped_refptr<base::RefCountedBytes> buffer,
unsigned int timeout,
TransferCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
@@ -748,7 +713,7 @@ void UsbDeviceHandleUsbfs::GenericTransfer(
const mojom::UsbInterfaceInfo* UsbDeviceHandleUsbfs::FindInterfaceByEndpoint(
uint8_t endpoint_address) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = endpoints_.find(endpoint_address);
if (it != endpoints_.end())
return it->second.interface;
@@ -756,24 +721,24 @@ const mojom::UsbInterfaceInfo* UsbDeviceHandleUsbfs::FindInterfaceByEndpoint(
}
UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!device_) << "Handle must be closed before it is destroyed.";
}
-void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() {
- // Calls to this method must be posted to |blocking_task_runner_|.
- helper_->ReleaseFileDescriptor();
- helper_.reset();
+void UsbDeviceHandleUsbfs::ReleaseFileDescriptor(base::OnceClosure callback) {
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::ReleaseFileDescriptor)
+ .Then(std::move(callback));
+ helper_.Reset();
}
-void UsbDeviceHandleUsbfs::CloseBlocking() {
- // Calls to this method must be posted to |blocking_task_runner_|.
- helper_.reset();
+void UsbDeviceHandleUsbfs::FinishClose() {
+ helper_.Reset();
}
void UsbDeviceHandleUsbfs::SetConfigurationComplete(int configuration_value,
- bool success,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ ResultCallback callback,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (success && device_) {
device_->ActiveConfigurationChanged(configuration_value);
// TODO(reillyg): If all interfaces are unclaimed before a new configuration
@@ -786,9 +751,9 @@ void UsbDeviceHandleUsbfs::SetConfigurationComplete(int configuration_value,
void UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete(
int interface_number,
int alternate_setting,
- bool success,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ ResultCallback callback,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (success && device_) {
interfaces_[interface_number].alternate_setting = alternate_setting;
RefreshEndpointInfo();
@@ -797,8 +762,14 @@ void UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete(
}
void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(int interface_number,
- ResultCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ ResultCallback callback,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!success) {
+ std::move(callback).Run(false);
+ return;
+ }
+
auto it = interfaces_.find(interface_number);
DCHECK(it != interfaces_.end());
interfaces_.erase(it);
@@ -816,7 +787,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferInternal(
const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
IsochronousTransferCallback callback) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_) {
ReportIsochronousError(packet_lengths, std::move(callback),
UsbTransferStatus::DISCONNECT);
@@ -859,7 +830,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferInternal(
}
void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (auto* urb : urbs) {
Transfer* transfer = static_cast<Transfer*>(urb->usercontext);
DCHECK_EQ(urb, &transfer->urb);
@@ -876,7 +847,7 @@ void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) {
void UsbDeviceHandleUsbfs::TransferComplete(
std::unique_ptr<Transfer> transfer) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (transfer->cancelled)
return;
@@ -913,7 +884,7 @@ void UsbDeviceHandleUsbfs::TransferComplete(
}
void UsbDeviceHandleUsbfs::RefreshEndpointInfo() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(device_);
endpoints_.clear();
@@ -940,7 +911,7 @@ void UsbDeviceHandleUsbfs::ReportIsochronousError(
const std::vector<uint32_t>& packet_lengths,
UsbDeviceHandle::IsochronousTransferCallback callback,
UsbTransferStatus status) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<UsbIsochronousPacketPtr> packets(packet_lengths.size());
for (size_t i = 0; i < packet_lengths.size(); ++i) {
packets[i] = mojom::UsbIsochronousPacket::New();
@@ -954,7 +925,7 @@ void UsbDeviceHandleUsbfs::ReportIsochronousError(
void UsbDeviceHandleUsbfs::SetUpTimeoutCallback(Transfer* transfer,
unsigned int timeout) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (timeout == 0)
return;
@@ -970,7 +941,7 @@ void UsbDeviceHandleUsbfs::OnTimeout(Transfer* transfer) {
std::unique_ptr<UsbDeviceHandleUsbfs::Transfer>
UsbDeviceHandleUsbfs::RemoveFromTransferList(Transfer* transfer_ptr) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = std::find_if(
transfers_.begin(), transfers_.end(),
[transfer_ptr](const std::unique_ptr<Transfer>& transfer) -> bool {
@@ -984,7 +955,7 @@ UsbDeviceHandleUsbfs::RemoveFromTransferList(Transfer* transfer_ptr) {
void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer,
UsbTransferStatus status) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(device_);
if (transfer->cancelled)
@@ -994,11 +965,10 @@ void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer,
// kernel and will be reaped later.
transfer->cancelled = true;
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::DiscardUrb,
- base::Unretained(helper_.get()), transfer));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::DiscardUrb)
+ .WithArgs(transfer)
+ .Then(
+ base::BindOnce(&UsbDeviceHandleUsbfs::UrbDiscarded, this, transfer));
// Cancelling |timeout_closure| and running completion callbacks may free
// |this| so these operations must be performed at the end of this function.
@@ -1020,7 +990,7 @@ void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer,
}
void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
transfer->discarded = true;
if (transfer->reaped)
RemoveFromTransferList(transfer);
diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.h b/chromium/services/device/usb/usb_device_handle_usbfs.h
index 10e4fecad8d..f4e7e796bab 100644
--- a/chromium/services/device/usb/usb_device_handle_usbfs.h
+++ b/chromium/services/device/usb/usb_device_handle_usbfs.h
@@ -11,8 +11,10 @@
#include <vector>
#include "base/files/scoped_file.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/sequence_bound.h"
#include "services/device/usb/usb_device_handle.h"
struct usbdevfs_urb;
@@ -84,11 +86,11 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
}
// Destroys |helper_| and releases ownership of |fd_| without closing it.
- void ReleaseFileDescriptor();
+ void ReleaseFileDescriptor(base::OnceClosure callback);
// Destroys |helper_| and closes |fd_|. Override to call
// ReleaseFileDescriptor() if necessary.
- virtual void CloseBlocking();
+ virtual void FinishClose();
private:
class BlockingTaskRunnerHelper;
@@ -98,17 +100,19 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
};
struct EndpointInfo {
mojom::UsbTransferType type;
- const mojom::UsbInterfaceInfo* interface;
+ raw_ptr<const mojom::UsbInterfaceInfo> interface;
};
void SetConfigurationComplete(int configuration_value,
- bool success,
- ResultCallback callback);
+ ResultCallback callback,
+ bool success);
void SetAlternateInterfaceSettingComplete(int interface_number,
int alternate_setting,
- bool success,
- ResultCallback callback);
- void ReleaseInterfaceComplete(int interface_number, ResultCallback callback);
+ ResultCallback callback,
+ bool success);
+ void ReleaseInterfaceComplete(int interface_number,
+ ResultCallback callback,
+ bool success);
void IsochronousTransferInternal(uint8_t endpoint_address,
scoped_refptr<base::RefCountedBytes> buffer,
size_t total_length,
@@ -130,9 +134,8 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
void UrbDiscarded(Transfer* transfer);
scoped_refptr<UsbDevice> device_;
- int fd_; // Copy of the base::ScopedFD held by |helper_| valid if |device_|.
+ int fd_; // Copy of the base::ScopedFD held by |helper_|. Valid if |device_|.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
- scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
// Maps claimed interfaces by interface number to their current alternate
// setting.
@@ -145,10 +148,13 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
// Helper object exists on the blocking task thread and all calls to it and
// its destruction must be posted there.
- std::unique_ptr<BlockingTaskRunnerHelper> helper_;
+ base::SequenceBound<BlockingTaskRunnerHelper> helper_;
std::list<std::unique_ptr<Transfer>> transfers_;
- base::SequenceChecker sequence_checker_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<UsbDeviceHandleUsbfs> weak_factory_{this};
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_handle_win.cc b/chromium/services/device/usb/usb_device_handle_win.cc
index cfaf8c8e7c3..70d23401051 100644
--- a/chromium/services/device/usb/usb_device_handle_win.cc
+++ b/chromium/services/device/usb/usb_device_handle_win.cc
@@ -22,7 +22,6 @@
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/task/post_task.h"
@@ -631,12 +630,14 @@ UsbDeviceHandleWin::UsbDeviceHandleWin(scoped_refptr<UsbDeviceWin> device)
}
}
-UsbDeviceHandleWin::UsbDeviceHandleWin(scoped_refptr<UsbDeviceWin> device,
- base::win::ScopedHandle handle)
+UsbDeviceHandleWin::UsbDeviceHandleWin(
+ scoped_refptr<UsbDeviceWin> device,
+ base::win::ScopedHandle handle,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
: device_(std::move(device)),
hub_handle_(std::move(handle)),
task_runner_(base::SequencedTaskRunnerHandle::Get()),
- blocking_task_runner_(UsbService::CreateBlockingTaskRunner()) {}
+ blocking_task_runner_(std::move(blocking_task_runner)) {}
UsbDeviceHandleWin::~UsbDeviceHandleWin() = default;
diff --git a/chromium/services/device/usb/usb_device_handle_win.h b/chromium/services/device/usb/usb_device_handle_win.h
index 722ced7eb2a..0f86ebccd36 100644
--- a/chromium/services/device/usb/usb_device_handle_win.h
+++ b/chromium/services/device/usb/usb_device_handle_win.h
@@ -11,7 +11,7 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
@@ -31,6 +31,9 @@ class UsbDeviceWin;
// UsbDeviceHandle class provides basic I/O related functionalities.
class UsbDeviceHandleWin : public UsbDeviceHandle {
public:
+ UsbDeviceHandleWin(const UsbDeviceHandleWin&) = delete;
+ UsbDeviceHandleWin& operator=(const UsbDeviceHandleWin&) = delete;
+
scoped_refptr<UsbDevice> GetDevice() const override;
void Close() override;
void SetConfiguration(int configuration_value,
@@ -80,9 +83,13 @@ class UsbDeviceHandleWin : public UsbDeviceHandle {
// Constructor used to build a connection to the device.
UsbDeviceHandleWin(scoped_refptr<UsbDeviceWin> device);
- // Constructor used to build a connection to the device's parent hub.
- UsbDeviceHandleWin(scoped_refptr<UsbDeviceWin> device,
- base::win::ScopedHandle handle);
+ // Constructor used to build a connection to the device's parent hub. To avoid
+ // bugs in USB hub drivers a single global sequenced task runner is used for
+ // all calls to the driver.
+ UsbDeviceHandleWin(
+ scoped_refptr<UsbDeviceWin> device,
+ base::win::ScopedHandle handle,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
~UsbDeviceHandleWin() override;
@@ -98,13 +105,17 @@ class UsbDeviceHandleWin : public UsbDeviceHandle {
struct Interface {
Interface();
+
+ Interface(const Interface&) = delete;
+ Interface& operator=(const Interface&) = delete;
+
~Interface();
// This may be nullptr in the rare case of a device which doesn't have any
// interfaces. In that case the Windows API still considers the device to
// have a single function which is represented here by initializing
// |interface_number| and |first_interface| to create a fake interface 0.
- const mojom::UsbInterfaceInfo* info = nullptr;
+ raw_ptr<const mojom::UsbInterfaceInfo> info = nullptr;
// These fields are copied from |info| and initialized to 0 in case it is
// nullptr.
@@ -129,12 +140,10 @@ class UsbDeviceHandleWin : public UsbDeviceHandle {
// Closures to execute when |function_path| has been populated.
std::vector<OpenInterfaceCallback> ready_callbacks;
-
- DISALLOW_COPY_AND_ASSIGN(Interface);
};
struct Endpoint {
- const mojom::UsbInterfaceInfo* interface;
+ raw_ptr<const mojom::UsbInterfaceInfo> interface;
mojom::UsbTransferType type;
};
@@ -222,8 +231,6 @@ class UsbDeviceHandleWin : public UsbDeviceHandle {
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
base::WeakPtrFactory<UsbDeviceHandleWin> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandleWin);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_impl.cc b/chromium/services/device/usb/usb_device_impl.cc
index aca10158b01..49968886303 100644
--- a/chromium/services/device/usb/usb_device_impl.cc
+++ b/chromium/services/device/usb/usb_device_impl.cc
@@ -12,8 +12,8 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
diff --git a/chromium/services/device/usb/usb_device_impl.h b/chromium/services/device/usb/usb_device_impl.h
index a8815ce6e67..13376eec80b 100644
--- a/chromium/services/device/usb/usb_device_impl.h
+++ b/chromium/services/device/usb/usb_device_impl.h
@@ -14,7 +14,6 @@
#include "base/callback.h"
#include "base/files/scoped_file.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "services/device/usb/scoped_libusb_device_ref.h"
@@ -37,6 +36,9 @@ class UsbDeviceImpl : public UsbDevice {
UsbDeviceImpl(ScopedLibusbDeviceRef platform_device,
const libusb_device_descriptor& descriptor);
+ UsbDeviceImpl(const UsbDeviceImpl&) = delete;
+ UsbDeviceImpl& operator=(const UsbDeviceImpl&) = delete;
+
// UsbDevice implementation:
void Open(OpenCallback callback) override;
@@ -84,8 +86,6 @@ class UsbDeviceImpl : public UsbDevice {
bool visited_ = false;
const ScopedLibusbDeviceRef platform_device_;
-
- DISALLOW_COPY_AND_ASSIGN(UsbDeviceImpl);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_linux.cc b/chromium/services/device/usb/usb_device_linux.cc
index ca5c5f8fb31..7b8061ebb68 100644
--- a/chromium/services/device/usb/usb_device_linux.cc
+++ b/chromium/services/device/usb/usb_device_linux.cc
@@ -14,8 +14,8 @@
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/chromeos_buildflags.h"
#include "components/device_event_log/device_event_log.h"
diff --git a/chromium/services/device/usb/usb_device_linux.h b/chromium/services/device/usb/usb_device_linux.h
index 2ea0f612961..f78c30c99de 100644
--- a/chromium/services/device/usb/usb_device_linux.h
+++ b/chromium/services/device/usb/usb_device_linux.h
@@ -12,7 +12,6 @@
#include <utility>
#include "base/files/scoped_file.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -28,6 +27,9 @@ struct UsbDeviceDescriptor;
class UsbDeviceLinux : public UsbDevice {
public:
+ UsbDeviceLinux(const UsbDeviceLinux&) = delete;
+ UsbDeviceLinux& operator=(const UsbDeviceLinux&) = delete;
+
// UsbDevice implementation:
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
void CheckUsbAccess(ResultCallback callback) override;
@@ -73,8 +75,6 @@ class UsbDeviceLinux : public UsbDevice {
SEQUENCE_CHECKER(sequence_checker_);
const std::string device_path_;
-
- DISALLOW_COPY_AND_ASSIGN(UsbDeviceLinux);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_device_win.cc b/chromium/services/device/usb/usb_device_win.cc
index bc6acf24f16..f9d3b24c12a 100644
--- a/chromium/services/device/usb/usb_device_win.cc
+++ b/chromium/services/device/usb/usb_device_win.cc
@@ -10,9 +10,9 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/usb/usb_device_handle_win.h"
@@ -51,7 +51,9 @@ void UsbDeviceWin::Open(OpenCallback callback) {
FROM_HERE, base::BindOnce(std::move(callback), std::move(device_handle)));
}
-void UsbDeviceWin::ReadDescriptors(base::OnceCallback<void(bool)> callback) {
+void UsbDeviceWin::ReadDescriptors(
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ base::OnceCallback<void(bool)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<UsbDeviceHandle> device_handle;
@@ -59,7 +61,8 @@ void UsbDeviceWin::ReadDescriptors(base::OnceCallback<void(bool)> callback) {
CreateFile(hub_path_.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr));
if (handle.IsValid()) {
- device_handle = new UsbDeviceHandleWin(this, std::move(handle));
+ device_handle = new UsbDeviceHandleWin(this, std::move(handle),
+ std::move(blocking_task_runner));
} else {
USB_PLOG(ERROR) << "Failed to open " << hub_path_;
std::move(callback).Run(false);
diff --git a/chromium/services/device/usb/usb_device_win.h b/chromium/services/device/usb/usb_device_win.h
index 083628e03cc..e8b8bb72818 100644
--- a/chromium/services/device/usb/usb_device_win.h
+++ b/chromium/services/device/usb/usb_device_win.h
@@ -10,7 +10,6 @@
#include <string>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "services/device/usb/usb_device.h"
@@ -40,6 +39,9 @@ class UsbDeviceWin : public UsbDevice {
uint32_t port_number,
DriverType driver_type);
+ UsbDeviceWin(const UsbDeviceWin&) = delete;
+ UsbDeviceWin& operator=(const UsbDeviceWin&) = delete;
+
// UsbDevice implementation:
void Open(OpenCallback callback) override;
@@ -57,7 +59,9 @@ class UsbDeviceWin : public UsbDevice {
// Opens the device's parent hub in order to read the device, configuration
// and string descriptors.
- void ReadDescriptors(base::OnceCallback<void(bool)> callback);
+ void ReadDescriptors(
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ base::OnceCallback<void(bool)> callback);
void UpdateFunction(int interface_number, const FunctionInfo& function_info);
@@ -92,8 +96,6 @@ class UsbDeviceWin : public UsbDevice {
const std::wstring hub_path_;
base::flat_map<int, FunctionInfo> functions_;
const DriverType driver_type_;
-
- DISALLOW_COPY_AND_ASSIGN(UsbDeviceWin);
};
} // namespace device
diff --git a/chromium/services/device/usb/usb_service.h b/chromium/services/device/usb/usb_service.h
index ddccf373f21..78a7b59bd27 100644
--- a/chromium/services/device/usb/usb_service.h
+++ b/chromium/services/device/usb/usb_service.h
@@ -13,12 +13,11 @@
#include "base/callback_helpers.h"
#include "base/check.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
namespace device {
diff --git a/chromium/services/device/usb/usb_service_android.cc b/chromium/services/device/usb/usb_service_android.cc
index df48f19ec24..011a94053c4 100644
--- a/chromium/services/device/usb/usb_service_android.cc
+++ b/chromium/services/device/usb/usb_service_android.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/location.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/usb/jni_headers/ChromeUsbService_jni.h"
#include "services/device/usb/usb_device_android.h"
diff --git a/chromium/services/device/usb/usb_service_impl.cc b/chromium/services/device/usb/usb_service_impl.cc
index 74bfe41d530..8e3c821381a 100644
--- a/chromium/services/device/usb/usb_service_impl.cc
+++ b/chromium/services/device/usb/usb_service_impl.cc
@@ -18,10 +18,10 @@
#include "base/location.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "build/build_config.h"
diff --git a/chromium/services/device/usb/usb_service_impl.h b/chromium/services/device/usb/usb_service_impl.h
index 7ce65214a52..73135fb2fdc 100644
--- a/chromium/services/device/usb/usb_service_impl.h
+++ b/chromium/services/device/usb/usb_service_impl.h
@@ -15,7 +15,6 @@
#include <vector>
#include "base/containers/queue.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "services/device/usb/scoped_libusb_device_ref.h"
diff --git a/chromium/services/device/usb/usb_service_linux.cc b/chromium/services/device/usb/usb_service_linux.cc
index 4370a475380..76fc4b8084b 100644
--- a/chromium/services/device/usb/usb_service_linux.cc
+++ b/chromium/services/device/usb/usb_service_linux.cc
@@ -89,15 +89,15 @@ void OnDeviceOpenedToReadDescriptors(
class UsbServiceLinux::BlockingTaskRunnerHelper : public UdevWatcher::Observer {
public:
- explicit BlockingTaskRunnerHelper(base::WeakPtr<UsbServiceLinux> service);
+ explicit BlockingTaskRunnerHelper(
+ base::WeakPtr<UsbServiceLinux> service,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
BlockingTaskRunnerHelper(const BlockingTaskRunnerHelper&) = delete;
BlockingTaskRunnerHelper& operator=(const BlockingTaskRunnerHelper&) = delete;
~BlockingTaskRunnerHelper() override;
- void Start();
-
private:
// UdevWatcher::Observer
void OnDeviceAdded(ScopedUdevDevicePtr device) override;
@@ -110,23 +110,14 @@ class UsbServiceLinux::BlockingTaskRunnerHelper : public UdevWatcher::Observer {
base::WeakPtr<UsbServiceLinux> service_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
- base::SequenceChecker sequence_checker_;
+ SEQUENCE_CHECKER(sequence_checker_);
};
UsbServiceLinux::BlockingTaskRunnerHelper::BlockingTaskRunnerHelper(
- base::WeakPtr<UsbServiceLinux> service)
- : service_(service), task_runner_(base::SequencedTaskRunnerHandle::Get()) {
- // Detaches from the sequence on which this object was created. It will be
- // bound to its owning sequence when Start() is called.
- sequence_checker_.DetachFromSequence();
-}
-
-UsbServiceLinux::BlockingTaskRunnerHelper::~BlockingTaskRunnerHelper() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-}
-
-void UsbServiceLinux::BlockingTaskRunnerHelper::Start() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ base::WeakPtr<UsbServiceLinux> service,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : service_(std::move(service)), task_runner_(std::move(task_runner)) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -140,9 +131,13 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::Start() {
FROM_HERE, base::BindOnce(&UsbServiceLinux::HelperStarted, service_));
}
+UsbServiceLinux::BlockingTaskRunnerHelper::~BlockingTaskRunnerHelper() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded(
ScopedUdevDevicePtr device) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -214,7 +209,7 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded(
void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceRemoved(
ScopedUdevDevicePtr device) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -229,17 +224,14 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceRemoved(
void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceChanged(
ScopedUdevDevicePtr) {}
-UsbServiceLinux::UsbServiceLinux()
- : UsbService(),
- blocking_task_runner_(CreateBlockingTaskRunner()),
- helper_(nullptr, base::OnTaskRunnerDeleter(blocking_task_runner_)) {
- helper_.reset(new BlockingTaskRunnerHelper(weak_factory_.GetWeakPtr()));
- blocking_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::Start,
- base::Unretained(helper_.get())));
+UsbServiceLinux::UsbServiceLinux() {
+ helper_ = base::SequenceBound<BlockingTaskRunnerHelper>(
+ CreateBlockingTaskRunner(), weak_factory_.GetWeakPtr(),
+ base::SequencedTaskRunnerHandle::Get());
}
UsbServiceLinux::~UsbServiceLinux() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NotifyWillDestroyUsbService();
}
diff --git a/chromium/services/device/usb/usb_service_linux.h b/chromium/services/device/usb/usb_service_linux.h
index 5830b654a67..6d9ba3b7378 100644
--- a/chromium/services/device/usb/usb_service_linux.h
+++ b/chromium/services/device/usb/usb_service_linux.h
@@ -10,9 +10,8 @@
#include <string>
#include <unordered_map>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/threading/sequence_bound.h"
#include "build/chromeos_buildflags.h"
#include "services/device/usb/usb_service.h"
@@ -58,8 +57,7 @@ class UsbServiceLinux final : public UsbService {
uint32_t first_enumeration_countdown_ = 0;
std::list<GetDevicesCallback> enumeration_callbacks_;
- scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
- std::unique_ptr<BlockingTaskRunnerHelper, base::OnTaskRunnerDeleter> helper_;
+ base::SequenceBound<BlockingTaskRunnerHelper> helper_;
DeviceMap devices_by_path_;
base::WeakPtrFactory<UsbServiceLinux> weak_factory_{this};
diff --git a/chromium/services/device/usb/usb_service_win.cc b/chromium/services/device/usb/usb_service_win.cc
index 554c3519846..d999a29c851 100644
--- a/chromium/services/device/usb/usb_service_win.cc
+++ b/chromium/services/device/usb/usb_service_win.cc
@@ -21,7 +21,6 @@
#include "base/memory/free_deleter.h"
#include "base/memory/ptr_util.h"
#include "base/scoped_generic.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece_forward.h"
#include "base/strings/string_split.h"
@@ -30,7 +29,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/scoped_thread_priority.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/win/registry.h"
#include "base/win/scoped_devinfo.h"
#include "base/win/scoped_handle.h"
@@ -418,12 +417,11 @@ UsbDeviceWin::FunctionInfo GetFunctionInfo(const std::wstring& instance_id) {
class UsbServiceWin::BlockingTaskRunnerHelper {
public:
- explicit BlockingTaskRunnerHelper(base::WeakPtr<UsbServiceWin> service)
- : service_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- service_(service) {}
- ~BlockingTaskRunnerHelper() {}
-
- void EnumerateDevices() {
+ BlockingTaskRunnerHelper(
+ base::WeakPtr<UsbServiceWin> service,
+ scoped_refptr<base::SequencedTaskRunner> service_task_runner)
+ : service_task_runner_(std::move(service_task_runner)),
+ service_(std::move(service)) {
// Boost priority while potentially loading SetupAPI.dll for the following
// functions on a background thread.
SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
@@ -454,6 +452,8 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
FROM_HERE, base::BindOnce(&UsbServiceWin::HelperStarted, service_));
}
+ ~BlockingTaskRunnerHelper() = default;
+
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.
@@ -583,22 +583,19 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
// Calls back to |service_| must be posted to |service_task_runner_|, which
// runs tasks on the thread where that object lives.
- scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
base::WeakPtr<UsbServiceWin> service_;
};
UsbServiceWin::UsbServiceWin()
- : UsbService(),
- blocking_task_runner_(CreateBlockingTaskRunner()),
- helper_(nullptr, base::OnTaskRunnerDeleter(blocking_task_runner_)) {
+ : blocking_task_runner_(CreateBlockingTaskRunner()) {
DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForAllInterfaces();
if (device_monitor)
device_observation_.Observe(device_monitor);
- helper_.reset(new BlockingTaskRunnerHelper(weak_factory_.GetWeakPtr()));
- blocking_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::EnumerateDevices,
- base::Unretained(helper_.get())));
+ helper_ = base::SequenceBound<BlockingTaskRunnerHelper>(
+ blocking_task_runner_, weak_factory_.GetWeakPtr(),
+ base::SequencedTaskRunnerHandle::Get());
}
UsbServiceWin::~UsbServiceWin() {
@@ -615,10 +612,8 @@ void UsbServiceWin::GetDevices(GetDevicesCallback callback) {
void UsbServiceWin::OnDeviceAdded(const GUID& class_guid,
const std::wstring& device_path) {
- blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BlockingTaskRunnerHelper::OnDeviceAdded,
- base::Unretained(helper_.get()), class_guid, device_path));
+ helper_.AsyncCall(&BlockingTaskRunnerHelper::OnDeviceAdded)
+ .WithArgs(class_guid, device_path);
}
void UsbServiceWin::OnDeviceRemoved(const GUID& class_guid,
@@ -673,9 +668,10 @@ void UsbServiceWin::CreateDeviceObject(
auto device = base::MakeRefCounted<UsbDeviceWin>(
device_path, hub_path, functions, bus_number, port_number, driver_type);
devices_by_path_[device->device_path()] = device;
- device->ReadDescriptors(base::BindOnce(&UsbServiceWin::DeviceReady,
- weak_factory_.GetWeakPtr(), device,
- driver_name));
+ device->ReadDescriptors(
+ blocking_task_runner_,
+ base::BindOnce(&UsbServiceWin::DeviceReady, weak_factory_.GetWeakPtr(),
+ device, driver_name));
}
void UsbServiceWin::UpdateFunction(
diff --git a/chromium/services/device/usb/usb_service_win.h b/chromium/services/device/usb/usb_service_win.h
index 5c7dfab7ca3..4eb5d9d58eb 100644
--- a/chromium/services/device/usb/usb_service_win.h
+++ b/chromium/services/device/usb/usb_service_win.h
@@ -12,10 +12,10 @@
#include <unordered_map>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/threading/sequence_bound.h"
#include "device/base/device_monitor_win.h"
#include "services/device/usb/usb_device_win.h"
@@ -71,7 +71,7 @@ class UsbServiceWin final : public DeviceMonitorWin::Observer,
std::list<GetDevicesCallback> enumeration_callbacks_;
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
- std::unique_ptr<BlockingTaskRunnerHelper, base::OnTaskRunnerDeleter> helper_;
+ base::SequenceBound<BlockingTaskRunnerHelper> helper_;
std::unordered_map<std::wstring, scoped_refptr<UsbDeviceWin>>
devices_by_path_;
diff --git a/chromium/services/device/vibration/OWNERS b/chromium/services/device/vibration/OWNERS
deleted file mode 100644
index 56c64582cfe..00000000000
--- a/chromium/services/device/vibration/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-blundell@chromium.org
-timvolodine@chromium.org
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 5bc4ea649e9..1637134b948 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
+++ b/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
@@ -13,8 +13,14 @@ if (is_android) {
source_set("power_save_blocker") {
visibility = [
# Crosapi power API needs to directly use the Ash PowerBlocker .
+ # TODO(b/193670013): Remove visibility after Wayland idle inhibitor replaces
+ # crosapi power service.
"//chrome/browser/ash/crosapi",
+ # Exo Wayland idle inhibit protocol needs to directly use the Ash
+ # PowerBlocker.
+ "//components/exo/wayland",
+
# //remoting runs in a separate process which is outside of the context of
# the ServiceManager-based world. Instead of embedding a Service Manager
# environment and Device Service in it, we allow the power save blocker to
@@ -56,23 +62,9 @@ source_set("power_save_blocker") {
}
deps += [
"//dbus",
+ "//ui/display",
"//ui/gfx",
]
- if (use_x11 || use_ozone) {
- deps += [ "//ui/base:features" ]
- }
- if (use_x11) {
- deps += [
- "//ui/base/x:x",
- "//ui/gfx/x",
- ]
- }
- if (use_ozone) {
- deps += [
- "//ui/base:features",
- "//ui/display:display",
- ]
- }
} else if (is_mac) {
sources += [ "power_save_blocker_mac.cc" ]
frameworks = [
diff --git a/chromium/services/device/wake_lock/power_save_blocker/DEPS b/chromium/services/device/wake_lock/power_save_blocker/DEPS
index 0ab93edcb06..04bd6b68a07 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/DEPS
+++ b/chromium/services/device/wake_lock/power_save_blocker/DEPS
@@ -4,7 +4,6 @@ include_rules = [
"+services/device/public",
"+ui/android",
"+ui/gfx",
- "+ui/base/ui_base_features.h",
"+ui/base/x",
"+ui/display",
]
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker.h b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker.h
index f29cbb74ce9..026407b2ac1 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker.h
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker.h
@@ -9,8 +9,8 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_android.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_android.cc
index bfaa4cad9d3..17a599ede3c 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_android.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_android.cc
@@ -8,8 +8,7 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/location.h"
-#include "base/macros.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "services/device/wake_lock/power_save_blocker/jni_headers/PowerSaveBlocker_jni.h"
#include "ui/android/view_android.h"
@@ -23,6 +22,9 @@ class PowerSaveBlocker::Delegate
public:
Delegate(scoped_refptr<base::SequencedTaskRunner> ui_task_runner);
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
+
// Does the actual work to apply or remove the desired power save block.
void ApplyBlock(ui::ViewAndroid* view_android);
void RemoveBlock();
@@ -34,8 +36,6 @@ class PowerSaveBlocker::Delegate
base::android::ScopedJavaGlobalRef<jobject> java_power_save_blocker_;
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
};
PowerSaveBlocker::Delegate::Delegate(
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_ash.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_ash.cc
index f5c867badec..c2ba9d6f565 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_ash.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_ash.cc
@@ -11,7 +11,7 @@
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/notreached.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "chromeos/dbus/power/power_policy_controller.h"
namespace device {
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc
index 99cf56c7a99..444853e06a6 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc
@@ -10,14 +10,18 @@
#include "chromeos/crosapi/mojom/power.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "ui/display/screen.h"
namespace device {
/******** PowerSaveBlocker::Delegate ********/
-// Lacros-chrome PowerSaveBlocker uses ash-chrome ProwerSaveBlocker via crosapi.
+// Lacros-chrome PowerSaveBlocker uses ash-chrome ProwerSaveBlocker via either
+// crosapi (the default) or Wayland (if the idle inhibitor feature is enabled).
// RAII style is maintained by keeping a crosapi::mojom::PowerWakeLock Mojo
// connection, whose disconnection triggers resource release in ash-chrome.
+// TODO(b/193670013): Cleanup logic after Wayland idle inhibitor replaces
+// crosapi power service.
class PowerSaveBlocker::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlocker::Delegate> {
@@ -35,6 +39,11 @@ class PowerSaveBlocker::Delegate
void ApplyBlock() {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
+
+ auto* const screen = display::Screen::GetScreen();
+ if (screen && screen->SetScreenSaverSuspended(true))
+ return;
+
auto* lacros_service = chromeos::LacrosService::Get();
if (lacros_service->IsAvailable<crosapi::mojom::Power>()) {
lacros_service->GetRemote<crosapi::mojom::Power>()->AddPowerSaveBlocker(
@@ -44,6 +53,11 @@ class PowerSaveBlocker::Delegate
void RemoveBlock() {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
+
+ auto* const screen = display::Screen::GetScreen();
+ if (screen && screen->SetScreenSaverSuspended(false))
+ return;
+
// Disconnect to make ash-chrome release its PowerSaveBlocker.
receiver_.reset();
}
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 92e3e974cbc..5af73f59a15 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
@@ -14,30 +14,16 @@
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/single_thread_task_runner.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
-#include "ui/gfx/switches.h"
-
-#if defined(USE_X11) || defined(USE_OZONE)
-#include "ui/base/ui_base_features.h" // nogncheck
-#endif
-
-#if defined(USE_X11)
-#include "ui/base/x/x11_util.h" // nogncheck
-#include "ui/gfx/x/connection.h" // nogncheck
-#include "ui/gfx/x/screensaver.h" // nogncheck
-#endif
-
-#if defined(USE_OZONE)
#include "ui/display/screen.h"
-#endif
+#include "ui/gfx/switches.h"
namespace device {
@@ -140,19 +126,9 @@ void GetDbusStringsForApi(DBusAPI api,
}
void SetScreenSaverSuspended(bool suspend) {
-#if defined(USE_OZONE)
- if (features::IsUsingOzonePlatform()) {
- auto* const screen = display::Screen::GetScreen();
- // The screen can be nullptr in tests.
- if (!screen)
- return;
+ // The screen can be nullptr in tests.
+ if (auto* const screen = display::Screen::GetScreen())
screen->SetScreenSaverSuspended(suspend);
- return;
- }
-#endif
-#if defined(USE_X11)
- ui::SuspendX11ScreenSaver(suspend);
-#endif
}
} // namespace
@@ -166,6 +142,9 @@ class PowerSaveBlocker::Delegate
scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner);
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
+
// Post a task to initialize the delegate on the UI thread, which will itself
// then post a task to apply the power save block on the blocking task runner.
void Init();
@@ -211,8 +190,6 @@ class PowerSaveBlocker::Delegate
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
};
PowerSaveBlocker::Delegate::Delegate(
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc
index 4d61b8a459d..82fee719061 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc
@@ -10,8 +10,8 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/sys_string_conversions.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_stub.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_stub.cc
index c2f917a5c3e..0f788eda259 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_stub.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_stub.cc
@@ -4,7 +4,6 @@
#include "services/device/wake_lock/power_save_blocker/power_save_blocker.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
namespace device {
@@ -14,11 +13,12 @@ class PowerSaveBlocker::Delegate
public:
Delegate() {}
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
+
private:
friend class base::RefCountedThreadSafe<Delegate>;
virtual ~Delegate() {}
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
};
PowerSaveBlocker::PowerSaveBlocker(
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 b4b31fb2c8a..375377e42a9 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
@@ -8,9 +8,8 @@
#include "base/bind.h"
#include "base/check.h"
-#include "base/macros.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
@@ -69,6 +68,9 @@ class PowerSaveBlocker::Delegate
description_(description),
ui_task_runner_(ui_task_runner) {}
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
+
// Does the actual work to apply or remove the desired power save block.
void ApplyBlock();
void RemoveBlock();
@@ -84,8 +86,6 @@ class PowerSaveBlocker::Delegate
const std::string description_;
base::win::ScopedHandle handle_;
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
};
void PowerSaveBlocker::Delegate::ApplyBlock() {
diff --git a/chromium/services/device/wake_lock/wake_lock.h b/chromium/services/device/wake_lock/wake_lock.h
index 9e08614bb64..bab0f7ae76f 100644
--- a/chromium/services/device/wake_lock/wake_lock.h
+++ b/chromium/services/device/wake_lock/wake_lock.h
@@ -8,9 +8,9 @@
#include <memory>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
@@ -101,7 +101,7 @@ class WakeLock : public mojom::WakeLock {
std::unique_ptr<PowerSaveBlocker> wake_lock_;
// Not owned. |observer_| must outlive this instance of WakeLock.
- Observer* const observer_;
+ const raw_ptr<Observer> observer_;
// Multiple clients that associate to the same WebContents share the same one
// WakeLock instance. Two consecutive |RequestWakeLock| requests
diff --git a/chromium/services/device/wake_lock/wake_lock_context.h b/chromium/services/device/wake_lock/wake_lock_context.h
index 66edc018d7c..05b328b354b 100644
--- a/chromium/services/device/wake_lock/wake_lock_context.h
+++ b/chromium/services/device/wake_lock/wake_lock_context.h
@@ -12,7 +12,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/wake_lock_context.mojom.h"
#include "services/device/wake_lock/wake_lock.h"
diff --git a/chromium/services/device/wake_lock/wake_lock_provider.cc b/chromium/services/device/wake_lock/wake_lock_provider.cc
index 66c5275d62a..db926a95384 100644
--- a/chromium/services/device/wake_lock/wake_lock_provider.cc
+++ b/chromium/services/device/wake_lock/wake_lock_provider.cc
@@ -19,6 +19,10 @@ namespace device {
// would be 3.
struct WakeLockProvider::WakeLockDataPerType {
WakeLockDataPerType() = default;
+
+ WakeLockDataPerType(const WakeLockDataPerType&) = delete;
+ WakeLockDataPerType& operator=(const WakeLockDataPerType&) = delete;
+
~WakeLockDataPerType() = default;
// Currently activated wake locks of this wake lock type.
@@ -30,8 +34,6 @@ struct WakeLockProvider::WakeLockDataPerType {
// Observers for this wake lock type.
mojo::RemoteSet<mojom::WakeLockObserver> observers;
-
- DISALLOW_COPY_AND_ASSIGN(WakeLockDataPerType);
};
WakeLockProvider::WakeLockProvider(
diff --git a/chromium/services/device/wake_lock/wake_lock_provider.h b/chromium/services/device/wake_lock/wake_lock_provider.h
index c10f54f3e76..ea8849008c9 100644
--- a/chromium/services/device/wake_lock/wake_lock_provider.h
+++ b/chromium/services/device/wake_lock/wake_lock_provider.h
@@ -9,8 +9,8 @@
#include <memory>
#include <string>
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.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/annotator.cc b/chromium/services/image_annotation/annotator.cc
index 8f04ba5489a..82fb0e8f2ad 100644
--- a/chromium/services/image_annotation/annotator.cc
+++ b/chromium/services/image_annotation/annotator.cc
@@ -230,6 +230,38 @@ std::tuple<bool, std::vector<mojom::AnnotationPtr>> ParseJsonDescAnnotations(
return {adult, std::move(results)};
}
+// Extracts annotations from the given icon engine result.
+mojom::AnnotationPtr ParseJsonIconAnnotations(const base::Value& icon_engine) {
+ mojom::AnnotationPtr result;
+ if (!icon_engine.is_dict())
+ return {};
+
+ const base::Value* const icon_list = icon_engine.FindKey("icon");
+ if (!icon_list || !icon_list->is_list())
+ return {};
+
+ for (const base::Value& icon : icon_list->GetList()) {
+ if (!icon.is_dict())
+ continue;
+
+ const base::Value* const icon_type = icon.FindKey("iconType");
+ if (!icon_type || !icon_type->is_string())
+ continue;
+
+ std::string icon_type_value = icon_type->GetString();
+
+ const base::Value* const score = icon.FindKey("score");
+ if (!score || (!score->is_double() && !score->is_int()))
+ continue;
+
+ // Only return the first matching icon.
+ auto type = mojom::AnnotationType::kIcon;
+ return mojom::Annotation::New(type, score->GetDouble(), icon_type_value);
+ }
+
+ return {};
+}
+
// Returns the integer status code for this engine, or -1 if no status can be
// extracted.
int ExtractStatusCode(const base::Value* const status_dict) {
@@ -289,6 +321,7 @@ std::map<std::string, mojom::AnnotateImageResultPtr> UnpackJsonResponse(
bool adult = false;
std::vector<mojom::AnnotationPtr> annotations;
mojom::AnnotationPtr ocr_annotation;
+ mojom::AnnotationPtr icon_annotation;
for (const base::Value& engine_result : engine_results->GetList()) {
if (!engine_result.is_dict())
continue;
@@ -306,6 +339,8 @@ std::map<std::string, mojom::AnnotateImageResultPtr> UnpackJsonResponse(
const base::Value* const desc_engine =
engine_result.FindKey("descriptionEngine");
const base::Value* const ocr_engine = engine_result.FindKey("ocrEngine");
+ const base::Value* const icon_engine =
+ engine_result.FindKey("iconEngine");
if (desc_engine) {
// Add description annotations and update the adult image flag.
@@ -322,6 +357,10 @@ std::map<std::string, mojom::AnnotateImageResultPtr> UnpackJsonResponse(
ocr_annotation =
ParseJsonOcrAnnotation(*ocr_engine, min_ocr_confidence);
}
+ } else if (icon_engine) {
+ if (status_code <= 0) {
+ icon_annotation = ParseJsonIconAnnotations(*icon_engine);
+ }
}
ReportEngineKnown(ocr_engine || desc_engine);
@@ -336,6 +375,19 @@ std::map<std::string, mojom::AnnotateImageResultPtr> UnpackJsonResponse(
annotations.push_back(std::move(ocr_annotation));
}
+ // Remove labels and captions if the image is detected
+ // as an icon. Don't remove OCR as any text in the icon might
+ // be useful.
+ // TODO(accessibility): consider filtering some icon types here e.g.
+ // information.
+ if (!icon_annotation.is_null()) {
+ base::EraseIf(annotations, [](const mojom::AnnotationPtr& a) {
+ return a->type == mojom::AnnotationType::kLabel ||
+ a->type == mojom::AnnotationType::kCaption;
+ });
+ annotations.push_back(std::move(icon_annotation));
+ }
+
if (adult) {
out[image_id->GetString()] = mojom::AnnotateImageResult::NewErrorCode(
mojom::AnnotateImageError::kAdult);
@@ -356,6 +408,8 @@ static_assert(Annotator::kDescMinDimension > 0,
"Description engine must accept images of some sizes.");
static_assert(Annotator::kDescMaxAspectRatio > 0.0,
"Description engine must accept images of some aspect ratios.");
+static_assert(Annotator::kIconMinDimension > 0,
+ "Icon engine must accept images of some sizes.");
Annotator::ClientRequestInfo::ClientRequestInfo(
mojo::PendingRemote<mojom::ImageProcessor> in_image_processor,
@@ -368,10 +422,12 @@ Annotator::ClientRequestInfo::~ClientRequestInfo() = default;
Annotator::ServerRequestInfo::ServerRequestInfo(
const std::string& in_source_id,
const bool in_desc_requested,
+ const bool in_icon_requested,
const std::string& in_desc_lang_tag,
const std::vector<uint8_t>& in_image_bytes)
: source_id(in_source_id),
desc_requested(in_desc_requested),
+ icon_requested(in_icon_requested),
desc_lang_tag(in_desc_lang_tag),
image_bytes(in_image_bytes) {}
@@ -485,6 +541,23 @@ bool Annotator::IsWithinDescPolicy(const int32_t width, const int32_t height) {
}
// static
+bool Annotator::IsWithinIconPolicy(const int32_t width, const int32_t height) {
+ if (width < kIconMinDimension || height < kIconMinDimension ||
+ width > kIconMaxDimension || height > kIconMaxDimension) {
+ return false;
+ }
+
+ // Can't be 0 or inf because |kIconMinDimension| is guaranteed positive (via a
+ // static_assert).
+ const double aspect_ratio = static_cast<double>(width) / height;
+ if (aspect_ratio < 1.0 / kIconMaxAspectRatio ||
+ aspect_ratio > kIconMaxAspectRatio)
+ return false;
+
+ return true;
+}
+
+// static
std::string Annotator::FormatJsonRequest(
const std::deque<ServerRequestInfo>::iterator begin,
const std::deque<ServerRequestInfo>::iterator end) {
@@ -526,6 +599,17 @@ std::string Annotator::FormatJsonRequest(
}
ReportImageRequestIncludesDesc(it->desc_requested);
+ // Request icon classification.
+ // TODO(accessibility): Maybe only do this for certain
+ // file sizes?
+ if (it->icon_requested) {
+ base::Value icon_params(base::Value::Type::DICTIONARY);
+ base::Value engine_params(base::Value::Type::DICTIONARY);
+ engine_params.SetKey("iconParameters", std::move(icon_params));
+ engine_params_list.Append(std::move(engine_params));
+ }
+ ReportImageRequestIncludesIcon(it->icon_requested);
+
base::Value image_request(base::Value::Type::DICTIONARY);
image_request.SetKey(
"imageId", base::Value(MakeImageId(it->source_id, it->desc_lang_tag)));
@@ -626,9 +710,9 @@ void Annotator::OnJpgImageDataReceived(
local_processors_.erase(request_key);
// Schedule a server request for this image.
- server_request_queue_.emplace_front(source_id,
- IsWithinDescPolicy(width, height),
- request_language, image_bytes);
+ server_request_queue_.emplace_front(
+ source_id, IsWithinDescPolicy(width, height),
+ IsWithinIconPolicy(width, height), request_language, image_bytes);
pending_requests_.insert(request_key);
// Start sending batches to the server.
diff --git a/chromium/services/image_annotation/annotator.h b/chromium/services/image_annotation/annotator.h
index d1aa5e42c48..151cd2e6be1 100644
--- a/chromium/services/image_annotation/annotator.h
+++ b/chromium/services/image_annotation/annotator.h
@@ -14,7 +14,6 @@
#include <utility>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
@@ -67,6 +66,17 @@ class Annotator : public mojom::Annotator {
// The maximum aspect ratio permitted to request description annotations.
static constexpr double kDescMaxAspectRatio = 2.5;
+ // The minimum side length needed to request icon annotations.
+ static constexpr int32_t kIconMinDimension = 16;
+
+ // The maximum side length needed to request icon annotations.
+ static constexpr int32_t kIconMaxDimension = 256;
+
+ // The maximum aspect ratio permitted to request icon annotations.
+ // (Most icons are square, but something like an ellipsis / "more" menu
+ // can have a long aspect ratio.)
+ static constexpr double kIconMaxAspectRatio = 5.0;
+
// Constructs an annotator.
// |pixels_server_url| : the URL to use when the annotator sends image
// pixel data to get back annotations. The
@@ -134,6 +144,7 @@ class Annotator : public mojom::Annotator {
struct ServerRequestInfo {
ServerRequestInfo(const std::string& source_id,
bool desc_requested,
+ bool icon_requested,
const std::string& desc_lang_tag,
const std::vector<uint8_t>& image_bytes);
ServerRequestInfo(const ServerRequestInfo& other) = delete;
@@ -146,6 +157,7 @@ class Annotator : public mojom::Annotator {
std::string source_id; // The URL or hashed data URI for the image.
bool desc_requested; // Whether or not descriptions have been requested.
+ bool icon_requested; // Whether or not icons have been requested.
std::string desc_lang_tag; // The language in which descriptions have been
// requested.
@@ -167,6 +179,11 @@ class Annotator : public mojom::Annotator {
// the description model).
static bool IsWithinDescPolicy(int32_t width, int32_t height);
+ // Returns true if the given dimensions fit the policy of the icon
+ // backend (i.e. the image has size / shape on which it is acceptable to run
+ // the icon model).
+ static bool IsWithinIconPolicy(int32_t width, int32_t height);
+
// Constructs and returns a JSON object containing an request for the
// given images.
static std::string FormatJsonRequest(
diff --git a/chromium/services/image_annotation/annotator_unittest.cc b/chromium/services/image_annotation/annotator_unittest.cc
index bd6f224ca46..39c02b202de 100644
--- a/chromium/services/image_annotation/annotator_unittest.cc
+++ b/chromium/services/image_annotation/annotator_unittest.cc
@@ -65,7 +65,8 @@ constexpr char kTemplateRequest[] = R"(
"imageBytes": "%s",
"engineParameters": [
{"ocrParameters": {}},
- {"descriptionParameters": {}}
+ {"descriptionParameters": {}},
+ {"iconParameters": {}}
]
}]
}
@@ -80,7 +81,8 @@ constexpr char kBatchRequest[] = R"(
"imageBytes": "BwgJ",
"engineParameters": [
{"ocrParameters": {}},
- {"descriptionParameters": {}}
+ {"descriptionParameters": {}},
+ {"iconParameters": {}}
]
},
{
@@ -88,7 +90,8 @@ constexpr char kBatchRequest[] = R"(
"imageBytes": "BAUG",
"engineParameters": [
{"ocrParameters": {}},
- {"descriptionParameters": {}}
+ {"descriptionParameters": {}},
+ {"iconParameters": {}}
]
},
{
@@ -96,7 +99,8 @@ constexpr char kBatchRequest[] = R"(
"imageBytes": "AQID",
"engineParameters": [
{"ocrParameters": {}},
- {"descriptionParameters": {}}
+ {"descriptionParameters": {}},
+ {"iconParameters": {}}
]
}
]
@@ -239,6 +243,9 @@ class TestImageProcessor : public mojom::ImageProcessor {
public:
TestImageProcessor() = default;
+ TestImageProcessor(const TestImageProcessor&) = delete;
+ TestImageProcessor& operator=(const TestImageProcessor&) = delete;
+
mojo::PendingRemote<mojom::ImageProcessor> GetPendingRemote() {
mojo::PendingRemote<mojom::ImageProcessor> remote;
receivers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
@@ -260,8 +267,6 @@ class TestImageProcessor : public mojom::ImageProcessor {
std::vector<GetJpgImageDataCallback> callbacks_;
mojo::ReceiverSet<mojom::ImageProcessor> receivers_;
-
- DISALLOW_COPY_AND_ASSIGN(TestImageProcessor);
};
// A class that supports test URL loading for the "server" use case: where
@@ -275,6 +280,10 @@ class TestServerURLLoaderFactory {
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&loader_factory_)) {}
+ TestServerURLLoaderFactory(const TestServerURLLoaderFactory&) = delete;
+ TestServerURLLoaderFactory& operator=(const TestServerURLLoaderFactory&) =
+ delete;
+
const std::vector<network::TestURLLoaderFactory::PendingRequest>& requests() {
return *loader_factory_.pending_requests();
}
@@ -349,8 +358,6 @@ class TestServerURLLoaderFactory {
const std::string server_url_prefix_;
network::TestURLLoaderFactory loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_loader_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TestServerURLLoaderFactory);
};
// Returns a "canonically" formatted version of a JSON string by parsing and
@@ -1860,7 +1867,8 @@ TEST(AnnotatorTest, DescPolicy) {
"imageId": "https://www.example.com/image2.jpg",
"imageBytes": "BAUG",
"engineParameters": [
- {"ocrParameters": {}}
+ {"ocrParameters": {}},
+ {"iconParameters": {}}
]
},
{
@@ -1868,7 +1876,8 @@ TEST(AnnotatorTest, DescPolicy) {
"imageBytes": "AQID",
"engineParameters": [
{"ocrParameters": {}},
- {"descriptionParameters": {}}
+ {"descriptionParameters": {}},
+ {"iconParameters": {}}
]
}
]
@@ -2048,7 +2057,8 @@ TEST(AnnotatorTest, DescLanguage) {
"imageId": "https://www.example.com/image2.jpg en",
"imageBytes": "BAUG",
"engineParameters": [
- {"ocrParameters": {}}
+ {"ocrParameters": {}},
+ {"iconParameters": {}}
]
},
{
@@ -2060,7 +2070,8 @@ TEST(AnnotatorTest, DescLanguage) {
"descriptionParameters": {
"preferredLanguages": ["it"]
}
- }
+ },
+ {"iconParameters": {}}
]
},
{
@@ -2072,7 +2083,8 @@ TEST(AnnotatorTest, DescLanguage) {
"descriptionParameters": {
"preferredLanguages": ["fr"]
}
- }
+ },
+ {"iconParameters": {}}
]
}
]
@@ -2224,7 +2236,8 @@ TEST(AnnotatorTest, LanguageFallback) {
"descriptionParameters": {
"preferredLanguages": ["en"]
}
- }
+ },
+ {"iconParameters": {}}
]
}
]
diff --git a/chromium/services/image_annotation/image_annotation_metrics.cc b/chromium/services/image_annotation/image_annotation_metrics.cc
index a81e2ee5fb1..376e4864b5c 100644
--- a/chromium/services/image_annotation/image_annotation_metrics.cc
+++ b/chromium/services/image_annotation/image_annotation_metrics.cc
@@ -86,6 +86,11 @@ void ReportImageRequestIncludesDesc(const bool includes_desc) {
includes_desc);
}
+void ReportImageRequestIncludesIcon(const bool includes_icon) {
+ UMA_HISTOGRAM_BOOLEAN(metrics_internal::kImageRequestIncludesIcon,
+ includes_icon);
+}
+
void ReportServerRequestSizeKB(const size_t size_kb) {
// Use a custom memory histogram with ~10 buckets per order of magnitude
// between 1KB and 30MB.
diff --git a/chromium/services/image_annotation/image_annotation_metrics.h b/chromium/services/image_annotation/image_annotation_metrics.h
index e12c1136253..561dd4df48e 100644
--- a/chromium/services/image_annotation/image_annotation_metrics.h
+++ b/chromium/services/image_annotation/image_annotation_metrics.h
@@ -39,6 +39,8 @@ constexpr char kServerLatency[] =
"ImageAnnotationService.AccessibilityV1.ServerLatencyMs";
constexpr char kImageRequestIncludesDesc[] =
"ImageAnnotationService.AccessibilityV1.ImageRequestIncludesDesc";
+constexpr char kImageRequestIncludesIcon[] =
+ "ImageAnnotationService.AccessibilityV1.ImageRequestIncludesIcon";
constexpr char kServerRequestSize[] =
"ImageAnnotationService.AccessibilityV1.ServerRequestSizeKB";
constexpr char kServerResponseSize[] =
@@ -100,6 +102,11 @@ void ReportServerLatency(base::TimeDelta latency);
// engine policy (e.g. are too small) will not.
void ReportImageRequestIncludesDesc(bool includes_desc);
+// Report whether or not a request for image annotation includes parameters for
+// the icon engine; requests for images that violate the description
+// engine policy (e.g. are too large) will not.
+void ReportImageRequestIncludesIcon(bool includes_icon);
+
// Report the size of the request sent to the image annotation server.
void ReportServerRequestSizeKB(size_t size_kb);
diff --git a/chromium/services/image_annotation/image_annotation_service.h b/chromium/services/image_annotation/image_annotation_service.h
index b2e7d333ab8..25d0140ea58 100644
--- a/chromium/services/image_annotation/image_annotation_service.h
+++ b/chromium/services/image_annotation/image_annotation_service.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/field_trial_params.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/services/image_annotation/public/cpp/image_processor.cc b/chromium/services/image_annotation/public/cpp/image_processor.cc
index 7167140cbb6..64643d42af4 100644
--- a/chromium/services/image_annotation/public/cpp/image_processor.cc
+++ b/chromium/services/image_annotation/public/cpp/image_processor.cc
@@ -6,8 +6,8 @@
#include "base/bind.h"
#include "base/task/post_task.h"
+#include "base/task/task_runner_util.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
#include "services/image_annotation/image_annotation_metrics.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImage.h"
diff --git a/chromium/services/image_annotation/public/cpp/image_processor.h b/chromium/services/image_annotation/public/cpp/image_processor.h
index 7b22e363176..20967e3d6ea 100644
--- a/chromium/services/image_annotation/public/cpp/image_processor.h
+++ b/chromium/services/image_annotation/public/cpp/image_processor.h
@@ -7,9 +7,8 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/image_annotation/public/mojom/image_annotation.mojom.h"
diff --git a/chromium/services/image_annotation/public/mojom/image_annotation.mojom b/chromium/services/image_annotation/public/mojom/image_annotation.mojom
index 102ef42d22d..b54bd3aef5c 100644
--- a/chromium/services/image_annotation/public/mojom/image_annotation.mojom
+++ b/chromium/services/image_annotation/public/mojom/image_annotation.mojom
@@ -27,6 +27,7 @@ enum AnnotationType {
kOcr = 1,
kLabel = 2,
kCaption = 3,
+ kIcon = 4,
};
// One annotation for an image.
@@ -43,6 +44,8 @@ union AnnotateImageResult {
array<Annotation> annotations;
};
+// This interface is used inside Blink renderers and received within the
+// ImageAnnotationService to return image annotations.
interface Annotator {
// Requests a11y annotations (i.e. OCR, labels) for the given image.
//
diff --git a/chromium/services/media_session/audio_focus_manager_unittest.cc b/chromium/services/media_session/audio_focus_manager_unittest.cc
index bc26336f1b2..574131e0458 100644
--- a/chromium/services/media_session/audio_focus_manager_unittest.cc
+++ b/chromium/services/media_session/audio_focus_manager_unittest.cc
@@ -41,6 +41,9 @@ class AudioFocusManagerTest
public:
AudioFocusManagerTest() = default;
+ AudioFocusManagerTest(const AudioFocusManagerTest&) = delete;
+ AudioFocusManagerTest& operator=(const AudioFocusManagerTest&) = delete;
+
void SetUp() override {
// Create an instance of the MediaSessionService.
service_ = std::make_unique<MediaSessionServiceImpl>();
@@ -281,8 +284,6 @@ class AudioFocusManagerTest
mojo::Remote<mojom::MediaControllerManager> controller_manager_remote_;
base::test::ScopedPowerMonitorTestSource power_source_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioFocusManagerTest);
};
INSTANTIATE_TEST_SUITE_P(
diff --git a/chromium/services/media_session/audio_focus_request.h b/chromium/services/media_session/audio_focus_request.h
index 7dc3a53ce72..9fe8100c55a 100644
--- a/chromium/services/media_session/audio_focus_request.h
+++ b/chromium/services/media_session/audio_focus_request.h
@@ -6,7 +6,6 @@
#define SERVICES_MEDIA_SESSION_AUDIO_FOCUS_REQUEST_H_
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/media_session/media_controller.cc b/chromium/services/media_session/media_controller.cc
index 6ee69305676..ab83bf15647 100644
--- a/chromium/services/media_session/media_controller.cc
+++ b/chromium/services/media_session/media_controller.cc
@@ -8,6 +8,7 @@
#include "base/containers/contains.h"
#include "base/containers/cxx20_erase.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/audio_focus_request.h"
@@ -82,7 +83,7 @@ class MediaController::ImageObserverHolder {
media_session::MediaImageManager manager_;
- MediaController* const owner_;
+ const raw_ptr<MediaController> owner_;
mojom::MediaSessionImageType const type_;
diff --git a/chromium/services/media_session/media_controller.h b/chromium/services/media_session/media_controller.h
index 8c4d74359a3..8e02dc4f322 100644
--- a/chromium/services/media_session/media_controller.h
+++ b/chromium/services/media_session/media_controller.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/containers/flat_map.h"
+#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
@@ -112,7 +113,7 @@ class MediaController : public mojom::MediaController,
session_images_;
// Raw pointer to the media session we are controlling.
- AudioFocusRequest* session_ = nullptr;
+ raw_ptr<AudioFocusRequest> session_ = nullptr;
// Observers that are observing |this|.
mojo::RemoteSet<mojom::MediaControllerObserver> observers_;
diff --git a/chromium/services/media_session/media_controller_unittest.cc b/chromium/services/media_session/media_controller_unittest.cc
index 06772ce8a64..9cd256a9826 100644
--- a/chromium/services/media_session/media_controller_unittest.cc
+++ b/chromium/services/media_session/media_controller_unittest.cc
@@ -28,6 +28,9 @@ class MediaControllerTest : public testing::Test {
public:
MediaControllerTest() = default;
+ MediaControllerTest(const MediaControllerTest&) = delete;
+ MediaControllerTest& operator=(const MediaControllerTest&) = delete;
+
void SetUp() override {
// Create an instance of the MediaSessionService and bind some interfaces.
service_ = std::make_unique<MediaSessionServiceImpl>();
@@ -73,8 +76,6 @@ class MediaControllerTest : public testing::Test {
mojo::Remote<mojom::AudioFocusManager> audio_focus_remote_;
mojo::Remote<mojom::MediaController> media_controller_remote_;
mojo::Remote<mojom::MediaControllerManager> controller_manager_remote_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaControllerTest);
};
TEST_F(MediaControllerTest, ActiveController_Suspend) {
diff --git a/chromium/services/media_session/media_session_service_impl.h b/chromium/services/media_session/media_session_service_impl.h
index 6e45cb8ad8c..cc80416c2ad 100644
--- a/chromium/services/media_session/media_session_service_impl.h
+++ b/chromium/services/media_session/media_session_service_impl.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/media_session/public/cpp/media_session_service.h"
diff --git a/chromium/services/media_session/media_session_service_impl_unittest.cc b/chromium/services/media_session/media_session_service_impl_unittest.cc
index 6b5fa83526a..0e4233ac82a 100644
--- a/chromium/services/media_session/media_session_service_impl_unittest.cc
+++ b/chromium/services/media_session/media_session_service_impl_unittest.cc
@@ -4,7 +4,6 @@
#include "services/media_session/media_session_service_impl.h"
-#include "base/macros.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/services/media_session/public/cpp/media_image_manager.h b/chromium/services/media_session/public/cpp/media_image_manager.h
index a4accdf9d66..65acd05fccc 100644
--- a/chromium/services/media_session/public/cpp/media_image_manager.h
+++ b/chromium/services/media_session/public/cpp/media_image_manager.h
@@ -9,7 +9,6 @@
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "services/media_session/public/cpp/media_image.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chromium/services/media_session/public/cpp/media_image_manager_unittest.cc b/chromium/services/media_session/public/cpp/media_image_manager_unittest.cc
index 5eaa642bba4..e3efd6ed14f 100644
--- a/chromium/services/media_session/public/cpp/media_image_manager_unittest.cc
+++ b/chromium/services/media_session/public/cpp/media_image_manager_unittest.cc
@@ -7,7 +7,6 @@
#include <string>
#include "base/hash/hash.h"
-#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,6 +23,9 @@ class MediaImageManagerTest : public testing::Test {
public:
MediaImageManagerTest() = default;
+ MediaImageManagerTest(const MediaImageManagerTest&) = delete;
+ MediaImageManagerTest& operator=(const MediaImageManagerTest&) = delete;
+
void SetUp() override {
manager_ = std::make_unique<MediaImageManager>(kMinSize, kIdealSize);
}
@@ -32,8 +34,6 @@ class MediaImageManagerTest : public testing::Test {
private:
std::unique_ptr<MediaImageManager> manager_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaImageManagerTest);
};
TEST_F(MediaImageManagerTest, CheckExpectedImageExtensionHashes) {
diff --git a/chromium/services/media_session/public/cpp/test/BUILD.gn b/chromium/services/media_session/public/cpp/test/BUILD.gn
index c55e8b145f4..548c29d9df0 100644
--- a/chromium/services/media_session/public/cpp/test/BUILD.gn
+++ b/chromium/services/media_session/public/cpp/test/BUILD.gn
@@ -3,11 +3,17 @@
# found in the LICENSE file.
component("test_support") {
+ testonly = true
+
output_name = "media_session_test_support_cpp"
sources = [
"audio_focus_test_util.cc",
"audio_focus_test_util.h",
+ "mock_audio_focus_manager.cc",
+ "mock_audio_focus_manager.h",
+ "mock_media_controller_manager.cc",
+ "mock_media_controller_manager.h",
"mock_media_session.cc",
"mock_media_session.h",
"test_media_controller.cc",
@@ -18,6 +24,7 @@ component("test_support") {
"//base",
"//services/media_session/public/cpp",
"//services/media_session/public/mojom",
+ "//testing/gmock",
]
defines = [ "IS_MEDIA_SESSION_TEST_SUPPORT_CPP_IMPL" ]
diff --git a/chromium/services/metrics/public/cpp/delegating_ukm_recorder.h b/chromium/services/metrics/public/cpp/delegating_ukm_recorder.h
index e431f920a15..70885c017fe 100644
--- a/chromium/services/metrics/public/cpp/delegating_ukm_recorder.h
+++ b/chromium/services/metrics/public/cpp/delegating_ukm_recorder.h
@@ -8,8 +8,8 @@
#include <set>
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/sequenced_task_runner.h"
#include "services/metrics/public/cpp/metrics_export.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/mojom/ukm_interface.mojom.h"
diff --git a/chromium/services/metrics/public/cpp/metrics_utils.cc b/chromium/services/metrics/public/cpp/metrics_utils.cc
index b23113376af..675dbe3ab1b 100644
--- a/chromium/services/metrics/public/cpp/metrics_utils.cc
+++ b/chromium/services/metrics/public/cpp/metrics_utils.cc
@@ -61,6 +61,8 @@ int64_t GetLinearBucketMin(double sample, int32_t bucket_size) {
}
int64_t METRICS_EXPORT GetSemanticBucketMinForDurationTiming(int64_t sample) {
+ if (sample == 0)
+ return 0;
DCHECK(sample > 0);
const int64_t kMillisecondsPerMinute = 60 * 1000;
const int64_t kMillisecondsPerTenMinutes = 10 * kMillisecondsPerMinute;
diff --git a/chromium/services/metrics/public/cpp/ukm_entry_builder.h b/chromium/services/metrics/public/cpp/ukm_entry_builder.h
index f5b0845f906..437c55634cc 100644
--- a/chromium/services/metrics/public/cpp/ukm_entry_builder.h
+++ b/chromium/services/metrics/public/cpp/ukm_entry_builder.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_H_
#define SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_H_
-#include "base/macros.h"
#include "services/metrics/public/cpp/metrics_export.h"
#include "services/metrics/public/cpp/ukm_entry_builder_base.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
diff --git a/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h b/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h
index cc8cdb27aef..a50249a5af3 100644
--- a/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h
+++ b/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_BASE_H_
#define SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_BASE_H_
-#include "base/macros.h"
#include "services/metrics/public/cpp/metrics_export.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
diff --git a/chromium/services/metrics/public/cpp/ukm_recorder.h b/chromium/services/metrics/public/cpp/ukm_recorder.h
index 5b53111fd4d..0bfcc0b8e90 100644
--- a/chromium/services/metrics/public/cpp/ukm_recorder.h
+++ b/chromium/services/metrics/public/cpp/ukm_recorder.h
@@ -7,7 +7,6 @@
#include "base/callback.h"
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "services/metrics/public/cpp/metrics_export.h"
#include "services/metrics/public/cpp/ukm_source.h"
@@ -47,6 +46,7 @@ enum class AppType {
kExtension,
kChromeApp,
kCrostini,
+ kBorealis,
};
namespace internal {
@@ -79,8 +79,8 @@ class METRICS_EXPORT UkmRecorder {
// Add an entry to the UkmEntry list.
virtual void AddEntry(mojom::UkmEntryPtr entry) = 0;
- // Disables sampling for testing purposes.
- virtual void DisableSamplingForTesting() {}
+ // Controls sampling for testing purposes. Sampling is 1-in-N (N==rate).
+ virtual void SetSamplingForTesting(int rate) {}
protected:
// Type-safe wrappers for Update<X> functions.
diff --git a/chromium/services/metrics/public/cpp/ukm_source.h b/chromium/services/metrics/public/cpp/ukm_source.h
index 3ce2989ff3a..8699aeb5f89 100644
--- a/chromium/services/metrics/public/cpp/ukm_source.h
+++ b/chromium/services/metrics/public/cpp/ukm_source.h
@@ -8,7 +8,6 @@
#include <map>
#include <vector>
-#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
diff --git a/chromium/services/metrics/ukm_api.md b/chromium/services/metrics/ukm_api.md
index 6fe5eeaf3e1..23401f21b2a 100644
--- a/chromium/services/metrics/ukm_api.md
+++ b/chromium/services/metrics/ukm_api.md
@@ -219,7 +219,7 @@ void DidGetBackgroundSourceId(absl::optional<ukm::SourceId> source_id) {
}
```
-For the remaining cases you may need to temporarily create your own IDs and associate the URL with them. However we currently prefer that this method is not used, and if you need to setup the URL yourself, please email us first at ukm-team@google.com.
+For the remaining cases you may need to temporarily create your own IDs and associate the URL with them. However we currently prefer that this method is not used, and if you need to setup the URL yourself, please email the OWNERS of components/ukm.
Example:
```cpp
@@ -255,6 +255,10 @@ Build Chromium and run it with '--force-enable-metrics-reporting --metrics-uploa
You can pass your code a TestUkmRecorder (see [//components/ukm/test_ukm_recorder.h](https://cs.chromium.org/chromium/src/components/ukm/test_ukm_recorder.h)) and then use the methods it provides to test that your data records correctly.
+## Adding UKMs every report
+
+Certain information may be useful to be included on every UKM upload. This may be applicable if your information is always "available" in some sense, as opposed to triggered/computed at a particular instance, which is the default. In this case, the best way to proceed is to setup a [MetricsProvider](https://source.chromium.org/chromium/src/components/metrics/metrics_provider.h). The new Provider should implement the ProvideCurrentSessionUKMData() method. Record a UKM Event within that implementation, and it will be recorded exactly once per UKM report, immediately before the information is uploaded.
+
## Recording Information about Subframes URLs via Categorization
The UKM infrastructure primarily supports recording metrics tied with navigation URLs as that is the basis of the consent model. As there is desire for information related to URLs loaded within a page itself (i.e. subframe URLs), here we describe an approach for how to record this via categorization.
diff --git a/chromium/services/metrics/ukm_recorder_interface.h b/chromium/services/metrics/ukm_recorder_interface.h
index 19084b4f89b..a88bbc18162 100644
--- a/chromium/services/metrics/ukm_recorder_interface.h
+++ b/chromium/services/metrics/ukm_recorder_interface.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_METRICS_UKM_RECORDER_INTERFACE_H_
#define SERVICES_METRICS_UKM_RECORDER_INTERFACE_H_
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/metrics/public/mojom/ukm_interface.mojom.h"
@@ -32,7 +33,7 @@ class UkmRecorderInterface : public ukm::mojom::UkmRecorderInterface {
void AddEntry(ukm::mojom::UkmEntryPtr entry) override;
void UpdateSourceURL(int64_t source_id, const std::string& url) override;
- ukm::UkmRecorder* ukm_recorder_;
+ raw_ptr<ukm::UkmRecorder> ukm_recorder_;
};
} // namespace metrics
diff --git a/chromium/services/network/BUILD.gn b/chromium/services/network/BUILD.gn
index 005c7686255..bf42c742547 100644
--- a/chromium/services/network/BUILD.gn
+++ b/chromium/services/network/BUILD.gn
@@ -85,16 +85,6 @@ component("network_service") {
"origin_policy/origin_policy_parsed_header.h",
"origin_policy/origin_policy_parser.cc",
"origin_policy/origin_policy_parser.h",
- "p2p/socket.cc",
- "p2p/socket.h",
- "p2p/socket_manager.cc",
- "p2p/socket_manager.h",
- "p2p/socket_tcp.cc",
- "p2p/socket_tcp.h",
- "p2p/socket_throttler.cc",
- "p2p/socket_throttler.h",
- "p2p/socket_udp.cc",
- "p2p/socket_udp.h",
"pending_callback_chain.cc",
"pending_callback_chain.h",
"private_network_access_check.cc",
@@ -188,6 +178,21 @@ component("network_service") {
"web_transport.h",
]
+ if (is_p2p_enabled) {
+ sources += [
+ "p2p/socket.cc",
+ "p2p/socket.h",
+ "p2p/socket_manager.cc",
+ "p2p/socket_manager.h",
+ "p2p/socket_tcp.cc",
+ "p2p/socket_tcp.h",
+ "p2p/socket_throttler.cc",
+ "p2p/socket_throttler.h",
+ "p2p/socket_udp.cc",
+ "p2p/socket_udp.h",
+ ]
+ }
+
if (enable_mdns) {
sources += [
"mdns_responder.cc",
@@ -233,7 +238,7 @@ component("network_service") {
"//components/os_crypt",
"//components/prefs",
"//components/web_package",
- "//jingle:fake_ssl_socket",
+ "//jingle/glue:fake_ssl_socket",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//net",
@@ -247,7 +252,6 @@ component("network_service") {
"//services/network/trust_tokens",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
- "//third_party/webrtc_overrides:webrtc_component",
"//url",
]
@@ -265,6 +269,10 @@ component("network_service") {
"expect_ct_reporter.h",
"sct_auditing/sct_auditing_cache.cc",
"sct_auditing/sct_auditing_cache.h",
+ "sct_auditing/sct_auditing_handler.cc",
+ "sct_auditing/sct_auditing_handler.h",
+ "sct_auditing/sct_auditing_reporter.cc",
+ "sct_auditing/sct_auditing_reporter.h",
]
deps += [
"//components/certificate_transparency",
@@ -272,6 +280,10 @@ component("network_service") {
]
}
+ if (is_p2p_enabled) {
+ deps += [ "//third_party/webrtc_overrides:webrtc_component" ]
+ }
+
if (is_android) {
deps += [
"//crypto",
@@ -336,10 +348,6 @@ source_set("tests") {
"origin_policy/origin_policy_manager_unittest.cc",
"origin_policy/origin_policy_parsed_header_unittest.cc",
"origin_policy/origin_policy_parser_unittest.cc",
- "p2p/socket_tcp_unittest.cc",
- "p2p/socket_test_utils.cc",
- "p2p/socket_test_utils.h",
- "p2p/socket_udp_unittest.cc",
"pending_callback_chain_unittest.cc",
"private_network_access_check_unittest.cc",
"proxy_auto_config_library_unittest.cc",
@@ -370,6 +378,15 @@ source_set("tests") {
"web_transport_unittest.cc",
]
+ if (is_p2p_enabled) {
+ sources += [
+ "p2p/socket_tcp_unittest.cc",
+ "p2p/socket_test_utils.cc",
+ "p2p/socket_test_utils.h",
+ "p2p/socket_udp_unittest.cc",
+ ]
+ }
+
if (enable_mdns) {
sources += [ "mdns_responder_unittest.cc" ]
}
@@ -389,7 +406,6 @@ source_set("tests") {
"//net/tools/testserver/",
"//services/test/data",
"//third_party/pywebsocket3/src/mod_pywebsocket/",
- "//third_party/tlslite/",
]
}
@@ -409,11 +425,12 @@ source_set("tests") {
"//components/network_session_configurator/browser",
"//components/prefs:test_support",
"//components/variations:test_support",
- "//components/web_package:test_support",
+ "//components/web_package",
"//crypto",
- "//jingle:fake_ssl_socket",
+ "//jingle/glue:fake_ssl_socket",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
+ "//mojo/public/cpp/test_support:test_utils",
"//net",
"//net:extras",
"//net:quic_test_tools",
diff --git a/chromium/services/network/OWNERS b/chromium/services/network/OWNERS
index 0f2bce7c445..62d6e9f8d81 100644
--- a/chromium/services/network/OWNERS
+++ b/chromium/services/network/OWNERS
@@ -23,7 +23,7 @@ per-file sec_header_helpers*=mkwst@chromium.org
per-file expect_ct_reporter*=estark@chromium.org
-per-file cert_verifier_with_trust_anchors*=file://chromeos/policy/OWNERS
+per-file cert_verifier_with_trust_anchors*=file://ash/components/policy/OWNERS
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/network/cert_verifier_with_trust_anchors.h b/chromium/services/network/cert_verifier_with_trust_anchors.h
index 26be41c5d0d..dc824d36de5 100644
--- a/chromium/services/network/cert_verifier_with_trust_anchors.h
+++ b/chromium/services/network/cert_verifier_with_trust_anchors.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "net/base/completion_once_callback.h"
diff --git a/chromium/services/network/chunked_data_pipe_upload_data_stream.h b/chromium/services/network/chunked_data_pipe_upload_data_stream.h
index 4eded028af5..1c0fda4233e 100644
--- a/chromium/services/network/chunked_data_pipe_upload_data_stream.h
+++ b/chromium/services/network/chunked_data_pipe_upload_data_stream.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/network/chunked_data_pipe_upload_data_stream_unittest.cc b/chromium/services/network/chunked_data_pipe_upload_data_stream_unittest.cc
index 54694c1fd59..eeb80cfae45 100644
--- a/chromium/services/network/chunked_data_pipe_upload_data_stream_unittest.cc
+++ b/chromium/services/network/chunked_data_pipe_upload_data_stream_unittest.cc
@@ -9,7 +9,6 @@
#include <limits>
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
diff --git a/chromium/services/network/conditional_cache_deletion_helper.cc b/chromium/services/network/conditional_cache_deletion_helper.cc
index 9b533db4b67..1e583f11029 100644
--- a/chromium/services/network/conditional_cache_deletion_helper.cc
+++ b/chromium/services/network/conditional_cache_deletion_helper.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/http/http_cache.h"
#include "net/http/http_util.h"
@@ -71,7 +71,7 @@ void ConditionalCacheDeletionHelper::IterateOverEntries(
// won't be invalidated. Always close the previous entry so it does not
// leak.
if (previous_entry_) {
- if (condition_.Run(previous_entry_)) {
+ if (condition_.Run(previous_entry_.get())) {
previous_entry_->Doom();
}
previous_entry_->Close();
diff --git a/chromium/services/network/conditional_cache_deletion_helper.h b/chromium/services/network/conditional_cache_deletion_helper.h
index 71d69d1715e..3545f29558d 100644
--- a/chromium/services/network/conditional_cache_deletion_helper.h
+++ b/chromium/services/network/conditional_cache_deletion_helper.h
@@ -8,8 +8,9 @@
#include <memory>
#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner_helpers.h"
+#include "base/task/sequenced_task_runner_helpers.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/disk_cache.h"
#include "url/gurl.h"
@@ -57,7 +58,7 @@ class ConditionalCacheDeletionHelper {
base::OnceClosure completion_callback_;
std::unique_ptr<disk_cache::Backend::Iterator> iterator_;
- disk_cache::Entry* previous_entry_ = nullptr;
+ raw_ptr<disk_cache::Entry> previous_entry_ = nullptr;
base::WeakPtrFactory<ConditionalCacheDeletionHelper> weak_factory_{this};
};
diff --git a/chromium/services/network/cookie_access_delegate_impl.cc b/chromium/services/network/cookie_access_delegate_impl.cc
index 8e875330139..bbddfbc868f 100644
--- a/chromium/services/network/cookie_access_delegate_impl.cc
+++ b/chromium/services/network/cookie_access_delegate_impl.cc
@@ -80,6 +80,14 @@ bool CookieAccessDelegateImpl::IsInNontrivialFirstPartySet(
first_party_sets_->IsInNontrivialFirstPartySet(site);
}
+absl::optional<net::SchemefulSite>
+CookieAccessDelegateImpl::FindFirstPartySetOwner(
+ const net::SchemefulSite& site) const {
+ if (!first_party_sets_)
+ return absl::nullopt;
+ return first_party_sets_->FindOwner(site);
+}
+
base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>
CookieAccessDelegateImpl::RetrieveFirstPartySets() const {
if (!first_party_sets_)
diff --git a/chromium/services/network/cookie_access_delegate_impl.h b/chromium/services/network/cookie_access_delegate_impl.h
index 0d94904a3a2..79b71fcc418 100644
--- a/chromium/services/network/cookie_access_delegate_impl.h
+++ b/chromium/services/network/cookie_access_delegate_impl.h
@@ -6,6 +6,7 @@
#define SERVICES_NETWORK_COOKIE_ACCESS_DELEGATE_IMPL_H_
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "net/cookies/cookie_access_delegate.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/same_party_context.h"
@@ -58,13 +59,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieAccessDelegateImpl
const std::set<net::SchemefulSite>& party_context) const override;
bool IsInNontrivialFirstPartySet(
const net::SchemefulSite& site) const override;
+ absl::optional<net::SchemefulSite> FindFirstPartySetOwner(
+ const net::SchemefulSite& site) const override;
base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>
RetrieveFirstPartySets() const override;
private:
const mojom::CookieAccessDelegateType type_;
- const CookieSettings* const cookie_settings_;
- const FirstPartySets* const first_party_sets_;
+ const raw_ptr<const CookieSettings> cookie_settings_;
+ const raw_ptr<const FirstPartySets> first_party_sets_;
};
} // namespace network
diff --git a/chromium/services/network/cookie_manager.cc b/chromium/services/network/cookie_manager.cc
index c09630b6395..abce7aed59c 100644
--- a/chromium/services/network/cookie_manager.cc
+++ b/chromium/services/network/cookie_manager.cc
@@ -92,7 +92,7 @@ void CookieManager::GetAllCookiesWithAccessSemantics(
void CookieManager::GetCookieList(
const GURL& url,
const net::CookieOptions& cookie_options,
- const net::CookiePartitionKeychain& cookie_partition_keychain,
+ const net::CookiePartitionKeyCollection& cookie_partition_key_collection,
GetCookieListCallback callback) {
#if !defined(OS_IOS)
if (g_crash_on_get_cookie_list)
@@ -100,23 +100,60 @@ void CookieManager::GetCookieList(
#endif
cookie_store_->GetCookieListWithOptionsAsync(
- url, cookie_options, cookie_partition_keychain, std::move(callback));
+ url, cookie_options,
+ cookie_partition_key_collection.FirstPartySetify(
+ cookie_store_->cookie_access_delegate()),
+ std::move(callback));
}
void CookieManager::SetCanonicalCookie(const net::CanonicalCookie& cookie,
const GURL& source_url,
const net::CookieOptions& cookie_options,
SetCanonicalCookieCallback callback) {
- cookie_store_->SetCanonicalCookieAsync(
- std::make_unique<net::CanonicalCookie>(cookie), source_url,
- cookie_options, std::move(callback));
+ std::unique_ptr<net::CanonicalCookie> cookie_ptr =
+ std::make_unique<net::CanonicalCookie>(cookie);
+ if (absl::optional<net::CookiePartitionKey> cookie_partition_key =
+ cookie.PartitionKey()) {
+ absl::optional<net::CookiePartitionKey> fps_cookie_partition_key =
+ net::CookieAccessDelegate::FirstPartySetifyPartitionKey(
+ cookie_store_->cookie_access_delegate(),
+ cookie_partition_key.value());
+ if (fps_cookie_partition_key != cookie_partition_key) {
+ cookie_ptr = net::CanonicalCookie::FromStorage(
+ cookie.Name(), cookie.Value(), cookie.Domain(), cookie.Path(),
+ cookie.CreationDate(), cookie.ExpiryDate(), cookie.LastAccessDate(),
+ cookie.IsSecure(), cookie.IsHttpOnly(), cookie.SameSite(),
+ cookie.Priority(), cookie.IsSameParty(), fps_cookie_partition_key,
+ cookie.SourceScheme(), cookie.SourcePort());
+ if (!cookie_ptr) {
+ std::move(callback).Run(
+ net::CookieAccessResult(net::CookieInclusionStatus(
+ net::CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_FAILURE_TO_STORE)));
+ return;
+ }
+ }
+ }
+ cookie_store_->SetCanonicalCookieAsync(std::move(cookie_ptr), source_url,
+ cookie_options, std::move(callback));
}
void CookieManager::DeleteCanonicalCookie(
const net::CanonicalCookie& cookie,
DeleteCanonicalCookieCallback callback) {
+ std::unique_ptr<net::CanonicalCookie> cookie_ptr =
+ std::make_unique<net::CanonicalCookie>(cookie);
+ if (absl::optional<net::CookiePartitionKey> cookie_partition_key =
+ cookie.PartitionKey()) {
+ absl::optional<net::CookiePartitionKey> fps_cookie_partition_key =
+ net::CookieAccessDelegate::FirstPartySetifyPartitionKey(
+ cookie_store_->cookie_access_delegate(),
+ cookie_partition_key.value());
+ if (fps_cookie_partition_key && !cookie_partition_key->site().opaque())
+ DCHECK_EQ(cookie_partition_key.value(), fps_cookie_partition_key.value());
+ }
cookie_store_->DeleteCanonicalCookieAsync(
- cookie,
+ *cookie_ptr,
base::BindOnce(
[](DeleteCanonicalCookieCallback callback, uint32_t num_deleted) {
std::move(callback).Run(num_deleted > 0);
diff --git a/chromium/services/network/cookie_manager.h b/chromium/services/network/cookie_manager.h
index 3c4bcdb3d9f..bb988d98297 100644
--- a/chromium/services/network/cookie_manager.h
+++ b/chromium/services/network/cookie_manager.h
@@ -10,7 +10,7 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "components/content_settings/core/common/content_settings.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -65,7 +65,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager
void GetCookieList(
const GURL& url,
const net::CookieOptions& cookie_options,
- const net::CookiePartitionKeychain& cookie_partition_keychain,
+ const net::CookiePartitionKeyCollection& cookie_partition_key_collection,
GetCookieListCallback callback) override;
void SetCanonicalCookie(const net::CanonicalCookie& cookie,
const GURL& source_url,
@@ -117,6 +117,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager
// State associated with a CookieChangeListener.
struct ListenerRegistration {
ListenerRegistration();
+
+ ListenerRegistration(const ListenerRegistration&) = delete;
+ ListenerRegistration& operator=(const ListenerRegistration&) = delete;
+
~ListenerRegistration();
// Translates a CookieStore change callback to a CookieChangeListener call.
@@ -127,14 +131,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager
// The observer receiving change notifications.
mojo::Remote<mojom::CookieChangeListener> listener;
-
- DISALLOW_COPY_AND_ASSIGN(ListenerRegistration);
};
// Handles connection errors on change listener pipes.
void RemoveChangeListener(ListenerRegistration* registration);
- net::CookieStore* const cookie_store_;
+ const raw_ptr<net::CookieStore> cookie_store_;
scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store_;
mojo::ReceiverSet<mojom::CookieManager> receivers_;
std::vector<std::unique_ptr<ListenerRegistration>> listener_registrations_;
diff --git a/chromium/services/network/cookie_manager_unittest.cc b/chromium/services/network/cookie_manager_unittest.cc
index e34db7a7b2d..fea2731ec69 100644
--- a/chromium/services/network/cookie_manager_unittest.cc
+++ b/chromium/services/network/cookie_manager_unittest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/cxx17_backports.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/task/post_task.h"
@@ -121,11 +122,12 @@ class SynchronousCookieManager {
std::vector<net::CanonicalCookie> GetCookieList(
const GURL& url,
net::CookieOptions options,
- const net::CookiePartitionKeychain& cookie_partition_keychain) {
+ const net::CookiePartitionKeyCollection&
+ cookie_partition_key_collection) {
base::RunLoop run_loop;
std::vector<net::CanonicalCookie> cookies_out;
cookie_service_->GetCookieList(
- url, options, cookie_partition_keychain,
+ url, options, cookie_partition_key_collection,
base::BindLambdaForTesting(
[&run_loop, &cookies_out](
const net::CookieAccessResultList& cookies,
@@ -138,14 +140,15 @@ class SynchronousCookieManager {
}
// TODO(crbug.com/1225444): CookieManager should be able to see which cookies
- // are excluded because their partition key is not contained in the keychain.
+ // are excluded because their partition key is not contained in the
+ // key collection.
net::CookieAccessResultList GetExcludedCookieList(
const GURL& url,
net::CookieOptions options) {
base::RunLoop run_loop;
net::CookieAccessResultList cookies_out;
cookie_service_->GetCookieList(
- url, options, net::CookiePartitionKeychain::Todo(),
+ url, options, net::CookiePartitionKeyCollection::Todo(),
base::BindLambdaForTesting(
[&run_loop, &cookies_out](
const net::CookieAccessResultList& cookies,
@@ -301,7 +304,7 @@ class SynchronousCookieManager {
// No need to wrap Add*Listener and CloneInterface, since their use
// is purely async.
private:
- mojom::CookieManager* cookie_service_;
+ raw_ptr<mojom::CookieManager> cookie_service_;
uint32_t callback_counter_;
};
@@ -678,9 +681,9 @@ TEST_F(CookieManagerTest, GetCookieList) {
net::CookieOptions options;
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
- std::vector<net::CanonicalCookie> cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(2u, cookies.size());
std::sort(cookies.begin(), cookies.end(), &CompareCanonicalCookies);
@@ -732,9 +735,9 @@ TEST_F(CookieManagerTest, GetCookieListHttpOnly) {
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
EXPECT_TRUE(options.exclude_httponly());
- std::vector<net::CanonicalCookie> cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("C", cookies[0].Name());
@@ -748,9 +751,9 @@ TEST_F(CookieManagerTest, GetCookieListHttpOnly) {
// Retrieve with httponly cookies.
options.set_include_httponly();
- cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(2u, cookies.size());
std::sort(cookies.begin(), cookies.end(), &CompareCanonicalCookies);
@@ -793,9 +796,9 @@ TEST_F(CookieManagerTest, GetCookieListSameSite) {
net::CookieOptions::SameSiteCookieContext(
net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
options.same_site_cookie_context());
- std::vector<net::CanonicalCookie> cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("A", cookies[0].Name());
@@ -811,9 +814,9 @@ TEST_F(CookieManagerTest, GetCookieListSameSite) {
net::CookieOptions::SameSiteCookieContext(
net::CookieOptions::SameSiteCookieContext::ContextType::
SAME_SITE_LAX));
- cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(2u, cookies.size());
std::sort(cookies.begin(), cookies.end(), &CompareCanonicalCookies);
EXPECT_EQ("A", cookies[0].Name());
@@ -826,9 +829,9 @@ TEST_F(CookieManagerTest, GetCookieListSameSite) {
// Retrieve everything.
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
- cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(3u, cookies.size());
std::sort(cookies.begin(), cookies.end(), &CompareCanonicalCookies);
EXPECT_EQ("A", cookies[0].Name());
@@ -909,7 +912,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
// non-SameSite=None cookies are excluded.
EXPECT_THAT(
service_wrapper()->GetCookieList(cookie_url, options,
- net::CookiePartitionKeychain()),
+ net::CookiePartitionKeyCollection()),
UnorderedElementsAre(net::MatchesCookieWithName("nonSameParty-None")));
EXPECT_THAT(
@@ -927,7 +930,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
options.set_same_party_context(
net::SamePartyContext(net::SamePartyContext::Type::kSameParty));
EXPECT_THAT(service_wrapper()->GetCookieList(
- cookie_url, options, net::CookiePartitionKeychain()),
+ cookie_url, options, net::CookiePartitionKeyCollection()),
UnorderedElementsAre(
net::MatchesCookieWithName("SameParty-Unspecified"),
net::MatchesCookieWithName("SameParty-None"),
@@ -943,7 +946,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
EXPECT_THAT(service_wrapper()->GetCookieList(
- cookie_url, options, net::CookiePartitionKeychain()),
+ cookie_url, options, net::CookiePartitionKeyCollection()),
UnorderedElementsAre(
net::MatchesCookieWithName("SameParty-Unspecified"),
net::MatchesCookieWithName("SameParty-None"),
@@ -972,7 +975,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
// Cross-party, cross-site.
EXPECT_THAT(
service_wrapper()->GetCookieList(cookie_url, options,
- net::CookiePartitionKeychain()),
+ net::CookiePartitionKeyCollection()),
UnorderedElementsAre(net::MatchesCookieWithName("SameParty-None"),
net::MatchesCookieWithName("nonSameParty-None")));
@@ -989,7 +992,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
net::SamePartyContext(net::SamePartyContext::Type::kSameParty));
EXPECT_THAT(
service_wrapper()->GetCookieList(cookie_url, options,
- net::CookiePartitionKeychain()),
+ net::CookiePartitionKeyCollection()),
UnorderedElementsAre(net::MatchesCookieWithName("SameParty-None"),
net::MatchesCookieWithName("nonSameParty-None")));
EXPECT_THAT(
@@ -1004,7 +1007,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
EXPECT_THAT(service_wrapper()->GetCookieList(
- cookie_url, options, net::CookiePartitionKeychain()),
+ cookie_url, options, net::CookiePartitionKeyCollection()),
UnorderedElementsAre(
net::MatchesCookieWithName("SameParty-Unspecified"),
net::MatchesCookieWithName("SameParty-None"),
@@ -1017,7 +1020,7 @@ TEST_F(CookieManagerTest, GetCookieListSameParty) {
}
}
-TEST_F(CookieManagerTest, GetCookieListCookiePartitionKeychain) {
+TEST_F(CookieManagerTest, GetCookieListCookiePartitionKeyCollection) {
// Add unpartitioned cookie.
ASSERT_TRUE(SetCanonicalCookie(
*net::CanonicalCookie::CreateUnsafeCookieForTesting(
@@ -1059,28 +1062,30 @@ TEST_F(CookieManagerTest, GetCookieListCookiePartitionKeychain) {
GURL("https://www.c.com")))),
"https", true));
- // Test empty keychain.
- std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList(
- GURL("https://foo_host.com/with/path"),
- net::CookieOptions::MakeAllInclusive(), net::CookiePartitionKeychain());
+ // Test empty key_collection.
+ std::vector<net::CanonicalCookie> cookies =
+ service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
+ net::CookieOptions::MakeAllInclusive(),
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("__Host-A", cookies[0].Name());
- // Test keychain with single partition key.
+ // Test key_collection with single partition key.
cookies = service_wrapper()->GetCookieList(
GURL("https://foo_host.com/with/path"),
net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain(net::CookiePartitionKey::FromURLForTesting(
- GURL("https://subdomain.a.com"))));
+ net::CookiePartitionKeyCollection(
+ net::CookiePartitionKey::FromURLForTesting(
+ GURL("https://subdomain.a.com"))));
ASSERT_EQ(2u, cookies.size());
EXPECT_EQ("__Host-A", cookies[0].Name());
EXPECT_EQ("__Host-B", cookies[1].Name());
- // Test keychain with multiple partition keys.
+ // Test key_collection with multiple partition keys.
cookies = service_wrapper()->GetCookieList(
GURL("https://foo_host.com/with/path"),
net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain({
+ net::CookiePartitionKeyCollection({
net::CookiePartitionKey::FromURLForTesting(
GURL("https://subdomain.a.com")),
net::CookiePartitionKey::FromURLForTesting(
@@ -1091,11 +1096,11 @@ TEST_F(CookieManagerTest, GetCookieListCookiePartitionKeychain) {
EXPECT_EQ("__Host-B", cookies[1].Name());
EXPECT_EQ("__Host-C", cookies[2].Name());
- // Test keychain with all partition keys.
+ // Test key_collection with all partition keys.
cookies = service_wrapper()->GetCookieList(
GURL("https://foo_host.com/with/path"),
net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain::ContainsAll());
+ net::CookiePartitionKeyCollection::ContainsAll());
ASSERT_EQ(4u, cookies.size());
EXPECT_EQ("__Host-A", cookies[0].Name());
EXPECT_EQ("__Host-B", cookies[1].Name());
@@ -1120,9 +1125,9 @@ TEST_F(CookieManagerTest, GetCookieListAccessTime) {
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
options.set_do_not_update_access_time();
- std::vector<net::CanonicalCookie> cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("A", cookies[0].Name());
EXPECT_TRUE(cookies[0].LastAccessDate().is_null());
@@ -1131,9 +1136,9 @@ TEST_F(CookieManagerTest, GetCookieListAccessTime) {
// that it's a valid value.
base::Time start(base::Time::Now());
options.set_update_access_time();
- cookies =
- service_wrapper()->GetCookieList(GURL("https://foo_host.com/with/path"),
- options, net::CookiePartitionKeychain());
+ cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"), options,
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("A", cookies[0].Name());
EXPECT_FALSE(cookies[0].LastAccessDate().is_null());
@@ -1251,7 +1256,7 @@ TEST_F(CookieManagerTest, SecureCookieNonCryptographicPotentiallyTrustworthy) {
std::vector<net::CanonicalCookie> http_localhost_cookies =
service_wrapper()->GetCookieList(http_localhost_url,
net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain());
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, http_localhost_cookies.size());
EXPECT_EQ("http_localhost", http_localhost_cookies[0].Name());
EXPECT_EQ(net::CookieSourceScheme::kNonSecure,
@@ -1295,7 +1300,7 @@ TEST_F(CookieManagerTest, SecureCookieNonCryptographicPotentiallyTrustworthy) {
std::vector<net::CanonicalCookie> http_other_cookies =
service_wrapper()->GetCookieList(http_other_url,
net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain());
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, http_other_cookies.size());
EXPECT_EQ("http_other", http_other_cookies[0].Name());
EXPECT_EQ(net::CookieSourceScheme::kNonSecure,
@@ -2354,7 +2359,7 @@ class CookieChangeListener : public mojom::CookieChangeListener {
std::vector<net::CookieChangeInfo> observed_changes_;
// Loop to signal on receiving a notification if not null.
- base::RunLoop* run_loop_;
+ raw_ptr<base::RunLoop> run_loop_;
mojo::Receiver<mojom::CookieChangeListener> receiver_;
};
@@ -2611,7 +2616,7 @@ TEST_F(CookieManagerTest, CloningAndClientDestructVisible) {
std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList(
GURL("http://www.other.host/"), net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain());
+ net::CookiePartitionKeyCollection());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("X", cookies[0].Name());
EXPECT_EQ("Y", cookies[0].Value());
@@ -2914,5 +2919,128 @@ TEST_F(CookieManagerTest, SetStorageAccessGrantSettingsRunsCallback) {
ASSERT_EQ(1U, service_wrapper()->callback_count());
}
+class FPSPartitionedCookiesCookieManagerTest : public CookieManagerTest {
+ public:
+ FPSPartitionedCookiesCookieManagerTest()
+ : owner_url_(GURL("https://owner.test")),
+ owner_site_(owner_url_),
+ owner_partition_key_(
+ net::CookiePartitionKey::FromURLForTesting(owner_url_)),
+ member_url_(GURL("https://member.test")),
+ member_site_(member_url_),
+ member_partition_key_(
+ net::CookiePartitionKey::FromURLForTesting(GURL(member_url_))),
+ non_member_url_(GURL("https://nonmember.test")),
+ non_member_partition_key_(
+ net::CookiePartitionKey::FromURLForTesting(non_member_url_)) {
+ delegate_ = std::make_unique<net::TestCookieAccessDelegate>();
+ first_party_sets_.insert(std::make_pair(
+ owner_site_,
+ std::set<net::SchemefulSite>({owner_site_, member_site_})));
+ delegate_->SetFirstPartySets(first_party_sets_);
+ cookie_store()->SetCookieAccessDelegate(std::move(delegate_));
+ }
+
+ protected:
+ const GURL owner_url_;
+ const net::SchemefulSite owner_site_;
+ const net::CookiePartitionKey owner_partition_key_;
+
+ const GURL member_url_;
+ const net::SchemefulSite member_site_;
+ const net::CookiePartitionKey member_partition_key_;
+
+ const GURL non_member_url_;
+ const net::CookiePartitionKey non_member_partition_key_;
+
+ base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>
+ first_party_sets_;
+ std::unique_ptr<net::TestCookieAccessDelegate> delegate_;
+};
+
+TEST_F(FPSPartitionedCookiesCookieManagerTest, GetCookieList) {
+ // Add unpartitioned cookie.
+ ASSERT_TRUE(SetCanonicalCookie(
+ *net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-unpartitioned", "1", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
+ /*partition_key=*/absl::nullopt),
+ "https", true));
+ // Add partitioned cookies. One is in the First-Party Set's partition, the
+ // other is not.
+ ASSERT_TRUE(SetCanonicalCookie(
+ *net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-intheset", "2", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
+ absl::make_optional<net::CookiePartitionKey>(owner_partition_key_)),
+ "https", true));
+ ASSERT_TRUE(SetCanonicalCookie(
+ *net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-nonmember", "4", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
+ absl::make_optional<net::CookiePartitionKey>(
+ non_member_partition_key_)),
+ "https", true));
+
+ // Query cookies when the top-level site is a member of the First-Party Set.
+ // It should have access to the cookie set with the owner site as a partition
+ // key the unpartitioned cookie.
+ auto cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"),
+ net::CookieOptions::MakeAllInclusive(),
+ net::CookiePartitionKeyCollection(member_partition_key_));
+ EXPECT_EQ(2u, cookies.size());
+ EXPECT_EQ("__Host-unpartitioned", cookies[0].Name());
+ EXPECT_EQ("__Host-intheset", cookies[1].Name());
+ EXPECT_EQ(owner_partition_key_, cookies[1].PartitionKey().value());
+}
+
+TEST_F(FPSPartitionedCookiesCookieManagerTest, SetCanonicalCookie) {
+ // Add unpartitioned cookie.
+ ASSERT_TRUE(service_wrapper()->SetCanonicalCookie(
+ *net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-unpartitioned", "1", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
+ /*partition_key=*/absl::nullopt),
+ "https", true));
+ // Add partitioned cookies. One is in the First-Party Set's partition, and is
+ // first set with a member site as the partition key. SetCanonicalCookie
+ // should change the partition key to the First-Party Set's owner site.
+ ASSERT_TRUE(service_wrapper()->SetCanonicalCookie(
+ *net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-intheset", "2", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
+ absl::make_optional<net::CookiePartitionKey>(member_partition_key_)),
+ "https", true));
+ ASSERT_TRUE(service_wrapper()->SetCanonicalCookie(
+ *net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-nonmember", "4", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
+ absl::make_optional<net::CookiePartitionKey>(
+ non_member_partition_key_)),
+ "https", true));
+
+ auto cookies = service_wrapper()->GetCookieList(
+ GURL("https://foo_host.com/with/path"),
+ net::CookieOptions::MakeAllInclusive(),
+ net::CookiePartitionKeyCollection(owner_partition_key_));
+ EXPECT_EQ(2u, cookies.size());
+ EXPECT_EQ("__Host-unpartitioned", cookies[0].Name());
+ EXPECT_EQ("__Host-intheset", cookies[1].Name());
+ EXPECT_EQ(owner_partition_key_, cookies[1].PartitionKey().value());
+}
+
} // namespace
} // namespace network
diff --git a/chromium/services/network/cookie_settings.h b/chromium/services/network/cookie_settings.h
index d9f09bb088a..64d0e50c14f 100644
--- a/chromium/services/network/cookie_settings.h
+++ b/chromium/services/network/cookie_settings.h
@@ -5,6 +5,10 @@
#ifndef SERVICES_NETWORK_COOKIE_SETTINGS_H_
#define SERVICES_NETWORK_COOKIE_SETTINGS_H_
+#include <set>
+#include <string>
+#include <vector>
+
#include "base/component_export.h"
#include "base/feature_list.h"
#include "components/content_settings/core/common/content_settings.h"
diff --git a/chromium/services/network/cors/cors_url_loader.cc b/chromium/services/network/cors/cors_url_loader.cc
index b1043dfa8dd..d68c3330290 100644
--- a/chromium/services/network/cors/cors_url_loader.cc
+++ b/chromium/services/network/cors/cors_url_loader.cc
@@ -8,7 +8,7 @@
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/string_split.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
@@ -23,6 +23,7 @@
#include "services/network/public/cpp/timing_allow_origin_parser.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/early_hints.mojom.h"
+#include "services/network/public/mojom/ip_address_space.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/trust_tokens/trust_token_operation_metrics_recorder.h"
#include "services/network/url_loader.h"
@@ -36,7 +37,9 @@ namespace cors {
namespace {
enum class PreflightRequiredReason {
+ // TODO(https://crbug.com/1263483): Remove this.
kExternalRequest,
+ kPrivateNetworkAccess,
kCorsWithForcedPreflightMode,
kDisallowedMethod,
kDisallowedHeader
@@ -46,9 +49,18 @@ enum class PreflightRequiredReason {
// returns the reason why a preflight is needed.
absl::optional<PreflightRequiredReason> NeedsPreflight(
const ResourceRequest& request) {
+ if (request.target_ip_address_space != mojom::IPAddressSpace::kUnknown) {
+ // Force a preflight after a private network request was detected. See the
+ // HTTP-no-service-worker fetch algorithm defined in the Private Network
+ // Access spec:
+ // https://wicg.github.io/private-network-access/#http-no-service-worker-fetch
+ return PreflightRequiredReason::kPrivateNetworkAccess;
+ }
+
if (!IsCorsEnabledRequestMode(request.mode))
return absl::nullopt;
+ // TODO(https://crbug.com/1263483): Remove this.
if (request.is_external_request)
return PreflightRequiredReason::kExternalRequest;
@@ -99,9 +111,13 @@ base::Value NetLogPreflightRequiredParams(
if (preflight_required_reason) {
std::string preflight_required_reason_param;
switch (preflight_required_reason.value()) {
+ // TODO(https://crbug.com/1263483): Remove this.
case PreflightRequiredReason::kExternalRequest:
preflight_required_reason_param = "external_request";
break;
+ case PreflightRequiredReason::kPrivateNetworkAccess:
+ preflight_required_reason_param = "private_network_access";
+ break;
case PreflightRequiredReason::kCorsWithForcedPreflightMode:
preflight_required_reason_param = "cors_with_forced_preflight_mode";
break;
@@ -148,9 +164,9 @@ mojom::FetchResponseType CalculateResponseTainting(
// OriginAccessList is in practice used to disable CORS for Chrome Extensions.
// The extension origin can be found in either:
- // 1) |isolated_world_origin| (if this is a request from a content
+ // 1) `isolated_world_origin` (if this is a request from a content
// script; in this case there is no point looking at (2) below.
- // 2) |origin| (if this is a request from an extension
+ // 2) `origin` (if this is a request from an extension
// background page or from other extension frames).
//
// Note that similar code is present in OriginAccessList::CheckAccessState.
@@ -183,16 +199,16 @@ absl::optional<CorsErrorStatus> CheckRedirectLocation(
const absl::optional<url::Origin>& origin,
bool cors_flag,
bool tainted) {
- // If |actualResponse|’s location URL’s scheme is not an HTTP(S) scheme,
+ // If `actualResponse`’s location URL’s scheme is not an HTTP(S) scheme,
// then return a network error.
// This should be addressed in //net.
// Note: The redirect count check is done elsewhere.
const bool url_has_credentials = url.has_username() || url.has_password();
- // If |request|’s mode is "cors", |actualResponse|’s location URL includes
- // credentials, and either |request|’s tainted origin flag is set or
- // |request|’s origin is not same origin with |actualResponse|’s location
+ // If `request`’s mode is "cors", `actualResponse`’s location URL includes
+ // credentials, and either `request`’s tainted origin flag is set or
+ // `request`’s origin is not same origin with `actualResponse`’s location
// URL’s origin, then return a network error.
DCHECK(!IsCorsEnabledRequestMode(request_mode) || origin);
if (IsCorsEnabledRequestMode(request_mode) && url_has_credentials &&
@@ -200,7 +216,7 @@ absl::optional<CorsErrorStatus> CheckRedirectLocation(
return CorsErrorStatus(mojom::CorsError::kRedirectContainsCredentials);
}
- // If CORS flag is set and |actualResponse|’s location URL includes
+ // If CORS flag is set and `actualResponse`’s location URL includes
// credentials, then return a network error.
if (cors_flag && url_has_credentials)
return CorsErrorStatus(mojom::CorsError::kRedirectContainsCredentials);
@@ -209,12 +225,6 @@ absl::optional<CorsErrorStatus> CheckRedirectLocation(
}
constexpr const char kTimingAllowOrigin[] = "Timing-Allow-Origin";
-
-// Whether the sync client optimization is used for communication between the
-// CorsURLLoader and URLLoader.
-constexpr base::Feature kURLLoaderSyncClient{"URLLoaderSyncClient",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
} // namespace
CorsURLLoader::CorsURLLoader(
@@ -234,8 +244,10 @@ CorsURLLoader::CorsURLLoader(
PreflightController* preflight_controller,
const base::flat_set<std::string>* allowed_exempt_headers,
bool allow_any_cors_exempt_header,
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
const net::IsolationInfo& isolation_info,
- mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer)
+ mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
+ const mojom::ClientSecurityState* factory_client_security_state)
: receiver_(this, std::move(loader_receiver)),
process_id_(process_id),
request_id_(request_id),
@@ -251,7 +263,10 @@ CorsURLLoader::CorsURLLoader(
allowed_exempt_headers_(allowed_exempt_headers),
skip_cors_enabled_scheme_check_(skip_cors_enabled_scheme_check),
allow_any_cors_exempt_header_(allow_any_cors_exempt_header),
+ non_wildcard_request_headers_support_(
+ non_wildcard_request_headers_support),
isolation_info_(isolation_info),
+ factory_client_security_state_(factory_client_security_state),
devtools_observer_(std::move(devtools_observer)),
// CORS preflight related events are logged in a series of URL_REQUEST
// logs.
@@ -263,8 +278,7 @@ CorsURLLoader::CorsURLLoader(
receiver_.set_disconnect_handler(
base::BindOnce(&CorsURLLoader::OnMojoDisconnect, base::Unretained(this)));
- request_.net_log_params =
- network::ResourceRequest::NetLogParams(net_log_.source().id);
+ request_.net_log_create_info = net_log_.source();
DCHECK(network_loader_factory_);
DCHECK(origin_access_list_);
DCHECK(preflight_controller_);
@@ -274,7 +288,7 @@ CorsURLLoader::CorsURLLoader(
CorsURLLoader::~CorsURLLoader() {
// Reset pipes first to ignore possible subsequent callback invocations
- // caused by |network_loader_|
+ // caused by `network_loader_`
network_client_receiver_.reset();
}
@@ -298,13 +312,25 @@ void CorsURLLoader::FollowRedirect(
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
const absl::optional<GURL>& new_url) {
+ // If this is a navigation from a renderer, then its a service worker
+ // passthrough of a navigation request. Since this case uses manual
+ // redirect mode FollowRedirect() should never be called.
+ if (process_id_ != mojom::kBrowserProcessId &&
+ request_.mode == mojom::RequestMode::kNavigate) {
+ mojo::ReportBadMessage(
+ "CorsURLLoader: navigate from non-browser-process should not call "
+ "FollowRedirect");
+ HandleComplete(URLLoaderCompletionStatus(net::ERR_FAILED));
+ return;
+ }
+
if (!network_loader_ || !deferred_redirect_url_) {
HandleComplete(URLLoaderCompletionStatus(net::ERR_FAILED));
return;
}
- if (new_url &&
- (new_url->GetOrigin() != deferred_redirect_url_->GetOrigin())) {
+ if (new_url && (new_url->DeprecatedGetOriginAsURL() !=
+ deferred_redirect_url_->DeprecatedGetOriginAsURL())) {
NOTREACHED() << "Can only change the URL within the same origin.";
HandleComplete(URLLoaderCompletionStatus(net::ERR_FAILED));
return;
@@ -319,7 +345,7 @@ void CorsURLLoader::FollowRedirect(
return;
}
- // Does not allow modifying headers that are stored in |cors_exempt_headers|.
+ // Does not allow modifying headers that are stored in `cors_exempt_headers`.
for (const auto& header : modified_headers.GetHeaderVector()) {
if (request_.cors_exempt_headers.HasHeader(header.key)) {
LOG(WARNING) << "A client is trying to modify header value for '"
@@ -330,9 +356,9 @@ void CorsURLLoader::FollowRedirect(
}
network::URLLoader::LogConcerningRequestHeaders(
- modified_headers, true /* added_during_redirect */);
+ modified_headers, /*added_during_redirect=*/true);
network::URLLoader::LogConcerningRequestHeaders(
- modified_cors_exempt_headers, true /* added_during_redirect */);
+ modified_cors_exempt_headers, /*added_during_redirect=*/true);
for (const auto& name : removed_headers) {
request_.headers.RemoveHeader(name);
@@ -374,12 +400,12 @@ void CorsURLLoader::FollowRedirect(
const bool original_fetch_cors_flag = fetch_cors_flag_;
SetCorsFlagIfNeeded();
- // We cannot use FollowRedirect for a request with preflight (i.e., when both
- // |fetch_cors_flag_| and |NeedsPreflight(request_)| are true).
+ // We cannot use FollowRedirect for a request with preflight (i.e., when
+ // `fetch_cors_flag_` is true and `NeedsPreflight(request_)` is not nullopt).
//
- // When |original_fetch_cors_flag| is false, |fetch_cors_flag_| is true and
- // |NeedsPreflight(request)| is false, the net/ implementation won't attach an
- // "origin" header on redirect, as the original request didn't have one.
+ // When `original_fetch_cors_flag` is false, `fetch_cors_flag_` is true and
+ // `NeedsPreflight(request)` is nullopt, the net/ implementation won't attach
+ // an "origin" header on redirect, as the original request didn't have one.
//
// When the request method is changed (due to 302 status code, for example),
// the net/ implementation removes the origin header.
@@ -472,7 +498,7 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
DCHECK(forwarding_client_);
DCHECK(!deferred_redirect_url_);
- // If |CORS flag| is set and a CORS check for |request| and |response| returns
+ // If `CORS flag` is set and a CORS check for `request` and `response` returns
// failure, then return a network error.
if (fetch_cors_flag_ && IsCorsEnabledRequestMode(request_.mode)) {
const auto error_status = CheckAccessAndReportMetrics(
@@ -503,8 +529,8 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
// implement some logic in
// https://fetch.spec.whatwg.org/#http-redirect-fetch here.
- // If |request|’s redirect count is twenty, return a network error.
- // Increase |request|’s redirect count by one.
+ // If `request`’s redirect count is twenty, return a network error.
+ // Increase `request`’s redirect count by one.
if (redirect_count_++ == 20) {
HandleComplete(URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
return;
@@ -518,17 +544,17 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
return;
}
- // If |actualResponse|’s status is not 303, |request|’s body is non-null, and
- // |request|’s body’s source is null, then return a network error.
+ // If `actualResponse`’s status is not 303, `request`’s body is non-null, and
+ // `request`’s body’s source is null, then return a network error.
if (redirect_info.status_code != net::HTTP_SEE_OTHER &&
network::URLLoader::HasFetchStreamingUploadBody(&request_)) {
HandleComplete(URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT));
return;
}
- // If |actualResponse|’s location URL’s origin is not same origin with
- // |request|’s current url’s origin and |request|’s origin is not same origin
- // with |request|’s current url’s origin, then set |request|’s tainted origin
+ // If `actualResponse`’s location URL’s origin is not same origin with
+ // `request`’s current url’s origin and `request`’s origin is not same origin
+ // with `request`’s current url’s origin, then set `request`’s tainted origin
// flag.
if (request_.request_initiator &&
(!url::Origin::Create(redirect_info.new_url)
@@ -539,8 +565,8 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
}
// 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
+ // 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, 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
@@ -549,8 +575,8 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
// (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|. See 4.4. HTTP-redirect fetch
+ // Invoke `set request’s referrer policy on redirect` on `request` and
+ // `actualResponse`. See 4.4. HTTP-redirect fetch
// (https://fetch.spec.whatwg.org/#http-redirect-fetch), step 14.
redirect_info_ = redirect_info;
@@ -602,7 +628,7 @@ void CorsURLLoader::OnComplete(const URLLoaderCompletionStatus& status) {
DCHECK(network_loader_);
DCHECK(forwarding_client_);
- // |network_loader_| will call OnComplete at anytime when a problem happens
+ // `network_loader_` will call OnComplete at anytime when a problem happens
// inside the URLLoader, e.g. on URLLoader::OnMojoDisconnect call. We need
// to expect it also happens even during redirect handling.
DCHECK(!deferred_redirect_url_ || status.error_code != net::OK);
@@ -618,10 +644,10 @@ void CorsURLLoader::StartRequest() {
return;
}
- // If the |CORS flag| is set, |httpRequest|’s method is neither `GET` nor
- // `HEAD`, or |httpRequest|’s mode is "websocket", then append
- // `Origin`/the result of serializing a request origin with |httpRequest|, to
- // |httpRequest|’s header list.
+ // If the `CORS flag` is set, `httpRequest`’s method is neither `GET` nor
+ // `HEAD`, or `httpRequest`’s mode is "websocket", then append
+ // `Origin`/the result of serializing a request origin with `httpRequest`, to
+ // `httpRequest`’s header list.
//
// We exclude navigation requests to keep the existing behavior.
// TODO(yhirano): Reconsider this.
@@ -651,17 +677,28 @@ void CorsURLLoader::StartRequest() {
request_.isolated_world_origin, fetch_cors_flag_, tainted_,
*origin_access_list_);
- // 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.
+ // Note that even when `needs_preflight` holds we might not make a preflight
+ // request. This happens when `fetch_cors_flag_` is false, e.g. when the
+ // origin of the url is equal to the origin of the request, and the preflight
+ // reason is not `kPrivateNetworkAccess`. In the case of a private network
+ // access we always send a preflight, even for CORS-disabled requests.
+ //
+ // See the first step of the HTTP-no-service-worker fetch algorithm defined in
+ // the Private Network Access spec:
+ // https://wicg.github.io/private-network-access/#http-no-service-worker-fetch
absl::optional<PreflightRequiredReason> needs_preflight =
NeedsPreflight(request_);
- bool preflight_required = fetch_cors_flag_ && needs_preflight;
+ bool preflight_required =
+ needs_preflight.has_value() &&
+ (fetch_cors_flag_ ||
+ *needs_preflight == PreflightRequiredReason::kPrivateNetworkAccess);
net_log_.AddEvent(net::NetLogEventType::CHECK_CORS_PREFLIGHT_REQUIRED, [&] {
return NetLogPreflightRequiredParams(needs_preflight);
});
+
+ has_authorization_covered_by_wildcard_ = false;
if (!preflight_required) {
- StartNetworkRequest(net::OK, absl::nullopt, false);
+ StartNetworkRequest();
return;
}
@@ -677,32 +714,96 @@ void CorsURLLoader::StartRequest() {
// it now to free up the socket.
network_loader_.reset();
- has_authorization_covered_by_wildcard_ = false;
preflight_controller_->PerformPreflightCheck(
- base::BindOnce(&CorsURLLoader::StartNetworkRequest,
+ base::BindOnce(&CorsURLLoader::OnPreflightRequestComplete,
weak_factory_.GetWeakPtr()),
request_,
PreflightController::WithTrustedHeaderClient(
options_ & mojom::kURLLoadOptionUseHeaderClient),
- PreflightController::WithNonWildcardRequestHeadersSupport(false),
+ non_wildcard_request_headers_support_,
+ PreflightController::EnforcePrivateNetworkAccessHeader(
+ !ShouldIgnorePrivateNetworkAccessErrors()),
tainted_, net::NetworkTrafficAnnotationTag(traffic_annotation_),
- network_loader_factory_, isolation_info_, std::move(devtools_observer),
- net_log_);
+ network_loader_factory_, isolation_info_, CloneClientSecurityState(),
+ std::move(devtools_observer), net_log_);
+}
+
+void CorsURLLoader::ReportCorsErrorToDevTools(const CorsErrorStatus& status,
+ bool is_warning) {
+ DCHECK(devtools_observer_);
+
+ devtools_observer_->OnCorsError(
+ request_.devtools_request_id, request_.request_initiator,
+ CloneClientSecurityState(), request_.url, status, is_warning);
}
-void CorsURLLoader::StartNetworkRequest(
- int error_code,
+absl::optional<URLLoaderCompletionStatus> CorsURLLoader::ConvertPreflightResult(
+ int net_error,
+ absl::optional<CorsErrorStatus> status) {
+ if (net_error == net::OK) {
+ DCHECK(!status) << *status;
+ return absl::nullopt;
+ }
+
+ // `kInvalidResponse` is never returned by the preflight controller, so we use
+ // it to record the case where there was a net error and no CORS error.
+ auto histogram_error = mojom::CorsError::kInvalidResponse;
+ if (status) {
+ DCHECK(status->cors_error != mojom::CorsError::kInvalidResponse);
+ histogram_error = status->cors_error;
+ }
+
+ if (should_ignore_preflight_errors_) {
+ // Even if we ignore the error, record the warning in metrics and DevTools.
+ base::UmaHistogramEnumeration(kPreflightWarningHistogramName,
+ histogram_error);
+ if (devtools_observer_) {
+ if (!status) {
+ // Set the resource IP address space to the target IP address space for
+ // better error messages in DevTools. If the resource address space had
+ // not matched, the request would likely have failed with
+ // `CorsError::kInvalidPrivateNetwork`. If the error happened before we
+ // ever obtained a connection to the remote endpoint, then this value
+ // is incorrect - we cannot tell what value it would have been. Given
+ // that this is used for debugging only, the slight incorrectness is
+ // worth the increased debuggability.
+ status = CorsErrorStatus(mojom::CorsError::kInvalidResponse,
+ request_.target_ip_address_space,
+ request_.target_ip_address_space);
+ }
+
+ ReportCorsErrorToDevTools(*status, /*is_warning=*/true);
+ }
+
+ return absl::nullopt;
+ }
+
+ base::UmaHistogramEnumeration(kPreflightErrorHistogramName, histogram_error);
+ if (status) {
+ return URLLoaderCompletionStatus(*std::move(status));
+ }
+
+ return URLLoaderCompletionStatus(net_error);
+}
+
+void CorsURLLoader::OnPreflightRequestComplete(
+ int net_error,
absl::optional<CorsErrorStatus> status,
bool has_authorization_covered_by_wildcard) {
has_authorization_covered_by_wildcard_ =
has_authorization_covered_by_wildcard;
- if (error_code != net::OK) {
- HandleComplete(status ? URLLoaderCompletionStatus(*status)
- : URLLoaderCompletionStatus(error_code));
+
+ absl::optional<URLLoaderCompletionStatus> completion_status =
+ ConvertPreflightResult(net_error, std::move(status));
+ if (completion_status) {
+ HandleComplete(*std::move(completion_status));
return;
}
- DCHECK(!status);
+ StartNetworkRequest();
+}
+
+void CorsURLLoader::StartNetworkRequest() {
// Here we overwrite the credentials mode sent to URLLoader because
// network::URLLoader doesn't understand |kSameOrigin|.
// TODO(crbug.com/943939): Fix this.
@@ -718,7 +819,7 @@ void CorsURLLoader::StartNetworkRequest(
// |network_client_receiver_| shares this object's lifetime.
network_loader_.reset();
if (sync_network_loader_factory_ &&
- base::FeatureList::IsEnabled(kURLLoaderSyncClient)) {
+ base::FeatureList::IsEnabled(features::kURLLoaderSyncClient)) {
sync_network_loader_factory_->CreateLoaderAndStartWithSyncClient(
network_loader_.BindNewPipeAndPassReceiver(), request_id_, options_,
request_, network_client_receiver_.BindNewPipeAndPassRemote(),
@@ -743,9 +844,35 @@ void CorsURLLoader::HandleComplete(const URLLoaderCompletionStatus& status) {
}
if (devtools_observer_ && status.cors_error_status) {
- devtools_observer_->OnCorsError(request_.devtools_request_id,
- request_.request_initiator, request_.url,
- *status.cors_error_status);
+ ReportCorsErrorToDevTools(*status.cors_error_status);
+ }
+
+ // If we detect a private network access when we were not expecting one, we
+ // restart the request and force a preflight request. This preflight and the
+ // following request expect the resource to be in the same IP address space
+ // as was originally observed. Spec:
+ // https://wicg.github.io/private-network-access/#http-no-service-worker-fetch
+ if (status.cors_error_status &&
+ status.cors_error_status->cors_error ==
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess) {
+ DCHECK(status.cors_error_status->resource_address_space !=
+ mojom::IPAddressSpace::kUnknown);
+
+ // If we only send a preflight because of Private Network Access, and we are
+ // configured to ignore errors caused by Private Network Access, then we
+ // should ignore any preflight error, as if we had never sent the preflight.
+ // Otherwise, if we had sent a preflight before we noticed the private
+ // network access, then we rely on `PreflightController` to ignore
+ // PNA-specific preflight errors during this second preflight request.
+ should_ignore_preflight_errors_ =
+ ShouldIgnorePrivateNetworkAccessErrors() &&
+ !NeedsPreflight(request_).has_value();
+
+ network_client_receiver_.reset();
+ request_.target_ip_address_space =
+ status.cors_error_status->resource_address_space;
+ StartRequest();
+ return;
}
net_log_.EndEvent(net::NetLogEventType::CORS_REQUEST);
@@ -838,6 +965,40 @@ bool CorsURLLoader::PassesTimingAllowOriginCheck(
return false;
}
+// Computes the client security state to use, given the factory and
+// request-specific values.
+//
+// WARNING: This should be kept in sync with similar logic in
+// `network::URLLoader::GetClientSecurityState()`.
+const mojom::ClientSecurityState* CorsURLLoader::GetClientSecurityState()
+ const {
+ if (factory_client_security_state_) {
+ return factory_client_security_state_;
+ }
+
+ if (request_.trusted_params) {
+ // NOTE: This could return nullptr.
+ return request_.trusted_params->client_security_state.get();
+ }
+
+ return nullptr;
+}
+
+mojom::ClientSecurityStatePtr CorsURLLoader::CloneClientSecurityState() const {
+ const mojom::ClientSecurityState* state = GetClientSecurityState();
+ if (!state) {
+ return nullptr;
+ }
+
+ return state->Clone();
+}
+
+bool CorsURLLoader::ShouldIgnorePrivateNetworkAccessErrors() const {
+ const mojom::ClientSecurityState* state = GetClientSecurityState();
+ return state && state->private_network_request_policy ==
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn;
+}
+
// static
absl::optional<std::string> CorsURLLoader::GetHeaderString(
const mojom::URLResponseHead& response,
diff --git a/chromium/services/network/cors/cors_url_loader.h b/chromium/services/network/cors/cors_url_loader.h
index 0261b59951f..616a5ab39f5 100644
--- a/chromium/services/network/cors/cors_url_loader.h
+++ b/chromium/services/network/cors/cors_url_loader.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_NETWORK_CORS_CORS_URL_LOADER_H_
#define SERVICES_NETWORK_CORS_CORS_URL_LOADER_H_
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -14,9 +15,11 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/cors/preflight_controller.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
+#include "services/network/public/mojom/client_security_state.mojom-forward.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_loader_completion_status.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
@@ -33,14 +36,15 @@ class OriginAccessList;
// Wrapper class that adds cross-origin resource sharing capabilities
// (https://fetch.spec.whatwg.org/#http-cors-protocol), delegating requests as
// well as potential preflight requests to the supplied
-// |network_loader_factory|. It is owned by the CorsURLLoaderFactory that
+// `network_loader_factory`. It is owned by the CorsURLLoaderFactory that
// created it.
class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
: public mojom::URLLoader,
public mojom::URLLoaderClient {
public:
- using DeleteCallback = base::OnceCallback<void(mojom::URLLoader* loader)>;
+ using DeleteCallback = base::OnceCallback<void(CorsURLLoader* loader)>;
+ // Raw pointer arguments must outlive the returned instance.
CorsURLLoader(
mojo::PendingReceiver<mojom::URLLoader> loader_receiver,
int32_t process_id,
@@ -58,8 +62,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
PreflightController* preflight_controller,
const base::flat_set<std::string>* allowed_exempt_headers,
bool allow_any_cors_exempt_header,
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
const net::IsolationInfo& isolation_info,
- mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer);
+ mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
+ const mojom::ClientSecurityState* factory_client_security_state);
CorsURLLoader(const CorsURLLoader&) = delete;
CorsURLLoader& operator=(const CorsURLLoader&) = delete;
@@ -113,14 +119,26 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
private:
void StartRequest();
- void StartNetworkRequest(int net_error,
- absl::optional<CorsErrorStatus> status,
- bool has_authorization_covered_by_wildcard);
+
+ // Helper for `OnPreflightRequestComplete()`.
+ absl::optional<URLLoaderCompletionStatus> ConvertPreflightResult(
+ int net_error,
+ absl::optional<CorsErrorStatus> status);
+
+ void OnPreflightRequestComplete(int net_error,
+ absl::optional<CorsErrorStatus> status,
+ bool has_authorization_covered_by_wildcard);
+ void StartNetworkRequest();
// Called when there is a connection error on the upstream pipe used for the
// actual request.
void OnUpstreamConnectionError();
+ // Reports the error represented by `status` to DevTools, if possible.
+ // If `is_warning` is true, then the error is only reported as a warning.
+ void ReportCorsErrorToDevTools(const CorsErrorStatus& status,
+ bool is_warning = false);
+
// Handles OnComplete() callback.
void HandleComplete(const URLLoaderCompletionStatus& status);
@@ -129,12 +147,28 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
void SetCorsFlagIfNeeded();
// Returns true if request's origin has special access to the destination URL
- // (via |origin_access_list_|).
+ // (via `origin_access_list_`).
bool HasSpecialAccessToDestination() const;
bool PassesTimingAllowOriginCheck(
const mojom::URLResponseHead& response) const;
+ // Returns the client security state that applies to this request.
+ // May return nullptr.
+ const mojom::ClientSecurityState* GetClientSecurityState() const;
+
+ // Returns a clone of the value returned by `GetClientSecurityState()`.
+ mojom::ClientSecurityStatePtr CloneClientSecurityState() const;
+
+ // Returns whether preflight errors due exclusively to Private Network Access
+ // checks should be ignored.
+ //
+ // This is used to soft-launch Private Network Access preflights: we send
+ // preflights but do not require them to succeed.
+ //
+ // TODO(https://crbug.com/1268378): Remove this once it never returns true.
+ bool ShouldIgnorePrivateNetworkAccessErrors() const;
+
static absl::optional<std::string> GetHeaderString(
const mojom::URLResponseHead& response,
const std::string& header_name);
@@ -150,15 +184,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
// This raw URLLoaderFactory pointer is shared with the CorsURLLoaderFactory
// that created and owns this object.
- mojom::URLLoaderFactory* network_loader_factory_;
- // This has the same lifetime as |network_loader_factory_|, and should be used
+ raw_ptr<mojom::URLLoaderFactory> network_loader_factory_;
+ // This has the same lifetime as `network_loader_factory_`, and should be used
// when non-null to create optimized URLLoaders which can call URLLoaderClient
// methods synchronously.
- URLLoaderFactory* sync_network_loader_factory_;
+ raw_ptr<URLLoaderFactory> sync_network_loader_factory_;
// For the actual request.
mojo::Remote<mojom::URLLoader> network_loader_;
- // |sync_client_receiver_factory_| should be invalidated if this is ever
+ // `sync_client_receiver_factory_` should be invalidated if this is ever
// reset.
mojo::Receiver<mojom::URLLoaderClient> network_client_receiver_{this};
ResourceRequest request_;
@@ -197,27 +231,55 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
// We need to save this for redirect.
net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
- // Outlives |this|.
- const OriginAccessList* const origin_access_list_;
- PreflightController* preflight_controller_;
- const base::flat_set<std::string>* allowed_exempt_headers_;
+ // Outlives `this`.
+ const raw_ptr<const OriginAccessList> origin_access_list_;
+ raw_ptr<PreflightController> preflight_controller_;
+ raw_ptr<const base::flat_set<std::string>> allowed_exempt_headers_;
// Flag to specify if the CORS-enabled scheme check should be applied.
const bool skip_cors_enabled_scheme_check_;
const bool allow_any_cors_exempt_header_;
+ const NonWildcardRequestHeadersSupport non_wildcard_request_headers_support_;
+
net::IsolationInfo isolation_info_;
+ // The client security state set on the factory that created this loader.
+ //
+ // If non-null, this is used over any request-specific client security state
+ // passed in `request_.trusted_params`.
+ //
+ // NOTE: A default value is set here in order to avoid any risk of undefined
+ // behavior, but it should never be used since the constructor always
+ // initializes this member explicitly.
+ raw_ptr<const mojom::ClientSecurityState> factory_client_security_state_ =
+ nullptr;
+
bool has_authorization_covered_by_wildcard_ = false;
+ // If set to true, then any and all errors raised by subsequent preflight
+ // requests are ignored.
+ //
+ // This is used to soft-launch Private Network Access preflights. In some
+ // cases, the only reason we send a preflight is because of Private Network
+ // Access. Errors that arise then would never have been noticed if we had not
+ // sent the preflight, so we ignore them all.
+ //
+ // INVARIANT: if this is true, then
+ // `ShouldIgnorePrivateNetworkAccessErrors()` is also true.
+ //
+ // TODO(https://crbug.com/1268378): Remove this along with
+ // `should_ignore_private_network_access_errors_`.
+ bool should_ignore_preflight_errors_ = false;
+
mojo::Remote<mojom::DevToolsObserver> devtools_observer_;
net::NetLogWithSource net_log_;
// Used to provide weak pointers of this class for synchronously calling
// URLLoaderClient methods. This should be reset any time
- // |network_client_receiver_| is reset.
+ // `network_client_receiver_` is reset.
base::WeakPtrFactory<CorsURLLoader> sync_client_receiver_factory_{this};
// Used to run asynchronous class instance bound callbacks safely.
diff --git a/chromium/services/network/cors/cors_url_loader_factory.cc b/chromium/services/network/cors/cors_url_loader_factory.cc
index 561d9bec7bd..af0d8e606da 100644
--- a/chromium/services/network/cors/cors_url_loader_factory.cc
+++ b/chromium/services/network/cors/cors_url_loader_factory.cc
@@ -16,7 +16,6 @@
#include "net/http/http_util.h"
#include "services/network/cors/cors_url_loader.h"
#include "services/network/cors/preflight_controller.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/features.h"
@@ -178,6 +177,7 @@ CorsURLLoaderFactory::CorsURLLoaderFactory(
? params->client_security_state->cross_origin_embedder_policy
: CrossOriginEmbedderPolicy()),
coep_reporter_(std::move(params->coep_reporter)),
+ client_security_state_(params->client_security_state.Clone()),
origin_access_list_(origin_access_list) {
DCHECK(context_);
DCHECK(origin_access_list_);
@@ -212,29 +212,35 @@ CorsURLLoaderFactory::~CorsURLLoaderFactory() {
// Delete loaders one at a time, since deleting one loader can cause another
// loader waiting on it to fail synchronously, which could result in the other
// loader calling DestroyURLLoader().
- while (!loaders_.empty()) {
+ while (!url_loaders_.empty()) {
// No need to call context_->LoaderDestroyed(), since this method is only
// called from the NetworkContext's destructor, or when there are no
// remaining URLLoaders.
- loaders_.erase(loaders_.begin());
+ url_loaders_.erase(url_loaders_.begin());
+ }
+
+ // Same as above for CorsURLLoaders.
+ while (!cors_url_loaders_.empty()) {
+ cors_url_loaders_.erase(cors_url_loaders_.begin());
}
}
-void CorsURLLoaderFactory::OnLoaderCreated(
- std::unique_ptr<mojom::URLLoader> loader) {
- if (context_)
- context_->LoaderCreated(process_id_);
- loaders_.insert(std::move(loader));
+void CorsURLLoaderFactory::OnURLLoaderCreated(
+ std::unique_ptr<URLLoader> loader) {
+ OnLoaderCreated(std::move(loader), url_loaders_);
}
-void CorsURLLoaderFactory::DestroyURLLoader(mojom::URLLoader* loader) {
- if (context_)
- context_->LoaderDestroyed(process_id_);
- auto it = loaders_.find(loader);
- DCHECK(it != loaders_.end());
- loaders_.erase(it);
+void CorsURLLoaderFactory::OnCorsURLLoaderCreated(
+ std::unique_ptr<CorsURLLoader> loader) {
+ OnLoaderCreated(std::move(loader), cors_url_loaders_);
+}
- DeleteIfNeeded();
+void CorsURLLoaderFactory::DestroyURLLoader(URLLoader* loader) {
+ DestroyLoader(loader, url_loaders_);
+}
+
+void CorsURLLoaderFactory::DestroyCorsURLLoader(CorsURLLoader* loader) {
+ DestroyLoader(loader, cors_url_loaders_);
}
void CorsURLLoaderFactory::CreateLoaderAndStart(
@@ -283,7 +289,7 @@ void CorsURLLoaderFactory::CreateLoaderAndStart(
auto loader = std::make_unique<CorsURLLoader>(
std::move(receiver), process_id_, request_id, options,
- base::BindOnce(&CorsURLLoaderFactory::DestroyURLLoader,
+ base::BindOnce(&CorsURLLoaderFactory::DestroyCorsURLLoader,
base::Unretained(this)),
resource_request, ignore_isolated_world_origin_,
factory_override_ &&
@@ -292,10 +298,11 @@ void CorsURLLoaderFactory::CreateLoaderAndStart(
factory_override_ ? nullptr : network_loader_factory_.get(),
origin_access_list_, context_->cors_preflight_controller(),
context_->cors_exempt_header_list(),
- GetAllowAnyCorsExemptHeaderForBrowser(), isolation_info_,
- std::move(devtools_observer));
+ GetAllowAnyCorsExemptHeaderForBrowser(),
+ context_->cors_non_wildcard_request_headers_support(), isolation_info_,
+ std::move(devtools_observer), client_security_state_.get());
auto* raw_loader = loader.get();
- OnLoaderCreated(std::move(loader));
+ OnCorsURLLoaderCreated(std::move(loader));
raw_loader->Start();
} else {
inner_url_loader_factory->CreateLoaderAndStart(
@@ -318,7 +325,7 @@ void CorsURLLoaderFactory::ClearBindings() {
void CorsURLLoaderFactory::DeleteIfNeeded() {
if (!context_)
return;
- if (receivers_.empty() && loaders_.empty())
+ if (receivers_.empty() && url_loaders_.empty() && cors_url_loaders_.empty())
context_->DestroyURLLoaderFactory(this);
}
@@ -331,7 +338,7 @@ bool CorsURLLoaderFactory::IsValidCorsExemptHeaders(
allowed_exempt_headers.end()) {
continue;
}
- LOG(WARNING) << "|cors_exempt_headers| contains unexpected key: "
+ LOG(WARNING) << "`cors_exempt_headers` contains unexpected key: "
<< header.value;
return false;
}
@@ -345,8 +352,8 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
if (!request.request_initiator &&
request.mode != network::mojom::RequestMode::kNavigate &&
request.mode != mojom::RequestMode::kNoCors) {
- LOG(WARNING) << "|mode| is " << request.mode
- << ", but |request_initiator| is not set.";
+ LOG(WARNING) << "`mode` is " << request.mode
+ << ", but `request_initiator` is not set.";
mojo::ReportBadMessage("CorsURLLoaderFactory: cors without initiator");
return false;
}
@@ -382,18 +389,76 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
return false;
}
+ // The `force_main_frame_for_same_site_cookies` should only be set when a
+ // service worker passes through a navigation request. In this case the
+ // mode must be `kNavigate` and the destination must be empty.
+ if (request.original_destination == mojom::RequestDestination::kDocument &&
+ (request.mode != mojom::RequestMode::kNavigate ||
+ request.destination != mojom::RequestDestination::kEmpty)) {
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: original_destination is unexpectedly set to "
+ "kDocument");
+ return false;
+ }
+
+ // Validate that a navigation redirect chain is not sent for a non-navigation
+ // request.
+ if (!request.navigation_redirect_chain.empty() &&
+ request.mode != mojom::RequestMode::kNavigate) {
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: navigation redirect chain set for a "
+ "non-navigation");
+ return false;
+ }
+
+ // By default we compare the `request_initiator` to the lock below. This is
+ // overridden for renderer navigations, however.
+ absl::optional<url::Origin> origin_to_validate = request.request_initiator;
+
// Ensure that renderer requests are covered either by CORS or CORB.
if (process_id_ != mojom::kBrowserProcessId) {
switch (request.mode) {
case mojom::RequestMode::kNavigate:
- // Only the browser process can initiate navigations. This helps ensure
- // that a malicious/compromised renderer cannot bypass CORB by issuing
- // kNavigate, rather than kNoCors requests. (CORB should apply only to
- // no-cors requests as tracked in https://crbug.com/953315 and as
- // captured in https://fetch.spec.whatwg.org/#main-fetch).
- mojo::ReportBadMessage(
- "CorsURLLoaderFactory: navigate from non-browser-process");
- return false;
+ // A navigation request from a renderer can legally occur when a service
+ // worker passes it through from its `FetchEvent.request` to `fetch()`.
+ // In this case it is making a navigation request on behalf of the
+ // original initiator. Since that initiator may be cross-origin, its
+ // possible the request's initiator will not match our lock.
+ //
+ // To make this operation safe we instead compare the request URL origin
+ // against the initiator lock. We can do this since service workers
+ // should only ever handle same-origin navigations.
+ //
+ // With this approach its possible the initiator could be spoofed by the
+ // renderer. However, since we have validated the request URL they can
+ // only every lie to the origin that they have already compromised. It
+ // does not allow an attacker to target other arbitrary origins.
+ origin_to_validate = url::Origin::Create(request.url);
+
+ // We further validate the navigation request by ensuring it has the
+ // correct redirect mode. This avoids an attacker attempting to
+ // craft a navigation that is then automatically followed to a separate
+ // target origin. With manual mode the redirect will instead be
+ // processed as an opaque redirect response that is passed back to the
+ // renderer and navigation code. The redirected requested must be
+ // sent anew and go through this validation again.
+ if (request.redirect_mode != mojom::RedirectMode::kManual) {
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: navigate from non-browser-process with "
+ "redirect_mode set to 'follow'");
+ return false;
+ }
+
+ // Validate that a navigation redirect chain is always provided for a
+ // navigation request.
+ if (request.navigation_redirect_chain.empty()) {
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: navigate from non-browser-process without "
+ "a redirect chain provided");
+ return false;
+ }
+
+ break;
case mojom::RequestMode::kSameOrigin:
case mojom::RequestMode::kCors:
@@ -407,11 +472,11 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
}
}
- // Compare |request_initiator| and |request_initiator_origin_lock_|.
+ // Depending on the type of request, compare either `request_initiator` or
+ // `request.url` to `request_initiator_origin_lock_`.
InitiatorLockCompatibility initiator_lock_compatibility =
- VerifyRequestInitiatorLockWithPluginCheck(process_id_,
- request_initiator_origin_lock_,
- request.request_initiator);
+ VerifyRequestInitiatorLockWithPluginCheck(
+ process_id_, request_initiator_origin_lock_, origin_to_validate);
UMA_HISTOGRAM_ENUMERATION(
"NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility",
initiator_lock_compatibility);
@@ -422,7 +487,7 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
break;
case InitiatorLockCompatibility::kNoLock:
- // |request_initiator_origin_lock| should always be set in a
+ // `request_initiator_origin_lock` should always be set in a
// URLLoaderFactory vended to a renderer process. See also
// https://crbug.com/1114906.
NOTREACHED();
@@ -439,7 +504,6 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
case InitiatorLockCompatibility::kIncorrectLock:
// Requests from the renderer need to always specify a correct initiator.
- NOTREACHED();
mojo::ReportBadMessage(
"CorsURLLoaderFactory: lock VS initiator mismatch");
return false;
@@ -469,7 +533,7 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
return false;
}
- // We only support |kInclude| credentials mode with navigations. See also:
+ // We only support `kInclude` credentials mode with navigations. See also:
// a note at https://fetch.spec.whatwg.org/#concept-request-credentials-mode.
if (request.credentials_mode != mojom::CredentialsMode::kInclude &&
request.mode == network::mojom::RequestMode::kNavigate) {
@@ -497,7 +561,7 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
}
if (!net::HttpUtil::IsToken(request.method)) {
- // Callers are expected to ensure that |method| follows RFC 7230.
+ // Callers are expected to ensure that `method` follows RFC 7230.
mojo::ReportBadMessage(
"CorsURLLoaderFactory: invalid characters in method");
return false;
@@ -514,10 +578,25 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
return false;
}
- // |net_log_params| field is expected to be used within network service.
- if (request.net_log_params.has_value()) {
- mojo::ReportBadMessage(
- "CorsURLLoaderFactory: net_log_params field is not expected.");
+ // Check only when `disable_web_security_` is false because
+ // PreflightControllerTest use CorsURLLoaderFactory with this flag true
+ // instead of network::URLLoaderFactory.
+ // TODO(https://crbug.com/1264298): consider if we can remove this exemption.
+ if (!disable_web_security_) {
+ // `net_log_create_info` field is expected to be used within network
+ // service.
+ if (request.net_log_create_info) {
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: net_log_create_info field is not expected.");
+ }
+
+ // `net_log_reference_info` field is expected to be used within network
+ // service.
+ if (request.net_log_reference_info) {
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: net_log_reference_info field is not "
+ "expected.");
+ }
}
if (request.target_ip_address_space != mojom::IPAddressSpace::kUnknown) {
diff --git a/chromium/services/network/cors/cors_url_loader_factory.h b/chromium/services/network/cors/cors_url_loader_factory.h
index d4adc6840dd..7d346a28854 100644
--- a/chromium/services/network/cors/cors_url_loader_factory.h
+++ b/chromium/services/network/cors/cors_url_loader_factory.h
@@ -10,26 +10,29 @@
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_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"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/network_context.h"
#include "services/network/public/cpp/cors/origin_access_list.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
#include "services/network/public/cpp/initiator_lock_compatibility.h"
+#include "services/network/public/mojom/client_security_state.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace network {
-class NetworkContext;
class ResourceSchedulerClient;
class URLLoader;
class URLLoaderFactory;
struct ResourceRequest;
namespace cors {
+class CorsURLLoader;
// A factory class to create a URLLoader that supports CORS.
// This class takes a network::mojom::URLLoaderFactory instance in the
@@ -43,12 +46,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
allow_external_preflights_for_testing_ = allow;
}
- // Check if members in |headers| are permitted by |allowed_exempt_headers|.
+ // Check if members in `headers` are permitted by `allowed_exempt_headers`.
static bool IsValidCorsExemptHeaders(
const base::flat_set<std::string>& allowed_exempt_headers,
const net::HttpRequestHeaders& headers);
- // |origin_access_list| should always outlive this factory instance.
+ // `origin_access_list` should always outlive this factory instance.
// Used by network::NetworkContext.
CorsURLLoaderFactory(
NetworkContext* context,
@@ -62,8 +65,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
~CorsURLLoaderFactory() override;
- void OnLoaderCreated(std::unique_ptr<mojom::URLLoader> loader);
- void DestroyURLLoader(mojom::URLLoader* loader);
+ void OnURLLoaderCreated(std::unique_ptr<URLLoader> loader);
+ void OnCorsURLLoaderCreated(std::unique_ptr<CorsURLLoader> loader);
+ void DestroyURLLoader(URLLoader* loader);
+ void DestroyCorsURLLoader(CorsURLLoader* loader);
// Clears the bindings for this factory, but does not touch any in-progress
// URLLoaders. Calling this may delete this factory and remove it from the
@@ -75,6 +80,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
return coep_reporter_ ? coep_reporter_.get() : nullptr;
}
+ std::set<std::unique_ptr<URLLoader>, base::UniquePtrComparator>&
+ url_loaders() {
+ return url_loaders_;
+ }
+
private:
class FactoryOverride;
@@ -102,14 +112,36 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
mojo::PendingRemote<mojom::DevToolsObserver> GetDevToolsObserver(
const ResourceRequest& resource_request) const;
+ template <class T>
+ void OnLoaderCreated(
+ std::unique_ptr<T> loader,
+ std::set<std::unique_ptr<T>, base::UniquePtrComparator>& loaders) {
+ if (context_)
+ context_->LoaderCreated(process_id_);
+ loaders.insert(std::move(loader));
+ }
+
+ template <class T>
+ void DestroyLoader(
+ T* loader,
+ std::set<std::unique_ptr<T>, base::UniquePtrComparator>& loaders) {
+ if (context_)
+ context_->LoaderDestroyed(process_id_);
+ auto it = loaders.find(loader);
+ DCHECK(it != loaders.end());
+ loaders.erase(it);
+
+ DeleteIfNeeded();
+ }
+
mojo::ReceiverSet<mojom::URLLoaderFactory> receivers_;
// Used when constructed by NetworkContext.
- // The NetworkContext owns |this|.
- NetworkContext* const context_ = nullptr;
+ // The NetworkContext owns `this`.
+ const raw_ptr<NetworkContext> context_ = nullptr;
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client_;
- // If false, ResourceRequests cannot have their |trusted_params| fields set.
+ // If false, ResourceRequests cannot have their `trusted_params` fields set.
bool is_trusted_;
// Retained from URLLoaderFactoryParams:
@@ -122,8 +154,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
const std::string debug_tag_;
const CrossOriginEmbedderPolicy cross_origin_embedder_policy_;
mojo::Remote<mojom::CrossOriginEmbedderPolicyReporter> coep_reporter_;
+ const mojom::ClientSecurityStatePtr client_security_state_;
- // Relative order of |network_loader_factory_| and |loaders_| matters -
+ // Relative order of `network_loader_factory_` and `loaders_` matters -
// URLLoaderFactory needs to live longer than URLLoaders created using the
// factory. See also https://crbug.com/906305.
std::unique_ptr<network::URLLoaderFactory> network_loader_factory_;
@@ -131,12 +164,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
// Used when the network loader factory is overridden.
std::unique_ptr<FactoryOverride> factory_override_;
- std::set<std::unique_ptr<mojom::URLLoader>, base::UniquePtrComparator>
- loaders_;
+ std::set<std::unique_ptr<URLLoader>, base::UniquePtrComparator> url_loaders_;
+ std::set<std::unique_ptr<CorsURLLoader>, base::UniquePtrComparator>
+ cors_url_loaders_;
- // Accessed by instances in |loaders_| too. Since the factory outlives them,
+ // Accessed by instances in `loaders_` too. Since the factory outlives them,
// it's safe.
- const OriginAccessList* const origin_access_list_;
+ const raw_ptr<const OriginAccessList> origin_access_list_;
static bool allow_external_preflights_for_testing_;
};
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 1ce7585a411..baa0b717954 100644
--- a/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
+++ b/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
@@ -4,9 +4,10 @@
#include <memory>
-#include "base/macros.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/test_support/fake_message_dispatch_context.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/load_flags.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -48,6 +49,9 @@ class CorsURLLoaderFactoryTest : public testing::Test {
url_request_context_ = context_builder.Build();
}
+ CorsURLLoaderFactoryTest(const CorsURLLoaderFactoryTest&) = delete;
+ CorsURLLoaderFactoryTest& operator=(const CorsURLLoaderFactoryTest&) = delete;
+
protected:
// testing::Test implementation.
void SetUp() override {
@@ -108,6 +112,7 @@ class CorsURLLoaderFactoryTest : public testing::Test {
private:
// Test environment.
base::test::TaskEnvironment task_environment_;
+ mojo::FakeMessageDispatchContext mojo_context_;
std::unique_ptr<net::URLRequestContext> url_request_context_;
ResourceScheduler resource_scheduler_;
std::unique_ptr<NetworkService> network_service_;
@@ -128,8 +133,6 @@ class CorsURLLoaderFactoryTest : public testing::Test {
// Holds for allowed origin access lists.
OriginAccessList origin_access_list_;
-
- DISALLOW_COPY_AND_ASSIGN(CorsURLLoaderFactoryTest);
};
// Regression test for https://crbug.com/906305.
@@ -142,10 +145,10 @@ TEST_F(CorsURLLoaderFactoryTest, DestructionOrder) {
request.url = url;
request.request_initiator = url::Origin::Create(url);
- // As of r609458 setting |keepalive| to true was triggerring a dereference of
- // |factory_params_| in the destructor of network::URLLoader. This
+ // As of r609458 setting `keepalive` to true was triggerring a dereference of
+ // `factory_params_` in the destructor of network::URLLoader. This
// dereference assumes that the network::URLLoaderFactory (which keeps
- // |factory_params_| alive) lives longer than the network::URLLoaders created
+ // `factory_params_` alive) lives longer than the network::URLLoaders created
// via the factory (which necessitates being careful with the destruction
// order of fields of network::cors::CorsURLLoaderFactory which owns both
// network::URLLoaderFactory and the network::URLLoaders it creates).
@@ -172,7 +175,7 @@ TEST_F(CorsURLLoaderFactoryTest, CleanupWithSharedCacheObjectInUse) {
test_cors_loader_clients().back()->RunUntilResponseReceived();
// Read only requests will fail synchonously on destruction of the request
- // they're waiting on if they're in the |done_headers_queue| when the other
+ // they're waiting on if they're in the `done_headers_queue` when the other
// request fails. Make a large number of such requests, spin the message loop
// so they end up blocked on the hung request, and then destroy all loads. A
// large number of loaders is needed because they're stored in a set, indexed
@@ -189,5 +192,118 @@ TEST_F(CorsURLLoaderFactoryTest, CleanupWithSharedCacheObjectInUse) {
ResetFactory();
}
+TEST_F(CorsURLLoaderFactoryTest,
+ NavigationFromRendererWithBadRequestURLOrigin) {
+ ResourceRequest request;
+ GURL url = test_server()->GetURL("/echoall");
+ request.mode = mojom::RequestMode::kNavigate;
+ request.redirect_mode = mojom::RedirectMode::kManual;
+ request.destination = mojom::RequestDestination::kEmpty;
+ request.method = net::HttpRequestHeaders::kPostMethod;
+ request.url = GURL("https://some.other.origin/echoall");
+ request.navigation_redirect_chain.push_back(request.url);
+ request.request_initiator = url::Origin::Create(url);
+ mojo::test::BadMessageObserver bad_message_observer;
+ CreateLoaderAndStart(request);
+ EXPECT_EQ("CorsURLLoaderFactory: lock VS initiator mismatch",
+ bad_message_observer.WaitForBadMessage());
+}
+
+TEST_F(CorsURLLoaderFactoryTest, NavigationFromRendererWithBadRedirectMode) {
+ ResourceRequest request;
+ GURL url = test_server()->GetURL("/echoall");
+ request.mode = mojom::RequestMode::kNavigate;
+ request.redirect_mode = mojom::RedirectMode::kFollow;
+ request.destination = mojom::RequestDestination::kEmpty;
+ request.method = net::HttpRequestHeaders::kPostMethod;
+ request.url = url;
+ request.navigation_redirect_chain.push_back(request.url);
+ request.request_initiator = url::Origin::Create(url).DeriveNewOpaqueOrigin();
+ mojo::test::BadMessageObserver bad_message_observer;
+ CreateLoaderAndStart(request);
+ EXPECT_EQ(
+ "CorsURLLoaderFactory: navigate from non-browser-process with "
+ "redirect_mode set to 'follow'",
+ bad_message_observer.WaitForBadMessage());
+}
+
+TEST_F(CorsURLLoaderFactoryTest,
+ NavigationFromRendererWithBadRequestNavigationRedirectChain) {
+ ResourceRequest request;
+ GURL url = test_server()->GetURL("/echoall");
+ request.mode = mojom::RequestMode::kNavigate;
+ request.redirect_mode = mojom::RedirectMode::kManual;
+ request.destination = mojom::RequestDestination::kEmpty;
+ request.method = net::HttpRequestHeaders::kPostMethod;
+ request.url = url;
+ // Do not add url to navigation_redirect_chain
+ request.request_initiator = url::Origin::Create(url);
+ mojo::test::BadMessageObserver bad_message_observer;
+ CreateLoaderAndStart(request);
+ EXPECT_EQ(
+ "CorsURLLoaderFactory: navigate from non-browser-process without "
+ "a redirect chain provided",
+ bad_message_observer.WaitForBadMessage());
+}
+
+TEST_F(CorsURLLoaderFactoryTest, NavigationRedirectChainWithBadMode) {
+ ResourceRequest request;
+ GURL url = test_server()->GetURL("/echoall");
+ request.mode = mojom::RequestMode::kCors;
+ request.redirect_mode = mojom::RedirectMode::kFollow;
+ request.destination = mojom::RequestDestination::kEmpty;
+ request.method = net::HttpRequestHeaders::kGetMethod;
+ request.url = url;
+ request.navigation_redirect_chain.push_back(request.url);
+ request.request_initiator = url::Origin::Create(url);
+ mojo::test::BadMessageObserver bad_message_observer;
+ CreateLoaderAndStart(request);
+ EXPECT_EQ(
+ "CorsURLLoaderFactory: navigation redirect chain set for a "
+ "non-navigation",
+ bad_message_observer.WaitForBadMessage());
+}
+
+TEST_F(CorsURLLoaderFactoryTest, OriginalDestinationIsDocumentWithBadMode) {
+ ResourceRequest request;
+ GURL url = test_server()->GetURL("/echoall");
+ request.mode = mojom::RequestMode::kCors;
+ request.redirect_mode = mojom::RedirectMode::kFollow;
+ request.destination = mojom::RequestDestination::kEmpty;
+ request.method = net::HttpRequestHeaders::kGetMethod;
+ request.url = url;
+ request.navigation_redirect_chain.push_back(request.url);
+ request.request_initiator =
+ url::Origin::Create(GURL("https://some.other.origin"));
+ request.original_destination = mojom::RequestDestination::kDocument;
+ mojo::test::BadMessageObserver bad_message_observer;
+ CreateLoaderAndStart(request);
+ EXPECT_EQ(
+ "CorsURLLoaderFactory: original_destination is unexpectedly set to "
+ "kDocument",
+ bad_message_observer.WaitForBadMessage());
+}
+
+TEST_F(CorsURLLoaderFactoryTest,
+ OriginalDestinationIsDocumentWithBadDestination) {
+ ResourceRequest request;
+ GURL url = test_server()->GetURL("/echoall");
+ request.mode = mojom::RequestMode::kNavigate;
+ request.redirect_mode = mojom::RedirectMode::kManual;
+ request.destination = mojom::RequestDestination::kIframe;
+ request.method = net::HttpRequestHeaders::kGetMethod;
+ request.url = url;
+ request.navigation_redirect_chain.push_back(request.url);
+ request.request_initiator =
+ url::Origin::Create(GURL("https://some.other.origin"));
+ request.original_destination = mojom::RequestDestination::kDocument;
+ mojo::test::BadMessageObserver bad_message_observer;
+ CreateLoaderAndStart(request);
+ EXPECT_EQ(
+ "CorsURLLoaderFactory: original_destination is unexpectedly set to "
+ "kDocument",
+ bad_message_observer.WaitForBadMessage());
+}
+
} // namespace cors
} // namespace network
diff --git a/chromium/services/network/cors/cors_url_loader_unittest.cc b/chromium/services/network/cors/cors_url_loader_unittest.cc
index 236d744f56b..ef08f195465 100644
--- a/chromium/services/network/cors/cors_url_loader_unittest.cc
+++ b/chromium/services/network/cors/cors_url_loader_unittest.cc
@@ -11,7 +11,7 @@
#include "base/callback_helpers.h"
#include "base/check.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
@@ -38,6 +38,7 @@
#include "services/network/public/mojom/cors.mojom.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/early_hints.mojom.h"
+#include "services/network/public/mojom/ip_address_space.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -58,12 +59,25 @@ namespace cors {
namespace {
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::IsSupersetOf;
using ::testing::Optional;
+using ::testing::Pair;
const uint32_t kRendererProcessId = 573;
constexpr char kTestCorsExemptHeader[] = "x-test-cors-exempt";
+constexpr char kPreflightErrorHistogramName[] = "Net.Cors.PreflightCheckError2";
+constexpr char kPreflightWarningHistogramName[] =
+ "Net.Cors.PreflightCheckWarning";
+
+base::Bucket MakeBucket(mojom::CorsError error,
+ base::HistogramBase::Count count) {
+ return base::Bucket(static_cast<base::HistogramBase::Sample>(error), count);
+}
+
class TestURLLoaderFactory : public mojom::URLLoaderFactory {
public:
TestURLLoaderFactory() {}
@@ -96,7 +110,7 @@ class TestURLLoaderFactory : public mojom::URLLoaderFactory {
const std::vector<std::pair<std::string, std::string>>& extra_headers) {
DCHECK(client_remote_);
auto response = mojom::URLResponseHead::New();
- response->headers = new net::HttpResponseHeaders(
+ response->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
base::StringPrintf("HTTP/1.1 %d OK\n"
"Content-Type: image/png\n",
status_code));
@@ -111,6 +125,11 @@ class TestURLLoaderFactory : public mojom::URLLoaderFactory {
client_remote_->OnComplete(URLLoaderCompletionStatus(error_code));
}
+ void NotifyClientOnComplete(const CorsErrorStatus& status) {
+ DCHECK(client_remote_);
+ client_remote_->OnComplete(URLLoaderCompletionStatus(status));
+ }
+
void NotifyClientOnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const std::vector<std::pair<std::string, std::string>>& extra_headers) {
@@ -167,6 +186,31 @@ class TestURLLoaderFactory : public mojom::URLLoaderFactory {
base::WeakPtrFactory<TestURLLoaderFactory> weak_factory_{this};
};
+// Optional parameters for ResetFactory().
+struct ResetFactoryParams {
+ // Sets each member to the default value of the corresponding mojom member.
+ ResetFactoryParams();
+
+ // Members of `mojom::URLLoaderFactoryParams`.
+ bool is_trusted;
+ bool ignore_isolated_world_origin;
+ mojom::ClientSecurityStatePtr client_security_state;
+
+ // Member of `mojom::URLLoaderFactoryOverride`.
+ bool skip_cors_enabled_scheme_check;
+};
+
+ResetFactoryParams::ResetFactoryParams() {
+ mojom::URLLoaderFactoryParams params;
+ is_trusted = params.is_trusted;
+ ignore_isolated_world_origin = params.ignore_isolated_world_origin;
+ client_security_state = std::move(params.client_security_state);
+
+ mojom::URLLoaderFactoryOverride factory_override;
+ skip_cors_enabled_scheme_check =
+ factory_override.skip_cors_enabled_scheme_check;
+}
+
class CorsURLLoaderTest : public testing::Test {
public:
using ReferrerPolicy = net::ReferrerPolicy;
@@ -179,6 +223,9 @@ class CorsURLLoaderTest : public testing::Test {
url_request_context_ = context_builder.Build();
}
+ CorsURLLoaderTest(const CorsURLLoaderTest&) = delete;
+ CorsURLLoaderTest& operator=(const CorsURLLoaderTest&) = delete;
+
protected:
// testing::Test implementation.
void SetUp(network::mojom::NetworkContextParamsPtr context_params) {
@@ -204,14 +251,20 @@ class CorsURLLoaderTest : public testing::Test {
}
void SetUp() override { SetUp(mojom::NetworkContextParams::New()); }
- void CreateLoaderAndStart(const GURL& origin,
- const GURL& url,
- mojom::RequestMode mode) {
+ void CreateLoaderAndStart(
+ const GURL& origin,
+ const GURL& url,
+ mojom::RequestMode mode,
+ mojom::RedirectMode redirect_mode = mojom::RedirectMode::kFollow,
+ mojom::CredentialsMode credentials_mode = mojom::CredentialsMode::kOmit) {
ResourceRequest request;
request.mode = mode;
- request.credentials_mode = mojom::CredentialsMode::kOmit;
+ request.redirect_mode = redirect_mode;
+ request.credentials_mode = credentials_mode;
request.method = net::HttpRequestHeaders::kGetMethod;
request.url = url;
+ if (request.mode == mojom::RequestMode::kNavigate)
+ request.navigation_redirect_chain.push_back(url);
request.request_initiator = url::Origin::Create(origin);
if (devtools_observer_for_next_request_) {
request.trusted_params = ResourceRequest::TrustedParams();
@@ -273,6 +326,11 @@ class CorsURLLoaderTest : public testing::Test {
test_url_loader_factory_->NotifyClientOnComplete(error_code);
}
+ void NotifyLoaderClientOnComplete(const CorsErrorStatus& status) {
+ DCHECK(test_url_loader_factory_);
+ test_url_loader_factory_->NotifyClientOnComplete(status);
+ }
+
void FollowRedirect(
const std::vector<std::string>& removed_headers = {},
const net::HttpRequestHeaders& modified_headers =
@@ -368,9 +426,7 @@ class CorsURLLoaderTest : public testing::Test {
void ResetFactory(absl::optional<url::Origin> initiator,
uint32_t process_id,
- bool is_trusted,
- bool ignore_isolated_world_origin,
- bool skip_cors_enabled_scheme_check) {
+ const ResetFactoryParams& params = ResetFactoryParams()) {
if (process_id != mojom::kBrowserProcessId)
DCHECK(initiator.has_value());
@@ -383,15 +439,18 @@ class CorsURLLoaderTest : public testing::Test {
if (initiator) {
factory_params->request_initiator_origin_lock = *initiator;
}
- factory_params->is_trusted = is_trusted;
+ factory_params->is_trusted = params.is_trusted;
factory_params->process_id = process_id;
factory_params->is_corb_enabled = (process_id != mojom::kBrowserProcessId);
- factory_params->ignore_isolated_world_origin = ignore_isolated_world_origin;
+ factory_params->ignore_isolated_world_origin =
+ params.ignore_isolated_world_origin;
factory_params->factory_override = mojom::URLLoaderFactoryOverride::New();
factory_params->factory_override->overriding_factory =
test_url_loader_factory_receiver_->BindNewPipeAndPassRemote();
factory_params->factory_override->skip_cors_enabled_scheme_check =
- skip_cors_enabled_scheme_check;
+ params.skip_cors_enabled_scheme_check;
+ factory_params->client_security_state =
+ params.client_security_state.Clone();
auto resource_scheduler_client =
base::MakeRefCounted<ResourceSchedulerClient>(
process_id, ++last_issued_route_id, &resource_scheduler_,
@@ -404,14 +463,6 @@ class CorsURLLoaderTest : public testing::Test {
&origin_access_list_);
}
- void ResetFactory(absl::optional<url::Origin> initiator,
- uint32_t process_id) {
- auto params = network::mojom::URLLoaderFactoryParams::New();
- ResetFactory(initiator, process_id, params->is_trusted,
- params->ignore_isolated_world_origin,
- false /* skip_cors_enabled_scheme_check */);
- }
-
NetworkContext* network_context() { return network_context_.get(); }
void set_devtools_observer_for_next_request(MockDevToolsObserver* observer) {
@@ -451,7 +502,7 @@ class CorsURLLoaderTest : public testing::Test {
std::unique_ptr<TestURLLoaderFactory> test_url_loader_factory_;
std::unique_ptr<mojo::Receiver<mojom::URLLoaderFactory>>
test_url_loader_factory_receiver_;
- MockDevToolsObserver* devtools_observer_for_next_request_ = nullptr;
+ raw_ptr<MockDevToolsObserver> devtools_observer_for_next_request_ = nullptr;
// Holds URLLoader that CreateLoaderAndStart() creates.
mojo::Remote<mojom::URLLoader> url_loader_;
@@ -464,8 +515,6 @@ class CorsURLLoaderTest : public testing::Test {
// Holds for allowed origin access lists.
OriginAccessList origin_access_list_;
- DISALLOW_COPY_AND_ASSIGN(CorsURLLoaderTest);
-
net::RecordingNetLogObserver net_log_observer_;
};
@@ -572,8 +621,7 @@ TEST_F(CorsURLLoaderTest, ForbiddenMethods) {
EXPECT_TRUE(client().has_received_completion());
if (expect_allowed) {
EXPECT_THAT(client().completion_status().error_code, net::test::IsOk());
- EXPECT_THAT(bad_message_helper.bad_message_reports(),
- ::testing::IsEmptyMatcher());
+ EXPECT_THAT(bad_message_helper.bad_message_reports(), IsEmpty());
} else {
EXPECT_THAT(client().completion_status().error_code,
net::test::IsError(net::ERR_INVALID_ARGUMENT));
@@ -609,7 +657,7 @@ 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
+ // `request_initiator`. A renderer process would have run into NOTREACHED and
// mojo::ReportBadMessage via InitiatorLockCompatibility::kNoInitiator case in
// CorsURLLoaderFactory::IsValidRequest.
ResetFactory(absl::nullopt /* initiator */, mojom::kBrowserProcessId);
@@ -701,9 +749,14 @@ TEST_F(CorsURLLoaderTest, NavigateWithEarlyHints) {
}
TEST_F(CorsURLLoaderTest, NavigationFromRenderer) {
+ ResetFactory(url::Origin::Create(GURL("https://example.com/")),
+ kRendererProcessId);
+
ResourceRequest request;
request.mode = mojom::RequestMode::kNavigate;
- request.url = GURL("https://example.com/");
+ request.redirect_mode = mojom::RedirectMode::kManual;
+ request.url = GURL("https://some.other.example.com/");
+ request.navigation_redirect_chain.push_back(request.url);
request.request_initiator = absl::nullopt;
BadMessageTestHelper bad_message_helper;
@@ -717,12 +770,13 @@ TEST_F(CorsURLLoaderTest, NavigationFromRenderer) {
EXPECT_EQ(net::ERR_INVALID_ARGUMENT, client().completion_status().error_code);
EXPECT_THAT(bad_message_helper.bad_message_reports(),
::testing::ElementsAre(
- "CorsURLLoaderFactory: navigate from non-browser-process"));
+ "CorsURLLoaderFactory: lock VS initiator mismatch"));
}
TEST_F(CorsURLLoaderTest, SameOriginRequest) {
const GURL url("https://example.com/foo.png");
- CreateLoaderAndStart(url.GetOrigin(), url, mojom::RequestMode::kSameOrigin);
+ CreateLoaderAndStart(url.DeprecatedGetOriginAsURL(), url,
+ mojom::RequestMode::kSameOrigin);
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse();
@@ -739,7 +793,8 @@ TEST_F(CorsURLLoaderTest, SameOriginRequest) {
TEST_F(CorsURLLoaderTest, SameOriginRequestWithEarlyHints) {
const GURL url("https://example.com/foo.png");
- CreateLoaderAndStart(url.GetOrigin(), url, mojom::RequestMode::kSameOrigin);
+ CreateLoaderAndStart(url.DeprecatedGetOriginAsURL(), url,
+ mojom::RequestMode::kSameOrigin);
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveEarlyHints();
@@ -905,10 +960,10 @@ TEST_F(CorsURLLoaderTest, CorsEnabledSameCustomSchemeRequest) {
client().completion_status().cors_error_status->cors_error);
// Scheme check can be skipped via the factory params.
- auto params = network::mojom::URLLoaderFactoryParams::New();
+ ResetFactoryParams factory_params;
+ factory_params.skip_cors_enabled_scheme_check = true;
ResetFactory(url::Origin::Create(origin), mojom::kBrowserProcessId,
- params->is_trusted, params->ignore_isolated_world_origin,
- true /* skip_cors_enabled_scheme_check */);
+ factory_params);
// "Access-Control-Allow-Origin: *" accepts the custom scheme.
CreateLoaderAndStart(origin, url, mojom::RequestMode::kCors);
@@ -1388,10 +1443,9 @@ 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 */);
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(url_origin, kRendererProcessId, factory_params);
ResourceRequest request;
request.mode = mojom::RequestMode::kCors;
@@ -1611,9 +1665,9 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin) {
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 */,
- false /* skip_cors_enabled_scheme_check */);
+ ResetFactoryParams factory_params;
+ factory_params.ignore_isolated_world_origin = false;
+ ResetFactory(main_world_origin, kRendererProcessId, factory_params);
AddAllowListEntryForOrigin(isolated_world_origin, url.scheme(), url.host(),
mojom::CorsDomainMatchMode::kDisallowSubdomains);
@@ -1651,13 +1705,13 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin_Redirect) {
const url::Origin isolated_world_origin =
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
+ // `new_url` is same-origin as `url` to avoid tainting the response
// in CorsURLLoader::OnReceiveRedirect.
const GURL new_url("http://other.example.com/bar.png");
- ResetFactory(main_world_origin, kRendererProcessId, false /* trusted */,
- false /* ignore_isolated_world_origin */,
- false /* skip_cors_enabled_scheme_check */);
+ ResetFactoryParams factory_params;
+ factory_params.ignore_isolated_world_origin = false;
+ ResetFactory(main_world_origin, kRendererProcessId, factory_params);
AddAllowListEntryForOrigin(isolated_world_origin, url.scheme(), url.host(),
mojom::CorsDomainMatchMode::kDisallowSubdomains);
@@ -1709,9 +1763,7 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOriginIgnored) {
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 */,
- false /* skip_cors_enabled_scheme_check */);
+ ResetFactory(main_world_origin, kRendererProcessId);
AddAllowListEntryForOrigin(isolated_world_origin, url.scheme(), url.host(),
mojom::CorsDomainMatchMode::kDisallowSubdomains);
@@ -2223,7 +2275,7 @@ 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
+ // `request_initiator`. A renderer process would have run into NOTREACHED and
// mojo::ReportBadMessage via InitiatorLockCompatibility::kNoInitiator case in
// CorsURLLoaderFactory::IsValidRequest.
ResetFactory(absl::nullopt /* initiator */, mojom::kBrowserProcessId);
@@ -2296,7 +2348,7 @@ TEST_F(CorsURLLoaderTest, OmitCredentialsModeOnNavigation) {
"CorsURLLoaderFactory: unsupported credentials mode on navigation"));
}
-// Make sure than when a request is failed due to having |trusted_params| set
+// 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"));
@@ -2304,10 +2356,9 @@ TEST_F(CorsURLLoaderTest, TrustedParamsWithUntrustedFactoryFailsBeforeCORS) {
// 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(initiator, kRendererProcessId, is_trusted,
- ignore_isolated_world_origin,
- false /* skip_cors_enabled_scheme_check */);
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = is_trusted;
+ ResetFactory(initiator, kRendererProcessId, factory_params);
BadMessageTestHelper bad_message_helper;
@@ -2355,9 +2406,9 @@ TEST_F(CorsURLLoaderTest, TrustedParamsWithUntrustedFactoryFailsBeforeCORS) {
TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
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 */);
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator, kRendererProcessId, factory_params);
BadMessageTestHelper bad_message_helper;
@@ -2370,7 +2421,7 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
request.load_flags |= net::LOAD_RESTRICTED_PREFETCH;
request.trusted_params = ResourceRequest::TrustedParams();
- // Fill up the |trusted_params| NetworkIsolationKey member.
+ // Fill up the `trusted_params` NetworkIsolationKey member.
url::Origin request_origin = url::Origin::Create(request.url);
request.trusted_params->isolation_info = net::IsolationInfo::Create(
net::IsolationInfo::RequestType::kOther, request_origin, request_origin,
@@ -2395,12 +2446,13 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
// Test that when a request has LOAD_RESTRICTED_PREFETCH but no
// NetworkIsolationKey, CorsURLLoaderFactory rejects the request. This is
// because the LOAD_RESTRICTED_PREFETCH flag must only appear on requests that
-// make use of their TrustedParams' |isolation_info|.
+// make use of their TrustedParams' `isolation_info`.
TEST_F(CorsURLLoaderTest, RestrictedPrefetchFailsWithoutNIK) {
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 */);
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator, kRendererProcessId, factory_params);
BadMessageTestHelper bad_message_helper;
@@ -2600,9 +2652,11 @@ TEST_F(CorsURLLoaderTest, TAOCheckPassRedirect2) {
TEST_F(CorsURLLoaderTest, DevToolsObserverOnCorsErrorCallback) {
const GURL origin("https://example.com");
const url::Origin initiator_origin = url::Origin::Create(origin);
- ResetFactory(initiator_origin, kRendererProcessId, true /* is_trusted */,
- true /* ignore_isolated_world_origin */,
- false /* skip_cors_enabled_scheme_check */);
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
const GURL url("http://other.example.com/foo.png");
MockDevToolsObserver devtools_observer;
set_devtools_observer_for_next_request(&devtools_observer);
@@ -2803,7 +2857,8 @@ TEST_F(CorsURLLoaderTest, NetLogBasic) {
TEST_F(CorsURLLoaderTest, NetLogSameOriginRequest) {
const GURL url("https://example.com/foo.png");
- CreateLoaderAndStart(url.GetOrigin(), url, mojom::RequestMode::kSameOrigin);
+ CreateLoaderAndStart(url.DeprecatedGetOriginAsURL(), url,
+ mojom::RequestMode::kSameOrigin);
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse();
@@ -2827,7 +2882,8 @@ TEST_F(CorsURLLoaderTest, NetLogSameOriginRequest) {
TEST_F(CorsURLLoaderTest, NetLogCrossOriginSimpleRequest) {
const GURL origin("https://example.com");
const GURL url("https://other.example.com/foo.png");
- CreateLoaderAndStart(origin.GetOrigin(), url, mojom::RequestMode::kCors);
+ CreateLoaderAndStart(origin.DeprecatedGetOriginAsURL(), url,
+ mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse();
@@ -2870,6 +2926,1416 @@ TEST_F(CorsURLLoaderTest, PreflightMissingAllowOrigin) {
mojom::CorsError::kPreflightMissingAllowOriginHeader)));
}
+TEST_F(CorsURLLoaderTest, NonBrowserNavigationRedirect) {
+ BadMessageTestHelper bad_message_helper;
+
+ const GURL origin("https://example.com");
+ const GURL url("https://example.com/foo.png");
+ const GURL new_url("https://example.com/bar.png");
+
+ CreateLoaderAndStart(origin, url, mojom::RequestMode::kNavigate,
+ mojom::RedirectMode::kManual,
+ mojom::CredentialsMode::kInclude);
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(1, num_created_loaders());
+ EXPECT_EQ(GetRequest().url, url);
+ EXPECT_EQ(GetRequest().method, "GET");
+
+ NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(301, "GET", new_url));
+ RunUntilRedirectReceived();
+
+ EXPECT_TRUE(IsNetworkLoaderStarted());
+ EXPECT_FALSE(client().has_received_completion());
+ EXPECT_FALSE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_redirect());
+
+ FollowRedirect();
+
+ RunUntilComplete();
+ EXPECT_THAT(
+ bad_message_helper.bad_message_reports(),
+ ::testing::ElementsAre("CorsURLLoader: navigate from non-browser-process "
+ "should not call FollowRedirect"));
+}
+
+std::vector<std::pair<std::string, std::string>> MakeHeaderPairs(
+ const net::HttpRequestHeaders& headers) {
+ std::vector<std::pair<std::string, std::string>> result;
+ for (const auto& header : headers.GetHeaderVector()) {
+ result.emplace_back(header.key, header.value);
+ }
+ return result;
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessTargetIpAddressSpaceSimple) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+
+ // No target yet.
+ EXPECT_EQ(GetRequest().target_ip_address_space,
+ mojom::IPAddressSpace::kUnknown);
+
+ // Pretend we just hit a private IP address unexpectedly.
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ // The CORS URL loader restarts a new preflight request.
+ RunUntilCreateLoaderAndStartCalled();
+
+ // The second request expects the same IP address space.
+ EXPECT_EQ(GetRequest().target_ip_address_space,
+ mojom::IPAddressSpace::kPrivate);
+
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ // The CORS URL loader sends the actual request.
+ RunUntilCreateLoaderAndStartCalled();
+
+ // The actual request expects the same IP address space.
+ EXPECT_EQ(GetRequest().target_ip_address_space,
+ mojom::IPAddressSpace::kPrivate);
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessTargetIpAddressSpacePreflight) {
+ auto initiator = url::Origin::Create(GURL("https://foo.example"));
+ ResetFactory(initiator, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+
+ // No target yet.
+ EXPECT_EQ(GetRequest().target_ip_address_space,
+ mojom::IPAddressSpace::kUnknown);
+
+ // Pretend we just hit a private IP address unexpectedly.
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ // The CORS URL loader restarts a new preflight request.
+ RunUntilCreateLoaderAndStartCalled();
+
+ // The second request expects the same IP address space.
+ EXPECT_EQ(GetRequest().target_ip_address_space,
+ mojom::IPAddressSpace::kPrivate);
+
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ // The CORS URL loader sends the actual request.
+ RunUntilCreateLoaderAndStartCalled();
+
+ // The actual request expects the same IP address space.
+ EXPECT_EQ(GetRequest().target_ip_address_space,
+ mojom::IPAddressSpace::kPrivate);
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessRequestHeadersSimple) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(GetRequest().method, "GET");
+ EXPECT_FALSE(
+ GetRequest().headers.HasHeader("Access-Control-Request-Private-Network"));
+
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(GetRequest().method, "OPTIONS");
+ EXPECT_THAT(MakeHeaderPairs(GetRequest().headers),
+ IsSupersetOf({
+ Pair("Origin", "https://example.com"),
+ Pair("Access-Control-Request-Method", "GET"),
+ Pair("Access-Control-Request-Private-Network", "true"),
+ }));
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessRequestHeadersPreflight) {
+ auto initiator = url::Origin::Create(GURL("https://foo.example"));
+ ResetFactory(initiator, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(GetRequest().method, "OPTIONS");
+ EXPECT_FALSE(
+ GetRequest().headers.HasHeader("Access-Control-Request-Private-Network"));
+
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(GetRequest().method, "OPTIONS");
+ EXPECT_THAT(MakeHeaderPairs(GetRequest().headers),
+ IsSupersetOf({
+ Pair("Origin", "https://foo.example"),
+ Pair("Access-Control-Request-Method", "PUT"),
+ Pair("Access-Control-Request-Private-Network", "true"),
+ }));
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessMissingResponseHeaderSimple) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork);
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(expected_status));
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessMissingResponseHeaderPreflight) {
+ auto initiator = url::Origin::Create(GURL("https://foo.example"));
+ ResetFactory(initiator, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork);
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(expected_status));
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessInvalidResponseHeaderSimple) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "invalid-value"},
+ });
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightInvalidAllowPrivateNetwork, "invalid-value");
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(expected_status));
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessInvalidResponseHeaderPreflight) {
+ auto initiator = url::Origin::Create(GURL("https://foo.example"));
+ ResetFactory(initiator, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "invalid-value"},
+ });
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightInvalidAllowPrivateNetwork, "invalid-value");
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(expected_status));
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessSuccessSimple) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(GetRequest().method, "GET");
+
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessSuccessPreflight) {
+ auto initiator = url::Origin::Create(GURL("https://foo.example"));
+ ResetFactory(initiator, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(GetRequest().method, "PUT");
+
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessSuccessNoCors) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kNoCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+}
+
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessIgnoresCache) {
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ // Make a second request, observe that it does not use the preflight cache.
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+
+ // Second preflight request.
+ EXPECT_EQ(GetRequest().method, "OPTIONS");
+}
+
+// This test verifies that successful PNA preflights do not place entries in the
+// preflight cache that are shared with non-PNA preflights. In other words, a
+// non-PNA preflight cannot be skipped because a PNA preflght previously
+// succeeded.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessDoesNotShareCache) {
+ auto initiator = url::Origin::Create(GURL("https://foo.example"));
+ ResetFactory(initiator, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://foo.example"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ // Make a second request, observe that it does not use the preflight cache.
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+
+ // Second preflight request.
+ EXPECT_EQ(GetRequest().method, "OPTIONS");
+}
+
+class ClientSecurityStateBuilder {
+ public:
+ ClientSecurityStateBuilder() = default;
+ ~ClientSecurityStateBuilder() = default;
+
+ ClientSecurityStateBuilder& WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy policy) {
+ state_.private_network_request_policy = policy;
+ return *this;
+ }
+
+ ClientSecurityStateBuilder& WithIPAddressSpace(mojom::IPAddressSpace space) {
+ state_.ip_address_space = space;
+ return *this;
+ }
+
+ ClientSecurityStateBuilder& WithIsSecureContext(bool is_secure_context) {
+ state_.is_web_secure_context = is_secure_context;
+ return *this;
+ }
+
+ mojom::ClientSecurityStatePtr Build() const { return state_.Clone(); }
+
+ private:
+ mojom::ClientSecurityState state_;
+};
+
+class RequestTrustedParamsBuilder {
+ public:
+ RequestTrustedParamsBuilder() = default;
+ ~RequestTrustedParamsBuilder() = default;
+
+ RequestTrustedParamsBuilder& WithClientSecurityState(
+ mojom::ClientSecurityStatePtr client_security_state) {
+ params_.client_security_state = std::move(client_security_state);
+ return *this;
+ }
+
+ // Convenience shortcut for a default `ClientSecurityState` with a `policy`.
+ RequestTrustedParamsBuilder& WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy policy) {
+ return WithClientSecurityState(ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(policy)
+ .Build());
+ }
+
+ RequestTrustedParamsBuilder& WithDevToolsObserver(
+ mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer) {
+ params_.devtools_observer = std::move(devtools_observer);
+ return *this;
+ }
+
+ ResourceRequest::TrustedParams Build() const { return params_; }
+
+ private:
+ ResourceRequest::TrustedParams params_;
+};
+
+// The following `PrivateNetworkAccessPolicyWarn*` tests verify the correct
+// functioning of the `kPreflightWarn` private network request policy. That is,
+// preflight errors caused exclusively by Private Network Access logic should
+// be ignored.
+//
+// The `*PolicyWarnSimple*` variants test what happens in the "simple request"
+// case, when a preflight would not have been sent were it not for Private
+// Network Access. The `*PolicyWarnPreflight*` variants test what happens when
+// a preflight was attempted before noticing the private network access.
+//
+// TODO(https://crbug.com/1268378): Remove these tests once the policy is never
+// set to `kPreflightWarn` anymore.
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to a network error
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyWarnSimpleNetError) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ MockDevToolsObserver devtools_observer;
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithClientSecurityState(
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .WithIsSecureContext(true)
+ .WithIPAddressSpace(mojom::IPAddressSpace::kPublic)
+ .Build())
+ .WithDevToolsObserver(devtools_observer.Bind())
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(net::ERR_INVALID_ARGUMENT);
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ IsEmpty());
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ ElementsAre(MakeBucket(mojom::CorsError::kInvalidResponse, 1)));
+
+ devtools_observer.WaitUntilCorsError();
+
+ const MockDevToolsObserver::OnCorsErrorParams& error_params =
+ *devtools_observer.cors_error_params();
+ EXPECT_EQ(error_params.status,
+ CorsErrorStatus(mojom::CorsError::kInvalidResponse,
+ mojom::IPAddressSpace::kPrivate,
+ mojom::IPAddressSpace::kPrivate));
+ EXPECT_TRUE(error_params.is_warning);
+ ASSERT_TRUE(error_params.client_security_state);
+ EXPECT_TRUE(error_params.client_security_state->is_web_secure_context);
+ EXPECT_EQ(error_params.client_security_state->private_network_request_policy,
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn);
+ EXPECT_EQ(error_params.client_security_state->ip_address_space,
+ mojom::IPAddressSpace::kPublic);
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to a non-PNA CORS error
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyWarnSimpleCorsError) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ IsEmpty());
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightMissingAllowOriginHeader, 1)));
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to a missing PNA header
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest,
+ PrivateNetworkAccessPolicyWarnSimpleMissingAllowPrivateNetwork) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "GET"},
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ IsEmpty());
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork, 1)));
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to an invalid PNA header
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest,
+ PrivateNetworkAccessPolicyWarnSimpleInvalidAllowPrivateNetwork) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "GET"},
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "invalid-value"},
+ });
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ IsEmpty());
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightInvalidAllowPrivateNetwork, 1)));
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a CORS preflight request detects a private network request
+// - the following PNA preflight fails due to a network error
+//
+// ... the error is not ignored and the request is failed.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyWarnPreflightNetError) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(net::ERR_INVALID_ARGUMENT);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_INVALID_ARGUMENT);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ ElementsAre(MakeBucket(mojom::CorsError::kInvalidResponse, 1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ IsEmpty());
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a CORS preflight request detects a private network request
+// - the following PNA preflight fails due to a non-PNA CORS error
+//
+// ... the error is not ignored and the request is failed.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyWarnPreflightCorsError) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ MockDevToolsObserver devtools_observer;
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithClientSecurityState(
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .WithIsSecureContext(true)
+ .WithIPAddressSpace(mojom::IPAddressSpace::kPublic)
+ .Build())
+ .WithDevToolsObserver(devtools_observer.Bind())
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(CorsErrorStatus(
+ mojom::CorsError::kPreflightMissingAllowOriginHeader)));
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightMissingAllowOriginHeader, 1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ IsEmpty());
+
+ devtools_observer.WaitUntilCorsError();
+
+ const MockDevToolsObserver::OnCorsErrorParams& error_params =
+ *devtools_observer.cors_error_params();
+ EXPECT_EQ(
+ error_params.status,
+ CorsErrorStatus(mojom::CorsError::kPreflightMissingAllowOriginHeader));
+ EXPECT_FALSE(error_params.is_warning);
+ ASSERT_TRUE(error_params.client_security_state);
+ EXPECT_TRUE(error_params.client_security_state->is_web_secure_context);
+ EXPECT_EQ(error_params.client_security_state->private_network_request_policy,
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn);
+ EXPECT_EQ(error_params.client_security_state->ip_address_space,
+ mojom::IPAddressSpace::kPublic);
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a CORS preflight request detects a private network request
+// - the following PNA preflight fails due to a missing PNA header
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest,
+ PrivateNetworkAccessPolicyWarnPreflightMissingAllowPrivateNetwork) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ MockDevToolsObserver devtools_observer;
+
+ ResourceRequest request;
+ request.method = "PUT";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithClientSecurityState(
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .WithIsSecureContext(true)
+ .WithIPAddressSpace(mojom::IPAddressSpace::kPublic)
+ .Build())
+ .WithDevToolsObserver(devtools_observer.Bind())
+ .Build();
+ // Without this, the devtools observer is not passed to `PreflightController`
+ // and warnings suppressed inside `PreflightController` are not observed.
+ request.devtools_request_id = "devtools";
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "PUT"},
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::OK);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ IsEmpty());
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork, 1)));
+
+ devtools_observer.WaitUntilCorsError();
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork);
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+
+ const MockDevToolsObserver::OnCorsErrorParams& error_params =
+ *devtools_observer.cors_error_params();
+ EXPECT_EQ(error_params.devtools_request_id, "devtools");
+ EXPECT_EQ(error_params.status, expected_status);
+ EXPECT_TRUE(error_params.is_warning);
+ ASSERT_TRUE(error_params.client_security_state);
+ EXPECT_TRUE(error_params.client_security_state->is_web_secure_context);
+ EXPECT_EQ(error_params.client_security_state->private_network_request_policy,
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn);
+ EXPECT_EQ(error_params.client_security_state->ip_address_space,
+ mojom::IPAddressSpace::kPublic);
+}
+
+// The following `PrivateNetworkAccessPolicyBlock*` tests verify that PNA
+// preflights must succeed for the overall request to succeed when the private
+// network request policy is set to `kPreflightBlock`.
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightBlock`
+// - a private network request is detected
+// - the following PNA preflight fails due to a network error
+//
+// ... the error is not ignored and the request is failed.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyBlockNetError) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(net::ERR_INVALID_ARGUMENT);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_INVALID_ARGUMENT);
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ ElementsAre(MakeBucket(mojom::CorsError::kInvalidResponse, 1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ IsEmpty());
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightBlock`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to a non-PNA CORS error
+//
+// ... the error is not ignored and the request is failed.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyBlockCorsError) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ MockDevToolsObserver devtools_observer;
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithClientSecurityState(
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .WithIsSecureContext(true)
+ .WithIPAddressSpace(mojom::IPAddressSpace::kPublic)
+ .Build())
+ .WithDevToolsObserver(devtools_observer.Bind())
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse();
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(CorsErrorStatus(
+ mojom::CorsError::kPreflightMissingAllowOriginHeader)));
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightMissingAllowOriginHeader, 1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ IsEmpty());
+
+ devtools_observer.WaitUntilCorsError();
+
+ const MockDevToolsObserver::OnCorsErrorParams& error_params =
+ *devtools_observer.cors_error_params();
+ EXPECT_EQ(
+ error_params.status,
+ CorsErrorStatus(mojom::CorsError::kPreflightMissingAllowOriginHeader));
+ EXPECT_FALSE(error_params.is_warning);
+ ASSERT_TRUE(error_params.client_security_state);
+ EXPECT_TRUE(error_params.client_security_state->is_web_secure_context);
+ EXPECT_EQ(error_params.client_security_state->private_network_request_policy,
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock);
+ EXPECT_EQ(error_params.client_security_state->ip_address_space,
+ mojom::IPAddressSpace::kPublic);
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightBlock`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to a missing PNA header
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest,
+ PrivateNetworkAccessPolicyBlockMissingAllowPrivateNetwork) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ MockDevToolsObserver devtools_observer;
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithClientSecurityState(
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .WithIsSecureContext(true)
+ .WithIPAddressSpace(mojom::IPAddressSpace::kPublic)
+ .Build())
+ .WithDevToolsObserver(devtools_observer.Bind())
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "GET"},
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ });
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork);
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(expected_status));
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork, 1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ IsEmpty());
+
+ devtools_observer.WaitUntilCorsError();
+
+ const MockDevToolsObserver::OnCorsErrorParams& error_params =
+ *devtools_observer.cors_error_params();
+ EXPECT_EQ(error_params.status, expected_status);
+ EXPECT_FALSE(error_params.is_warning);
+ ASSERT_TRUE(error_params.client_security_state);
+ EXPECT_TRUE(error_params.client_security_state->is_web_secure_context);
+ EXPECT_EQ(error_params.client_security_state->private_network_request_policy,
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock);
+ EXPECT_EQ(error_params.client_security_state->ip_address_space,
+ mojom::IPAddressSpace::kPublic);
+}
+
+// This test verifies that when:
+//
+// - the private network request policy is set to `kPreflightWarn`
+// - a simple request detects a private network request
+// - the following PNA preflight fails due to an invalid PNA header
+//
+// ... the error is ignored and the request proceeds.
+TEST_F(CorsURLLoaderTest,
+ PrivateNetworkAccessPolicyBlockInvalidAllowPrivateNetwork) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ MockDevToolsObserver devtools_observer;
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithClientSecurityState(
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .WithIsSecureContext(true)
+ .WithIPAddressSpace(mojom::IPAddressSpace::kPublic)
+ .Build())
+ .WithDevToolsObserver(devtools_observer.Bind())
+ .Build();
+
+ base::HistogramTester histogram_tester;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnReceiveResponse({
+ {"Access-Control-Allow-Methods", "GET"},
+ {"Access-Control-Allow-Origin", "https://example.com"},
+ {"Access-Control-Allow-Credentials", "true"},
+ {"Access-Control-Allow-Private-Network", "invalid-value"},
+ });
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_FAILED);
+
+ CorsErrorStatus expected_status(
+ mojom::CorsError::kPreflightInvalidAllowPrivateNetwork, "invalid-value");
+ expected_status.target_address_space = mojom::IPAddressSpace::kPrivate;
+ EXPECT_THAT(client().completion_status().cors_error_status,
+ Optional(expected_status));
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightErrorHistogramName),
+ ElementsAre(MakeBucket(
+ mojom::CorsError::kPreflightInvalidAllowPrivateNetwork, 1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(kPreflightWarningHistogramName),
+ IsEmpty());
+
+ devtools_observer.WaitUntilCorsError();
+
+ const MockDevToolsObserver::OnCorsErrorParams& error_params =
+ *devtools_observer.cors_error_params();
+ EXPECT_EQ(error_params.status, expected_status);
+ EXPECT_FALSE(error_params.is_warning);
+ ASSERT_TRUE(error_params.client_security_state);
+ EXPECT_TRUE(error_params.client_security_state->is_web_secure_context);
+ EXPECT_EQ(error_params.client_security_state->private_network_request_policy,
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock);
+ EXPECT_EQ(error_params.client_security_state->ip_address_space,
+ mojom::IPAddressSpace::kPublic);
+}
+
+// The following `PrivateNetworkAccessPolicyOn*` tests verify that the private
+// network request policy can be set on the loader factory params or the request
+// itself, with preference given to the factory params.
+
+// This test verifies that when the `ResourceRequest` carries a client security
+// state and the loader factory params do not, the private network request
+// policy is taken from the request.
+//
+// This is achieved by setting the request policy to `kPreflightBlock` and
+// checking that preflight results are respected.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyOnRequestOnly) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .Build();
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(net::ERR_INVALID_ARGUMENT);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_INVALID_ARGUMENT);
+}
+
+// This test verifies that when the loader factory params carry a client
+// security state and the `ResourceRequest` does not, the private network
+// request policy is taken from the factory params.
+//
+// This is achieved by setting the factory policy to `kPreflightBlock` and
+// checking that preflight results are respected.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyOnFactoryOnly) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.client_security_state =
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .Build();
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(net::ERR_INVALID_ARGUMENT);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_INVALID_ARGUMENT);
+}
+
+// This test verifies that when both the `ResourceRequest` and the loader
+// factory params carry a client security state, the private network request
+// policy is taken from the factory.
+//
+// This is achieved by setting the factory policy to `kPreflightBlock`,
+// the request policy to `kPreflightWarn, and checking that preflight results
+// are respected.
+TEST_F(CorsURLLoaderTest, PrivateNetworkAccessPolicyOnFactoryAndRequest) {
+ auto initiator_origin = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactoryParams factory_params;
+ factory_params.is_trusted = true;
+ factory_params.client_security_state =
+ ClientSecurityStateBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightBlock)
+ .Build();
+ ResetFactory(initiator_origin, kRendererProcessId, factory_params);
+
+ ResourceRequest request;
+ request.method = "GET";
+ request.mode = mojom::RequestMode::kCors;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = initiator_origin;
+ request.trusted_params =
+ RequestTrustedParamsBuilder()
+ .WithPrivateNetworkRequestPolicy(
+ mojom::PrivateNetworkRequestPolicy::kPreflightWarn)
+ .Build();
+
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(CorsErrorStatus(
+ mojom::CorsError::kUnexpectedPrivateNetworkAccess,
+ mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate));
+
+ RunUntilCreateLoaderAndStartCalled();
+ NotifyLoaderClientOnComplete(net::ERR_INVALID_ARGUMENT);
+ RunUntilComplete();
+
+ EXPECT_EQ(client().completion_status().error_code, net::ERR_INVALID_ARGUMENT);
+}
+
} // namespace
} // namespace cors
diff --git a/chromium/services/network/cors/preflight_cache.cc b/chromium/services/network/cors/preflight_cache.cc
index 75cc0461fc5..9743744272c 100644
--- a/chromium/services/network/cors/preflight_cache.cc
+++ b/chromium/services/network/cors/preflight_cache.cc
@@ -76,7 +76,7 @@ void PreflightCache::AppendEntry(
std::unique_ptr<PreflightResult> preflight_result) {
DCHECK(preflight_result);
- // Do not cache |preflight_result| if |url| is too long.
+ // Do not cache `preflight_result` if `url` is too long.
const std::string url_spec = url.spec();
if (url_spec.length() >= kMaxKeyLength)
return;
@@ -114,11 +114,11 @@ bool PreflightCache::CheckIfRequestCanSkipPreflight(
// Check if the entry is still valid.
if (!cache_entry->second->IsExpired()) {
- // Both |origin| and |url| are in cache. Check if the entry is sufficient to
+ // Both `origin` and `url` are in cache. Check if the entry is sufficient to
// skip CORS-preflight.
if (cache_entry->second->EnsureAllowedRequest(
credentials_mode, method, request_headers, is_revalidating,
- PreflightResult::WithNonWildcardRequestHeadersSupport(true))) {
+ NonWildcardRequestHeadersSupport(true))) {
// Note that we always use the "with non-wildcard request headers"
// variant, because it is hard to generate the correct error information
// from here, and cache miss is in most case recoverable.
diff --git a/chromium/services/network/cors/preflight_cache.h b/chromium/services/network/cors/preflight_cache.h
index cb158274be2..3f56c6d387a 100644
--- a/chromium/services/network/cors/preflight_cache.h
+++ b/chromium/services/network/cors/preflight_cache.h
@@ -11,7 +11,6 @@
#include <tuple>
#include "base/component_export.h"
-#include "base/macros.h"
#include "net/base/network_isolation_key.h"
#include "net/http/http_request_headers.h"
#include "services/network/cors/preflight_result.h"
@@ -41,8 +40,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightCache final {
~PreflightCache();
- // Appends new |preflight_result| entry to the cache for a specified |origin|
- // and |url|.
+ // Appends new `preflight_result` entry to the cache for a specified `origin`
+ // and `url`.
void AppendEntry(const url::Origin& origin,
const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
@@ -63,7 +62,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightCache final {
// Counts cached entries for testing.
size_t CountEntriesForTesting() const;
- // Purges one cache entry if number of entries is larger than |max_entries|
+ // Purges one cache entry if number of entries is larger than `max_entries`
// for testing.
void MayPurgeForTesting(size_t max_entries, size_t purge_unit);
diff --git a/chromium/services/network/cors/preflight_cache_unittest.cc b/chromium/services/network/cors/preflight_cache_unittest.cc
index 7bb828ff893..7f2024ab9be 100644
--- a/chromium/services/network/cors/preflight_cache_unittest.cc
+++ b/chromium/services/network/cors/preflight_cache_unittest.cc
@@ -28,9 +28,9 @@ namespace {
class PreflightCacheTest : public testing::Test {
public:
PreflightCacheTest()
- : net_log_(net::NetLogWithSource::Make(
- net::NetLog::Get(),
- net::NetLogSourceType::CORS_URL_LOADER)) {}
+ : net_log_(
+ net::NetLogWithSource::Make(net::NetLog::Get(),
+ net::NetLogSourceType::URL_REQUEST)) {}
protected:
size_t CountEntries() const { return cache_.CountEntriesForTesting(); }
@@ -242,7 +242,7 @@ TEST_F(PreflightCacheTest, NetLogCheckCacheExist) {
std::vector<net::NetLogEntry> entries = net_log_observer.GetEntries();
ASSERT_EQ(entries.size(), 5u);
for (const auto& entry : entries) {
- EXPECT_EQ(entry.source.type, net::NetLogSourceType::CORS_URL_LOADER);
+ EXPECT_EQ(entry.source.type, net::NetLogSourceType::URL_REQUEST);
}
EXPECT_EQ(entries[0].type, net::NetLogEventType::CHECK_CORS_PREFLIGHT_CACHE);
EXPECT_EQ(net::GetStringValueFromParams(entries[0], "status"),
diff --git a/chromium/services/network/cors/preflight_controller.cc b/chromium/services/network/cors/preflight_controller.cc
index 05b66b589de..a3e76ea875c 100644
--- a/chromium/services/network/cors/preflight_controller.cc
+++ b/chromium/services/network/cors/preflight_controller.cc
@@ -8,6 +8,8 @@
#include <vector>
#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/strings/string_util.h"
@@ -15,6 +17,8 @@
#include "net/base/load_flags.h"
#include "net/base/network_isolation_key.h"
#include "net/http/http_request_headers.h"
+#include "net/log/net_log.h"
+#include "net/log/net_log_source.h"
#include "net/log/net_log_with_source.h"
#include "services/network/cors/cors_util.h"
#include "services/network/network_service.h"
@@ -82,6 +86,7 @@ std::string CreateAccessControlRequestHeadersHeader(
std::unique_ptr<ResourceRequest> CreatePreflightRequest(
const ResourceRequest& request,
bool tainted,
+ const net::NetLogWithSource& net_log_for_actual_request,
const absl::optional<base::UnguessableToken>& devtools_request_id) {
DCHECK(!request.url.has_username());
DCHECK(!request.url.has_password());
@@ -117,9 +122,14 @@ std::unique_ptr<ResourceRequest> CreatePreflightRequest(
header_names::kAccessControlRequestHeaders, request_headers);
}
- if (request.is_external_request) {
+ preflight_request->target_ip_address_space = request.target_ip_address_space;
+ if (preflight_request->target_ip_address_space !=
+ mojom::IPAddressSpace::kUnknown) {
+ // See the CORS-preflight fetch algorithm modifications laid out in the
+ // Private Network Access spec, in step 4 of the CORS preflight section as
+ // of writing: https://wicg.github.io/private-network-access/#cors-preflight
preflight_request->headers.SetHeader(
- header_names::kAccessControlRequestExternal, "true");
+ header_names::kAccessControlRequestPrivateNetwork, "true");
}
DCHECK(request.request_initiator);
@@ -144,22 +154,36 @@ std::unique_ptr<ResourceRequest> CreatePreflightRequest(
preflight_request->headers.SetHeader("Sec-Fetch-Mode", "cors");
if (devtools_request_id) {
- // Set |enable_load_timing| flag to make URLLoader fill the LoadTimingInfo
+ // Set `enable_load_timing` flag to make URLLoader fill the LoadTimingInfo
// in URLResponseHead, which will be sent to DevTools.
preflight_request->enable_load_timing = true;
- // Set |devtools_request_id| to make URLLoader send the raw request and the
+ // Set `devtools_request_id` to make URLLoader send the raw request and the
// raw response to DevTools.
preflight_request->devtools_request_id = devtools_request_id->ToString();
}
preflight_request->is_fetch_like_api = request.is_fetch_like_api;
preflight_request->is_favicon = request.is_favicon;
+ // Set `net_log_reference_info` to reference actual request from preflight
+ // request in NetLog.
+ preflight_request->net_log_reference_info =
+ net_log_for_actual_request.source();
+
+ net::NetLogSource net_log_source_for_preflight = net::NetLogSource(
+ net::NetLogSourceType::URL_REQUEST, net::NetLog::Get()->NextID());
+ net_log_for_actual_request.AddEventReferencingSource(
+ net::NetLogEventType::CORS_PREFLIGHT_URL_REQUEST,
+ net_log_source_for_preflight);
+ // Set `net_log_create_info` to specify NetLog source used in preflight
+ // URL Request.
+ preflight_request->net_log_create_info = net_log_source_for_preflight;
+
return preflight_request;
}
// Performs a CORS access check on the CORS-preflight response parameters.
// According to the note at https://fetch.spec.whatwg.org/#cors-preflight-fetch
-// step 6, even for a preflight check, |credentials_mode| should be checked on
+// step 6, even for a preflight check, `credentials_mode` should be checked on
// the actual request rather than preflight one.
absl::optional<CorsErrorStatus> CheckPreflightAccess(
const GURL& response_url,
@@ -221,24 +245,40 @@ absl::optional<CorsErrorStatus> CheckPreflightAccess(
return absl::nullopt;
}
- UMA_HISTOGRAM_ENUMERATION("Net.Cors.PreflightCheckError",
- error_status->cors_error);
return error_status;
}
-// Checks errors for the currently experimental "Access-Control-Allow-External"
-// header. Shares error conditions with standard preflight checking.
-// TODO(https://crbug.com/590714): Access-Control-Allow-External header is
-// stale. Following implementation need to be updated to follow the latest spec,
-// https://wicg.github.io/private-network-access/.
-absl::optional<CorsErrorStatus> CheckExternalPreflight(
- const absl::optional<std::string>& allow_external) {
- if (!allow_external)
- return CorsErrorStatus(mojom::CorsError::kPreflightMissingAllowExternal);
- if (*allow_external == kLowerCaseTrue)
+// Checks errors for the "Access-Control-Allow-Private-Network" header.
+//
+// See the CORS-preflight fetch algorithm modifications laid out in the Private
+// Network Access spec, in step 4 of the CORS preflight section as of writing:
+// https://wicg.github.io/private-network-access/#cors-preflight
+absl::optional<CorsErrorStatus> CheckAllowPrivateNetworkHeader(
+ const mojom::URLResponseHead& head,
+ const ResourceRequest& original_request) {
+ if (original_request.target_ip_address_space ==
+ mojom::IPAddressSpace::kUnknown) {
+ // Not a Private Network Access preflight.
return absl::nullopt;
- return CorsErrorStatus(mojom::CorsError::kPreflightInvalidAllowExternal,
- *allow_external);
+ }
+
+ absl::optional<std::string> header = GetHeaderString(
+ head.headers, header_names::kAccessControlAllowPrivateNetwork);
+ if (!header) {
+ CorsErrorStatus status(
+ mojom::CorsError::kPreflightMissingAllowPrivateNetwork);
+ status.target_address_space = original_request.target_ip_address_space;
+ return status;
+ }
+
+ if (*header != kLowerCaseTrue) {
+ CorsErrorStatus status(
+ mojom::CorsError::kPreflightInvalidAllowPrivateNetwork, *header);
+ status.target_address_space = original_request.target_ip_address_space;
+ return status;
+ }
+
+ return absl::nullopt;
}
std::unique_ptr<PreflightResult> CreatePreflightResult(
@@ -246,6 +286,10 @@ std::unique_ptr<PreflightResult> CreatePreflightResult(
const mojom::URLResponseHead& head,
const ResourceRequest& original_request,
bool tainted,
+ PreflightController::EnforcePrivateNetworkAccessHeader
+ enforce_private_network_access_header,
+ const mojom::ClientSecurityStatePtr& client_security_state,
+ mojom::DevToolsObserver* devtools_observer,
absl::optional<CorsErrorStatus>* detected_error_status) {
DCHECK(detected_error_status);
@@ -259,11 +303,25 @@ std::unique_ptr<PreflightResult> CreatePreflightResult(
if (*detected_error_status)
return nullptr;
- if (original_request.is_external_request) {
- *detected_error_status = CheckExternalPreflight(GetHeaderString(
- head.headers, header_names::kAccessControlAllowExternal));
- if (*detected_error_status)
+ absl::optional<CorsErrorStatus> status =
+ CheckAllowPrivateNetworkHeader(head, original_request);
+ if (status) {
+ if (enforce_private_network_access_header) {
+ *detected_error_status = std::move(status);
return nullptr;
+ }
+
+ // We only report these errors as warnings when they are suppressed, since
+ // `CorsURLLoader` already reports them otherwise.
+ if (devtools_observer) {
+ devtools_observer->OnCorsError(
+ original_request.devtools_request_id,
+ original_request.request_initiator, client_security_state.Clone(),
+ original_request.url, *status, /*is_warning=*/true);
+ }
+
+ base::UmaHistogramEnumeration(kPreflightWarningHistogramName,
+ status->cors_error);
}
absl::optional<mojom::CorsError> error;
@@ -276,14 +334,14 @@ std::unique_ptr<PreflightResult> CreatePreflightResult(
if (error)
*detected_error_status = CorsErrorStatus(*error);
+
return result;
}
absl::optional<CorsErrorStatus> CheckPreflightResult(
PreflightResult* result,
const ResourceRequest& original_request,
- PreflightResult::WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support) {
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support) {
absl::optional<CorsErrorStatus> status =
result->EnsureAllowedCrossOriginMethod(original_request.method);
if (status)
@@ -291,11 +349,14 @@ absl::optional<CorsErrorStatus> CheckPreflightResult(
return result->EnsureAllowedCrossOriginHeaders(
original_request.headers, original_request.is_revalidating,
- with_non_wildcard_request_headers_support);
+ non_wildcard_request_headers_support);
}
} // namespace
+const char kPreflightErrorHistogramName[] = "Net.Cors.PreflightCheckError2";
+const char kPreflightWarningHistogramName[] = "Net.Cors.PreflightCheckWarning";
+
class PreflightController::PreflightLoader final {
public:
PreflightLoader(
@@ -303,26 +364,30 @@ class PreflightController::PreflightLoader final {
CompletionCallback completion_callback,
const ResourceRequest& request,
WithTrustedHeaderClient with_trusted_header_client,
- WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support,
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
+ EnforcePrivateNetworkAccessHeader enforce_private_network_access_header,
bool tainted,
const net::NetworkTrafficAnnotationTag& annotation_tag,
const net::NetworkIsolationKey& network_isolation_key,
+ mojom::ClientSecurityStatePtr client_security_state,
mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
const net::NetLogWithSource net_log)
: controller_(controller),
completion_callback_(std::move(completion_callback)),
original_request_(request),
- with_non_wildcard_request_headers_support_(
- with_non_wildcard_request_headers_support),
+ non_wildcard_request_headers_support_(
+ non_wildcard_request_headers_support),
+ enforce_private_network_access_header_(
+ enforce_private_network_access_header),
tainted_(tainted),
network_isolation_key_(network_isolation_key),
+ client_security_state_(std::move(client_security_state)),
devtools_observer_(std::move(devtools_observer)),
net_log_(net_log) {
if (devtools_observer_)
devtools_request_id_ = base::UnguessableToken::Create();
auto preflight_request =
- CreatePreflightRequest(request, tainted, devtools_request_id_);
+ CreatePreflightRequest(request, tainted, net_log, devtools_request_id_);
if (devtools_observer_) {
DCHECK(devtools_request_id_);
@@ -342,6 +407,9 @@ class PreflightController::PreflightLoader final {
loader_->SetURLLoaderFactoryOptions(options);
}
+ PreflightLoader(const PreflightLoader&) = delete;
+ PreflightLoader& operator=(const PreflightLoader&) = delete;
+
void Request(mojom::URLLoaderFactory* loader_factory) {
DCHECK(loader_);
@@ -374,7 +442,7 @@ class PreflightController::PreflightLoader final {
false);
RemoveFromController();
- // |this| is deleted here.
+ // `this` is deleted here.
}
void HandleResponseHeader(const GURL& final_url,
@@ -392,23 +460,30 @@ class PreflightController::PreflightLoader final {
absl::optional<CorsErrorStatus> detected_error_status;
bool has_authorization_covered_by_wildcard = false;
std::unique_ptr<PreflightResult> result = CreatePreflightResult(
- final_url, head, original_request_, tainted_, &detected_error_status);
+ final_url, head, original_request_, tainted_,
+ enforce_private_network_access_header_, client_security_state_,
+ devtools_observer_ ? devtools_observer_.get() : nullptr,
+ &detected_error_status);
if (result) {
// Only log if there is a result to log.
net_log_.AddEvent(net::NetLogEventType::CORS_PREFLIGHT_RESULT,
[&result] { return result->NetLogParams(); });
- // Preflight succeeded. Check |original_request_| with |result|.
+ // Preflight succeeded. Check `original_request_` with `result`.
DCHECK(!detected_error_status);
detected_error_status =
CheckPreflightResult(result.get(), original_request_,
- with_non_wildcard_request_headers_support_);
+ non_wildcard_request_headers_support_);
has_authorization_covered_by_wildcard =
result->HasAuthorizationCoveredByWildcard(original_request_.headers);
}
if (!(original_request_.load_flags & net::LOAD_DISABLE_CACHE) &&
+ // TODO(https://crbug.com/1268312): Key the cache by target address
+ // space and remove this guard.
+ original_request_.target_ip_address_space ==
+ mojom::IPAddressSpace::kUnknown &&
!detected_error_status) {
controller_->AppendToCache(*original_request_.request_initiator,
original_request_.url, network_isolation_key_,
@@ -422,6 +497,9 @@ class PreflightController::PreflightLoader final {
void HandleResponseBody(std::unique_ptr<std::string> response_body) {
const int error = loader_->NetError();
+ const absl::optional<URLLoaderCompletionStatus>& status =
+ loader_->CompletionStatus();
+
if (!completion_callback_.is_null()) {
// As HandleResponseHeader() isn't called due to a request failure, such
// as unknown hosts. unreachable remote, reset by peer, and so on, we
@@ -431,19 +509,22 @@ class PreflightController::PreflightLoader final {
devtools_observer_->OnCorsPreflightRequestCompleted(
*devtools_request_id_, network::URLLoaderCompletionStatus(error));
}
- std::move(completion_callback_).Run(error, absl::nullopt, false);
+ std::move(completion_callback_)
+ .Run(error,
+ status.has_value() ? status->cors_error_status : absl::nullopt,
+ false);
}
RemoveFromController();
- // |this| is deleted here.
+ // `this` is deleted here.
}
- // Removes |this| instance from |controller_|. Once the method returns, |this|
+ // Removes `this` instance from `controller_`. Once the method returns, `this`
// is already removed.
void RemoveFromController() { controller_->RemoveLoader(this); }
// PreflightController owns all PreflightLoader instances, and should outlive.
- PreflightController* const controller_;
+ const raw_ptr<PreflightController> controller_;
// Holds SimpleURLLoader instance for the CORS-preflight request.
std::unique_ptr<SimpleURLLoader> loader_;
@@ -452,15 +533,15 @@ class PreflightController::PreflightLoader final {
PreflightController::CompletionCallback completion_callback_;
const ResourceRequest original_request_;
- const WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support_;
+ const NonWildcardRequestHeadersSupport non_wildcard_request_headers_support_;
+ const EnforcePrivateNetworkAccessHeader
+ enforce_private_network_access_header_;
const bool tainted_;
absl::optional<base::UnguessableToken> devtools_request_id_;
const net::NetworkIsolationKey network_isolation_key_;
+ const mojom::ClientSecurityStatePtr client_security_state_;
mojo::Remote<mojom::DevToolsObserver> devtools_observer_;
const net::NetLogWithSource net_log_;
-
- DISALLOW_COPY_AND_ASSIGN(PreflightLoader);
};
// static
@@ -468,7 +549,11 @@ std::unique_ptr<ResourceRequest>
PreflightController::CreatePreflightRequestForTesting(
const ResourceRequest& request,
bool tainted) {
- return CreatePreflightRequest(request, tainted, absl::nullopt);
+ return CreatePreflightRequest(
+ request, tainted,
+ net::NetLogWithSource::Make(net::NetLog::Get(),
+ net::NetLogSourceType::URL_REQUEST),
+ /*devtools_request_id=*/absl::nullopt);
}
// static
@@ -478,8 +563,12 @@ PreflightController::CreatePreflightResultForTesting(
const mojom::URLResponseHead& head,
const ResourceRequest& original_request,
bool tainted,
+ EnforcePrivateNetworkAccessHeader enforce_private_network_access_header,
absl::optional<CorsErrorStatus>* detected_error_status) {
return CreatePreflightResult(final_url, head, original_request, tainted,
+ enforce_private_network_access_header,
+ /*client_security_state=*/nullptr,
+ /*devtools_observer=*/nullptr,
detected_error_status);
}
@@ -497,13 +586,6 @@ PreflightController::CheckPreflightAccessForTesting(
actual_credentials_mode, origin);
}
-// static
-absl::optional<CorsErrorStatus>
-PreflightController::CheckExternalPreflightForTesting(
- const absl::optional<std::string>& allow_external) {
- return CheckExternalPreflight(allow_external);
-}
-
PreflightController::PreflightController(NetworkService* network_service)
: network_service_(network_service) {}
@@ -513,12 +595,13 @@ void PreflightController::PerformPreflightCheck(
CompletionCallback callback,
const ResourceRequest& request,
WithTrustedHeaderClient with_trusted_header_client,
- WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support,
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
+ EnforcePrivateNetworkAccessHeader enforce_private_network_access_header,
bool tainted,
const net::NetworkTrafficAnnotationTag& annotation_tag,
mojom::URLLoaderFactory* loader_factory,
const net::IsolationInfo& isolation_info,
+ mojom::ClientSecurityStatePtr client_security_state,
mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
const net::NetLogWithSource& net_log) {
DCHECK(request.request_initiator);
@@ -529,7 +612,12 @@ void PreflightController::PerformPreflightCheck(
: request.trusted_params.has_value()
? request.trusted_params->isolation_info.network_isolation_key()
: net::NetworkIsolationKey();
- if (!RetrieveCacheFlags(request.load_flags) && !request.is_external_request &&
+ if (!RetrieveCacheFlags(request.load_flags) &&
+ // TODO(https://crbug.com/1263483): Remove this.
+ !request.is_external_request &&
+ // TODO(https://crbug.com/1268312): Key the cache by target address space
+ // and remove this guard.
+ request.target_ip_address_space == mojom::IPAddressSpace::kUnknown &&
cache_.CheckIfRequestCanSkipPreflight(
request.request_initiator.value(), request.url, network_isolation_key,
request.credentials_mode, request.method, request.headers,
@@ -540,8 +628,10 @@ void PreflightController::PerformPreflightCheck(
auto emplaced_pair = loaders_.emplace(std::make_unique<PreflightLoader>(
this, std::move(callback), request, with_trusted_header_client,
- with_non_wildcard_request_headers_support, tainted, annotation_tag,
- network_isolation_key, std::move(devtools_observer), net_log));
+ non_wildcard_request_headers_support,
+ enforce_private_network_access_header, tainted, annotation_tag,
+ network_isolation_key, std::move(client_security_state),
+ std::move(devtools_observer), net_log));
(*emplaced_pair.first)->Request(loader_factory);
}
diff --git a/chromium/services/network/cors/preflight_controller.h b/chromium/services/network/cors/preflight_controller.h
index 8eebef03420..c7d2e8d97ab 100644
--- a/chromium/services/network/cors/preflight_controller.h
+++ b/chromium/services/network/cors/preflight_controller.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/types/strong_alias.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/cors/preflight_cache.h"
@@ -33,28 +33,41 @@ class NetworkService;
namespace cors {
+// Name of a histogram that records preflight errors (CorsError values).
+extern const char kPreflightErrorHistogramName[];
+
+// Name of a histogram that records suppressed preflight errors, aka warnings.
+extern const char kPreflightWarningHistogramName[];
+
// A class to manage CORS-preflight, making a CORS-preflight request, checking
// its result, and owning a CORS-preflight cache.
class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
public:
using CompletionCallback = base::OnceCallback<
void(int net_error, absl::optional<CorsErrorStatus>, bool)>;
+
using WithTrustedHeaderClient =
base::StrongAlias<class WithTrustedHeaderClientTag, bool>;
- using WithNonWildcardRequestHeadersSupport =
- PreflightResult::WithNonWildcardRequestHeadersSupport;
- // Creates a CORS-preflight ResourceRequest for a specified |request| for a
+
+ // TODO(https://crbug.com/1268378): Remove this once enforcement is always on.
+ using EnforcePrivateNetworkAccessHeader =
+ base::StrongAlias<class EnforcePrivateNetworkAccessHeaderTag, bool>;
+
+ // Creates a CORS-preflight ResourceRequest for a specified `request` for a
// URL that is originally requested.
static std::unique_ptr<ResourceRequest> CreatePreflightRequestForTesting(
const ResourceRequest& request,
bool tainted = false);
+
// Creates a PreflightResult for a specified response parameters for testing.
static std::unique_ptr<PreflightResult> CreatePreflightResultForTesting(
const GURL& final_url,
const mojom::URLResponseHead& head,
const ResourceRequest& original_request,
bool tainted,
+ EnforcePrivateNetworkAccessHeader enforce_private_network_access_header,
absl::optional<CorsErrorStatus>* detected_error_status);
+
// Checks CORS aceess on the CORS-preflight response parameters for testing.
static absl::optional<CorsErrorStatus> CheckPreflightAccessForTesting(
const GURL& response_url,
@@ -63,10 +76,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
const absl::optional<std::string>& allow_credentials_header,
mojom::CredentialsMode actual_credentials_mode,
const url::Origin& origin);
- // Checks errors for the currently experimental
- // "Access-Control-Allow-External" header for testing.
- static absl::optional<CorsErrorStatus> CheckExternalPreflightForTesting(
- const absl::optional<std::string>& allow_external);
explicit PreflightController(NetworkService* network_service);
@@ -82,12 +91,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
CompletionCallback callback,
const ResourceRequest& resource_request,
WithTrustedHeaderClient with_trusted_header_client,
- WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support,
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
+ EnforcePrivateNetworkAccessHeader enforce_private_network_access_header,
bool tainted,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
mojom::URLLoaderFactory* loader_factory,
const net::IsolationInfo& isolation_info,
+ mojom::ClientSecurityStatePtr client_security_state,
mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
const net::NetLogWithSource& net_log);
@@ -106,7 +116,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
std::set<std::unique_ptr<PreflightLoader>, base::UniquePtrComparator>
loaders_;
- NetworkService* const network_service_;
+ const raw_ptr<NetworkService> network_service_;
};
} // namespace cors
diff --git a/chromium/services/network/cors/preflight_controller_unittest.cc b/chromium/services/network/cors/preflight_controller_unittest.cc
index 3c23fb5abdf..badcd2d9034 100644
--- a/chromium/services/network/cors/preflight_controller_unittest.cc
+++ b/chromium/services/network/cors/preflight_controller_unittest.cc
@@ -13,6 +13,8 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
+#include "net/log/net_log.h"
+#include "net/log/net_log_source_type.h"
#include "net/log/net_log_with_source.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
@@ -40,8 +42,8 @@ namespace cors {
namespace {
using WithTrustedHeaderClient = PreflightController::WithTrustedHeaderClient;
-using WithNonWildcardRequestHeadersSupport =
- PreflightController::WithNonWildcardRequestHeadersSupport;
+using EnforcePrivateNetworkAccessHeader =
+ PreflightController::EnforcePrivateNetworkAccessHeader;
TEST(PreflightControllerCreatePreflightRequestTest, LexicographicalOrder) {
ResourceRequest request;
@@ -219,24 +221,30 @@ TEST(PreflightControllerOptionsTest, CheckOptions) {
base::test::TaskEnvironment task_environment_(
base::test::TaskEnvironment::MainThreadType::IO);
TestURLLoaderFactory url_loader_factory;
- PreflightController preflight_controller(nullptr /* network_service */);
+ PreflightController preflight_controller(/*network_service=*/nullptr);
network::ResourceRequest request;
request.url = GURL("https://example.com/");
request.request_initiator = url::Origin();
+ net::NetLogWithSource net_log = net::NetLogWithSource::Make(
+ net::NetLog::Get(), net::NetLogSourceType::URL_REQUEST);
preflight_controller.PerformPreflightCheck(
base::BindOnce([](int, absl::optional<CorsErrorStatus>, bool) {}),
request, WithTrustedHeaderClient(false),
- WithNonWildcardRequestHeadersSupport(false), false /* tainted */,
+ NonWildcardRequestHeadersSupport(false),
+ EnforcePrivateNetworkAccessHeader(false), /*tainted=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, &url_loader_factory, net::IsolationInfo(),
- /*devtools_observer=*/mojo::NullRemote(), net::NetLogWithSource());
+ /*client_security_state=*/nullptr,
+ /*devtools_observer=*/mojo::NullRemote(), net_log);
preflight_controller.PerformPreflightCheck(
base::BindOnce([](int, absl::optional<CorsErrorStatus>, bool) {}),
request, WithTrustedHeaderClient(true),
- WithNonWildcardRequestHeadersSupport(false), false /* tainted */,
+ NonWildcardRequestHeadersSupport(false),
+ EnforcePrivateNetworkAccessHeader(false), /*tainted=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, &url_loader_factory, net::IsolationInfo(),
- /*devtools_observer=*/mojo::NullRemote(), net::NetLogWithSource());
+ /*client_security_state=*/nullptr,
+ /*devtools_observer=*/mojo::NullRemote(), net_log);
ASSERT_EQ(2, url_loader_factory.NumPending());
EXPECT_EQ(mojom::kURLLoadOptionAsCorsPreflight,
@@ -351,8 +359,11 @@ class MockDevToolsObserver : public mojom::DevToolsObserver {
void OnCorsError(const absl::optional<std::string>& devtool_request_id,
const absl::optional<::url::Origin>& initiator_origin,
+ mojom::ClientSecurityStatePtr client_security_state,
const GURL& url,
- const network::CorsErrorStatus& status) override {}
+ const network::CorsErrorStatus& status,
+ bool is_warning) override {}
+
void Clone(mojo::PendingReceiver<DevToolsObserver> observer) override {
receivers_.Add(this, std::move(observer));
}
@@ -441,18 +452,22 @@ class PreflightControllerTest : public testing::Test {
base::BindOnce(&PreflightControllerTest::HandleRequestCompletion,
base::Unretained(this)),
request, WithTrustedHeaderClient(false),
- with_non_wildcard_request_headers_support_, tainted,
+ non_wildcard_request_headers_support_,
+ EnforcePrivateNetworkAccessHeader(false), tainted,
TRAFFIC_ANNOTATION_FOR_TESTS, url_loader_factory_remote_.get(),
- isolation_info, devtools_observer_->Bind(), net::NetLogWithSource());
+ isolation_info, /*client_security_state=*/nullptr,
+ devtools_observer_->Bind(),
+ net::NetLogWithSource::Make(net::NetLog::Get(),
+ net::NetLogSourceType::URL_REQUEST));
run_loop_->Run();
}
void SetAccessControlAllowOrigin(const url::Origin origin) {
access_control_allow_origin_ = origin;
}
- void SetWithNonWildcardRequestHeadersSupport(bool value) {
- with_non_wildcard_request_headers_support_ =
- WithNonWildcardRequestHeadersSupport(value);
+ void SetNonWildcardRequestHeadersSupport(bool value) {
+ non_wildcard_request_headers_support_ =
+ NonWildcardRequestHeadersSupport(value);
}
const url::Origin& test_initiator_origin() const {
@@ -531,8 +546,7 @@ class PreflightControllerTest : public testing::Test {
net::test_server::EmbeddedTestServer test_server_;
size_t access_count_ = 0;
- WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support_;
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support_;
std::unique_ptr<PreflightController> preflight_controller_;
int net_error_ = net::OK;
@@ -661,7 +675,7 @@ TEST_F(PreflightControllerTest, CheckTaintedRequest) {
request.url = GetURL("/tainted");
request.request_initiator = test_initiator_origin();
- PerformPreflightCheck(request, true /* tainted */);
+ PerformPreflightCheck(request, /*tainted=*/true);
EXPECT_EQ(net::OK, net_error());
ASSERT_FALSE(status());
EXPECT_EQ(1u, access_count());
@@ -680,7 +694,9 @@ TEST_F(PreflightControllerTest, CheckResponseWithNullHeaders) {
std::unique_ptr<PreflightResult> result =
PreflightController::CreatePreflightResultForTesting(
- url, response_head, request, tainted, &detected_error_status);
+ url, response_head, request, tainted,
+ PreflightController::EnforcePrivateNetworkAccessHeader(true),
+ &detected_error_status);
EXPECT_FALSE(result);
}
@@ -724,7 +740,7 @@ TEST_F(PreflightControllerTest, AuthorizationIsCoveredByWildcard) {
request.request_initiator = test_initiator_origin();
request.headers.SetHeader("authorization", "foobar");
- SetWithNonWildcardRequestHeadersSupport(false);
+ SetNonWildcardRequestHeadersSupport(false);
PerformPreflightCheck(request);
EXPECT_EQ(net::OK, net_error());
@@ -741,7 +757,7 @@ TEST_F(PreflightControllerTest, AuthorizationIsNotCoveredByWildcard) {
request.request_initiator = test_initiator_origin();
request.headers.SetHeader("authorization", "foobar");
- SetWithNonWildcardRequestHeadersSupport(true);
+ SetNonWildcardRequestHeadersSupport(true);
PerformPreflightCheck(request);
EXPECT_EQ(net::ERR_FAILED, net_error());
@@ -760,18 +776,18 @@ TEST_F(PreflightControllerTest, CheckPreflightAccessDetectsErrorStatus) {
// Status 200-299 should pass.
EXPECT_FALSE(PreflightController::CheckPreflightAccessForTesting(
response_url, 200, allow_all_header,
- absl::nullopt /* allow_credentials_header */,
+ /*allow_credentials_header=*/absl::nullopt,
network::mojom::CredentialsMode::kOmit, origin));
EXPECT_FALSE(PreflightController::CheckPreflightAccessForTesting(
response_url, 299, allow_all_header,
- absl::nullopt /* allow_credentials_header */,
+ /*allow_credentials_header=*/absl::nullopt,
network::mojom::CredentialsMode::kOmit, origin));
// Status 300 should fail.
absl::optional<CorsErrorStatus> invalid_status_error =
PreflightController::CheckPreflightAccessForTesting(
response_url, 300, allow_all_header,
- absl::nullopt /* allow_credentials_header */,
+ /*allow_credentials_header=*/absl::nullopt,
network::mojom::CredentialsMode::kOmit, origin);
ASSERT_TRUE(invalid_status_error);
EXPECT_EQ(mojom::CorsError::kPreflightInvalidStatus,
@@ -780,33 +796,13 @@ TEST_F(PreflightControllerTest, CheckPreflightAccessDetectsErrorStatus) {
// Status 0 should fail too.
invalid_status_error = PreflightController::CheckPreflightAccessForTesting(
response_url, 0, allow_all_header,
- absl::nullopt /* allow_credentials_header */,
+ /*allow_credentials_header=*/absl::nullopt,
network::mojom::CredentialsMode::kOmit, origin);
ASSERT_TRUE(invalid_status_error);
EXPECT_EQ(mojom::CorsError::kPreflightInvalidStatus,
invalid_status_error->cors_error);
}
-TEST_F(PreflightControllerTest, CheckExternalPreflightErrors) {
- EXPECT_FALSE(PreflightController::CheckExternalPreflightForTesting(
- std::string("true")));
-
- absl::optional<CorsErrorStatus> error2 =
- PreflightController::CheckExternalPreflightForTesting(absl::nullopt);
- ASSERT_TRUE(error2);
- EXPECT_EQ(mojom::CorsError::kPreflightMissingAllowExternal,
- error2->cors_error);
- EXPECT_EQ("", error2->failed_parameter);
-
- absl::optional<CorsErrorStatus> error3 =
- PreflightController::CheckExternalPreflightForTesting(
- std::string("TRUE"));
- ASSERT_TRUE(error3);
- EXPECT_EQ(mojom::CorsError::kPreflightInvalidAllowExternal,
- error3->cors_error);
- EXPECT_EQ("TRUE", error3->failed_parameter);
-}
-
} // namespace
} // namespace cors
diff --git a/chromium/services/network/cors/preflight_result.cc b/chromium/services/network/cors/preflight_result.cc
index a820cad3b02..2d6386bcb8a 100644
--- a/chromium/services/network/cors/preflight_result.cc
+++ b/chromium/services/network/cors/preflight_result.cc
@@ -78,8 +78,8 @@ base::TimeDelta ParseAccessControlMaxAge(
return base::Seconds(seconds);
}
-// Parses |string| as a Access-Control-Allow-* header value, storing the result
-// in |set|. This function returns false when |string| does not satisfy the
+// Parses `string` as a Access-Control-Allow-* header value, storing the result
+// in `set`. This function returns false when `string` does not satisfy the
// syntax here: https://fetch.spec.whatwg.org/#http-new-header-syntax.
bool ParseAccessControlAllowList(const absl::optional<std::string>& string,
base::flat_set<std::string>* set,
@@ -177,11 +177,11 @@ absl::optional<CorsErrorStatus>
PreflightResult::EnsureAllowedCrossOriginHeaders(
const net::HttpRequestHeaders& headers,
bool is_revalidating,
- WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support) const {
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support)
+ const {
const bool has_wildcard = !credentials_ && headers_.contains("*");
if (has_wildcard) {
- if (with_non_wildcard_request_headers_support) {
+ if (non_wildcard_request_headers_support) {
// "authorization" is the only member of
// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name.
if (headers.HasHeader(kAuthorization) &&
@@ -221,8 +221,8 @@ bool PreflightResult::EnsureAllowedRequest(
const std::string& method,
const net::HttpRequestHeaders& headers,
bool is_revalidating,
- WithNonWildcardRequestHeadersSupport
- with_non_wildcard_request_headers_support) const {
+ NonWildcardRequestHeadersSupport non_wildcard_request_headers_support)
+ const {
if (!credentials_ && credentials_mode == mojom::CredentialsMode::kInclude) {
return false;
}
@@ -231,9 +231,8 @@ bool PreflightResult::EnsureAllowedRequest(
return false;
}
- if (EnsureAllowedCrossOriginHeaders(
- headers, is_revalidating,
- with_non_wildcard_request_headers_support)) {
+ if (EnsureAllowedCrossOriginHeaders(headers, is_revalidating,
+ non_wildcard_request_headers_support)) {
return false;
}
diff --git a/chromium/services/network/cors/preflight_result.h b/chromium/services/network/cors/preflight_result.h
index 8f9ab24f77a..5e08b5a8a0c 100644
--- a/chromium/services/network/cors/preflight_result.h
+++ b/chromium/services/network/cors/preflight_result.h
@@ -28,6 +28,9 @@ namespace network {
namespace cors {
+using NonWildcardRequestHeadersSupport =
+ base::StrongAlias<class NonWildcardRequestHeadersSupportTag, bool>;
+
// Holds CORS-preflight request results, and provides access check methods.
// Each instance can be cached by CORS-preflight cache.
// See https://fetch.spec.whatwg.org/#concept-cache.
@@ -36,13 +39,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightResult final {
// Represents whether
// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name
// is supported.
- using WithNonWildcardRequestHeadersSupport =
- base::StrongAlias<class WithNonWildcardRequestHeadersSupportTag, bool>;
static void SetTickClockForTesting(const base::TickClock* tick_clock);
// Creates a PreflightResult instance from a CORS-preflight result. Returns
- // nullptr and |detected_error| is populated with the failed reason if the
+ // nullptr and `detected_error` is populated with the failed reason if the
// passed parameters contain an invalid entry, and the pointer is valid.
static std::unique_ptr<PreflightResult> Create(
const mojom::CredentialsMode credentials_mode,
@@ -56,11 +57,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightResult final {
~PreflightResult();
- // Checks if the given |method| is allowed by the CORS-preflight response.
+ // Checks if the given `method` is allowed by the CORS-preflight response.
absl::optional<CorsErrorStatus> EnsureAllowedCrossOriginMethod(
const std::string& method) const;
- // Checks if the given all |headers| are allowed by the CORS-preflight
+ // Checks if the given all `headers` are allowed by the CORS-preflight
// response.
// This does not reject when the headers contain forbidden headers
// (https://fetch.spec.whatwg.org/#forbidden-header-name) because they may be
@@ -69,14 +70,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightResult final {
absl::optional<CorsErrorStatus> EnsureAllowedCrossOriginHeaders(
const net::HttpRequestHeaders& headers,
bool is_revalidating,
- WithNonWildcardRequestHeadersSupport
+ NonWildcardRequestHeadersSupport
with_non_wildcard_request_headers_support) const;
// Checks if this entry is expired.
bool IsExpired() const;
- // Checks if the given combination of |credentials_mode|, |method|, and
- // |headers| is allowed by the CORS-preflight response.
+ // Checks if the given combination of `credentials_mode`, `method`, and
+ // `headers` is allowed by the CORS-preflight response.
// This also does not reject the forbidden headers as
// EnsureAllowCrossOriginHeaders does not.
bool EnsureAllowedRequest(
@@ -84,7 +85,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightResult final {
const std::string& method,
const net::HttpRequestHeaders& headers,
bool is_revalidating,
- WithNonWildcardRequestHeadersSupport
+ NonWildcardRequestHeadersSupport
with_non_wildcard_request_headers_support) const;
// Returns true when `headers` has "authorization" which is covered by the
@@ -125,7 +126,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightResult final {
// Corresponds to the fields of the CORS-preflight cache with the same name in
// the fetch spec.
- // |headers_| holds strings in lower case for case-insensitive search.
+ // `headers_` holds strings in lower case for case-insensitive search.
bool credentials_;
base::flat_set<std::string> methods_;
base::flat_set<std::string> headers_;
diff --git a/chromium/services/network/cors/preflight_result_unittest.cc b/chromium/services/network/cors/preflight_result_unittest.cc
index 8ecd765aab3..2d31940bf26 100644
--- a/chromium/services/network/cors/preflight_result_unittest.cc
+++ b/chromium/services/network/cors/preflight_result_unittest.cc
@@ -17,8 +17,6 @@ namespace cors {
namespace {
using PreflightResultTest = ::testing::Test;
-using WithNonWildcardRequestHeadersSupport =
- PreflightResult::WithNonWildcardRequestHeadersSupport;
constexpr absl::optional<mojom::CorsError> kNoError;
@@ -209,7 +207,7 @@ TEST_F(PreflightResultTest, EnsureHeaders) {
headers.AddHeadersFromString(test.request_headers);
EXPECT_EQ(test.expected_result,
result->EnsureAllowedCrossOriginHeaders(
- headers, false, WithNonWildcardRequestHeadersSupport(false)));
+ headers, false, NonWildcardRequestHeadersSupport(false)));
}
}
@@ -225,7 +223,7 @@ TEST_F(PreflightResultTest, EnsureRequest) {
EXPECT_EQ(test.expected_result == absl::nullopt,
result->EnsureAllowedRequest(
test.request_credentials_mode, test.request_method, headers,
- false, WithNonWildcardRequestHeadersSupport(false)));
+ false, NonWildcardRequestHeadersSupport(false)));
}
for (const auto& test : kHeaderCases) {
@@ -239,7 +237,7 @@ TEST_F(PreflightResultTest, EnsureRequest) {
EXPECT_EQ(test.expected_result == absl::nullopt,
result->EnsureAllowedRequest(
test.request_credentials_mode, test.request_method, headers,
- false, WithNonWildcardRequestHeadersSupport(false)));
+ false, NonWildcardRequestHeadersSupport(false)));
}
struct {
@@ -266,7 +264,7 @@ TEST_F(PreflightResultTest, EnsureRequest) {
EXPECT_EQ(test.expected_result,
result->EnsureAllowedRequest(
test.request_credentials_mode, "GET", headers, false,
- WithNonWildcardRequestHeadersSupport(false)));
+ NonWildcardRequestHeadersSupport(false)));
}
}
@@ -302,10 +300,9 @@ TEST_F(PreflightResultTest, ParseAllowControlAllowHeaders) {
for (const auto& request_header : test.values_to_be_accepted) {
net::HttpRequestHeaders headers;
headers.AddHeadersFromString(request_header);
- EXPECT_EQ(
- absl::nullopt,
- result->EnsureAllowedCrossOriginHeaders(
- headers, false, WithNonWildcardRequestHeadersSupport(false)));
+ EXPECT_EQ(absl::nullopt,
+ result->EnsureAllowedCrossOriginHeaders(
+ headers, false, NonWildcardRequestHeadersSupport(false)));
}
}
}
@@ -349,7 +346,7 @@ TEST_F(PreflightResultTest,
ASSERT_EQ(error, absl::nullopt);
net::HttpRequestHeaders headers = CreateHeaders({{"auThorization", "x"}});
const auto status = result->EnsureAllowedCrossOriginHeaders(
- headers, false, WithNonWildcardRequestHeadersSupport(false));
+ headers, false, NonWildcardRequestHeadersSupport(false));
EXPECT_EQ(status, absl::nullopt);
}
@@ -364,7 +361,7 @@ TEST_F(PreflightResultTest,
ASSERT_EQ(error, absl::nullopt);
net::HttpRequestHeaders headers = CreateHeaders({{"auThorization", "x"}});
const auto status = result->EnsureAllowedCrossOriginHeaders(
- headers, false, WithNonWildcardRequestHeadersSupport(true));
+ headers, false, NonWildcardRequestHeadersSupport(true));
ASSERT_NE(status, absl::nullopt);
EXPECT_EQ(status->cors_error,
mojom::CorsError::kHeaderDisallowedByPreflightResponse);
@@ -384,7 +381,7 @@ TEST_F(
ASSERT_EQ(error, absl::nullopt);
net::HttpRequestHeaders headers = CreateHeaders({{"auThorization", "x"}});
const auto status = result->EnsureAllowedCrossOriginHeaders(
- headers, false, WithNonWildcardRequestHeadersSupport(true));
+ headers, false, NonWildcardRequestHeadersSupport(true));
EXPECT_EQ(status, absl::nullopt);
}
diff --git a/chromium/services/network/crl_set_distributor.h b/chromium/services/network/crl_set_distributor.h
index 9711244891e..5c7975a63fe 100644
--- a/chromium/services/network/crl_set_distributor.h
+++ b/chromium/services/network/crl_set_distributor.h
@@ -10,7 +10,6 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
diff --git a/chromium/services/network/data_pipe_element_reader.h b/chromium/services/network/data_pipe_element_reader.h
index 10436e73009..27d86d352f5 100644
--- a/chromium/services/network/data_pipe_element_reader.h
+++ b/chromium/services/network/data_pipe_element_reader.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/data_pipe_element_reader_unittest.cc b/chromium/services/network/data_pipe_element_reader_unittest.cc
index d61561a8057..c9002c9d79b 100644
--- a/chromium/services/network/data_pipe_element_reader_unittest.cc
+++ b/chromium/services/network/data_pipe_element_reader_unittest.cc
@@ -9,7 +9,6 @@
#include <limits>
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
@@ -34,6 +33,10 @@ class PassThroughDataPipeGetter : public mojom::DataPipeGetter {
public:
explicit PassThroughDataPipeGetter() = default;
+ PassThroughDataPipeGetter(const PassThroughDataPipeGetter&) = delete;
+ PassThroughDataPipeGetter& operator=(const PassThroughDataPipeGetter&) =
+ delete;
+
mojo::PendingRemote<network::mojom::DataPipeGetter>
GetDataPipeGetterRemote() {
EXPECT_FALSE(receiver_.is_bound());
@@ -81,8 +84,6 @@ class PassThroughDataPipeGetter : public mojom::DataPipeGetter {
mojo::Receiver<network::mojom::DataPipeGetter> receiver_{this};
mojo::ScopedDataPipeProducerHandle write_pipe_;
ReadCallback read_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(PassThroughDataPipeGetter);
};
class DataPipeElementReaderTest : public testing::Test {
diff --git a/chromium/services/network/dhcp_pac_file_fetcher_mojo.h b/chromium/services/network/dhcp_pac_file_fetcher_mojo.h
index 1b5ac74d1ee..47f86a82d82 100644
--- a/chromium/services/network/dhcp_pac_file_fetcher_mojo.h
+++ b/chromium/services/network/dhcp_pac_file_fetcher_mojo.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/dns_config_change_manager.h b/chromium/services/network/dns_config_change_manager.h
index f225f9d8a59..38122358cda 100644
--- a/chromium/services/network/dns_config_change_manager.h
+++ b/chromium/services/network/dns_config_change_manager.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_DNS_CONFIG_CHANGE_MANAGER_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/chromium/services/network/dns_config_change_manager_unittest.cc b/chromium/services/network/dns_config_change_manager_unittest.cc
index d6c2afef18e..8f778032e11 100644
--- a/chromium/services/network/dns_config_change_manager_unittest.cc
+++ b/chromium/services/network/dns_config_change_manager_unittest.cc
@@ -24,6 +24,11 @@ class TestDnsConfigChangeManagerClient
manager_remote->RequestNotifications(receiver_.BindNewPipeAndPassRemote());
}
+ TestDnsConfigChangeManagerClient(const TestDnsConfigChangeManagerClient&) =
+ delete;
+ TestDnsConfigChangeManagerClient& operator=(
+ const TestDnsConfigChangeManagerClient&) = delete;
+
void OnDnsConfigChanged() override {
num_notifications_++;
if (num_notifications_ >= num_notifications_expected_)
@@ -43,14 +48,16 @@ class TestDnsConfigChangeManagerClient
int num_notifications_expected_ = INT_MAX;
base::RunLoop run_loop_;
mojo::Receiver<mojom::DnsConfigChangeManagerClient> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(TestDnsConfigChangeManagerClient);
};
class DnsConfigChangeManagerTest : public testing::Test {
public:
DnsConfigChangeManagerTest() {}
+ DnsConfigChangeManagerTest(const DnsConfigChangeManagerTest&) = delete;
+ DnsConfigChangeManagerTest& operator=(const DnsConfigChangeManagerTest&) =
+ delete;
+
DnsConfigChangeManager* manager() { return &manager_; }
TestDnsConfigChangeManagerClient* client() { return &client_; }
@@ -60,8 +67,6 @@ class DnsConfigChangeManagerTest : public testing::Test {
net::NetworkChangeNotifier::CreateMockIfNeeded();
DnsConfigChangeManager manager_;
TestDnsConfigChangeManagerClient client_{&manager_};
-
- DISALLOW_COPY_AND_ASSIGN(DnsConfigChangeManagerTest);
};
TEST_F(DnsConfigChangeManagerTest, Notification) {
diff --git a/chromium/services/network/expect_ct_reporter.cc b/chromium/services/network/expect_ct_reporter.cc
index b8b2686297c..0554779f554 100644
--- a/chromium/services/network/expect_ct_reporter.cc
+++ b/chromium/services/network/expect_ct_reporter.cc
@@ -12,8 +12,6 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/json/json_writer.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -194,8 +192,6 @@ void ExpectCTReporter::OnExpectCTFailed(
return;
}
- UMA_HISTOGRAM_BOOLEAN("SSL.ExpectCTReportSendingAttempt", true);
-
SendPreflight(report_uri, serialized_report, network_isolation_key);
}
@@ -290,7 +286,6 @@ void ExpectCTReporter::SendPreflight(
void ExpectCTReporter::OnReportFailure(const GURL& report_uri,
int net_error,
int http_response_code) {
- base::UmaHistogramSparse("SSL.ExpectCTReportFailure2", -net_error);
if (!failure_callback_.is_null())
failure_callback_.Run();
}
diff --git a/chromium/services/network/expect_ct_reporter.h b/chromium/services/network/expect_ct_reporter.h
index 8389544e9b8..d620cc0f52d 100644
--- a/chromium/services/network/expect_ct_reporter.h
+++ b/chromium/services/network/expect_ct_reporter.h
@@ -10,7 +10,7 @@
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "net/base/network_isolation_key.h"
#include "net/http/transport_security_state.h"
#include "net/url_request/url_request.h"
@@ -111,7 +111,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ExpectCTReporter
std::unique_ptr<net::ReportSender> report_sender_;
- net::URLRequestContext* request_context_;
+ raw_ptr<net::URLRequestContext> request_context_;
base::RepeatingClosure success_callback_;
base::RepeatingClosure failure_callback_;
diff --git a/chromium/services/network/expect_ct_reporter_unittest.cc b/chromium/services/network/expect_ct_reporter_unittest.cc
index c993f86cc8b..c1bd23b8471 100644
--- a/chromium/services/network/expect_ct_reporter_unittest.cc
+++ b/chromium/services/network/expect_ct_reporter_unittest.cc
@@ -14,7 +14,6 @@
#include "base/json/json_reader.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
-#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/values.h"
@@ -38,9 +37,6 @@
namespace network {
namespace {
-const char kSendHistogramName[] = "SSL.ExpectCTReportSendingAttempt";
-const char kFailureHistogramName[] = "SSL.ExpectCTReportFailure2";
-
// A test ReportSender that exposes the latest report URI and
// serialized report to be sent.
class TestCertificateReportSender : public net::ReportSender {
@@ -136,12 +132,12 @@ void CheckReportCertificateChain(
const base::ListValue& chain) {
std::vector<std::string> pem_encoded_chain;
expected_cert->GetPEMEncodedChain(&pem_encoded_chain);
- ASSERT_EQ(pem_encoded_chain.size(), chain.GetList().size());
+ base::Value::ConstListView chain_list = chain.GetList();
+ ASSERT_EQ(pem_encoded_chain.size(), chain_list.size());
for (size_t i = 0; i < pem_encoded_chain.size(); i++) {
- std::string cert_pem;
- ASSERT_TRUE(chain.GetString(i, &cert_pem));
- EXPECT_EQ(pem_encoded_chain[i], cert_pem);
+ ASSERT_TRUE(chain_list[i].is_string());
+ EXPECT_EQ(pem_encoded_chain[i], chain_list[i].GetString());
}
}
@@ -171,26 +167,26 @@ net::ct::SignedCertificateTimestamp::Origin SCTOriginStringToOrigin(
return ::testing::AssertionFailure() << "Failed to serialize SCT";
}
- for (size_t i = 0; i < report_list.GetList().size(); i++) {
- const base::DictionaryValue* report_sct;
- if (!report_list.GetDictionary(i, &report_sct)) {
+ for (const base::Value& report_sct_value : report_list.GetList()) {
+ if (!report_sct_value.is_dict()) {
return ::testing::AssertionFailure()
<< "Failed to get dictionary value from report SCT list";
}
-
+ const base::DictionaryValue& report_sct =
+ base::Value::AsDictionaryValue(report_sct_value);
std::string serialized_sct;
- EXPECT_TRUE(report_sct->GetString("serialized_sct", &serialized_sct));
+ EXPECT_TRUE(report_sct.GetString("serialized_sct", &serialized_sct));
std::string decoded_serialized_sct;
EXPECT_TRUE(base::Base64Decode(serialized_sct, &decoded_serialized_sct));
if (decoded_serialized_sct != expected_serialized_sct)
continue;
std::string source;
- EXPECT_TRUE(report_sct->GetString("source", &source));
+ EXPECT_TRUE(report_sct.GetString("source", &source));
EXPECT_EQ(expected_sct->origin, SCTOriginStringToOrigin(source));
std::string report_status;
- EXPECT_TRUE(report_sct->GetString("status", &report_status));
+ EXPECT_TRUE(report_sct.GetString("status", &report_status));
switch (expected_status) {
case net::ct::SCT_STATUS_LOG_UNKNOWN:
EXPECT_EQ("unknown", report_status);
@@ -282,6 +278,10 @@ class TestExpectCTNetworkDelegate : public net::NetworkDelegateImpl {
public:
TestExpectCTNetworkDelegate() = default;
+ TestExpectCTNetworkDelegate(const TestExpectCTNetworkDelegate&) = delete;
+ TestExpectCTNetworkDelegate& operator=(const TestExpectCTNetworkDelegate&) =
+ delete;
+
using OnBeforeURLRequestCallback =
base::RepeatingCallback<void(net::URLRequest* request)>;
@@ -311,8 +311,6 @@ class TestExpectCTNetworkDelegate : public net::NetworkDelegateImpl {
private:
OnBeforeURLRequestCallback on_before_url_request_callback_;
base::RepeatingClosure url_request_destroyed_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(TestExpectCTNetworkDelegate);
};
// A test fixture that allows tests to send a report and wait until the
@@ -322,6 +320,9 @@ class ExpectCTReporterWaitTest : public ::testing::Test {
ExpectCTReporterWaitTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
+ ExpectCTReporterWaitTest(const ExpectCTReporterWaitTest&) = delete;
+ ExpectCTReporterWaitTest& operator=(const ExpectCTReporterWaitTest&) = delete;
+
void SetUp() override {
// Initializes URLRequestContext after the thread is set up.
context_ = std::make_unique<net::TestURLRequestContext>(
@@ -357,8 +358,6 @@ class ExpectCTReporterWaitTest : public ::testing::Test {
TestExpectCTNetworkDelegate network_delegate_;
std::unique_ptr<net::TestURLRequestContext> context_;
base::test::TaskEnvironment task_environment_;
-
- DISALLOW_COPY_AND_ASSIGN(ExpectCTReporterWaitTest);
};
std::unique_ptr<net::test_server::HttpResponse> ReplyToPostWith200(
@@ -489,9 +488,6 @@ TEST_F(ExpectCTReporterTest, FeatureDisabled) {
&HandleReportPreflight, kGoodCorsHeaders, base::RepeatingClosure()));
ASSERT_TRUE(test_server().Start());
- base::HistogramTester histograms;
- histograms.ExpectTotalCount(kSendHistogramName, 0);
-
TestCertificateReportSender* sender = new TestCertificateReportSender();
net::TestURLRequestContext context;
ExpectCTReporter reporter(&context, base::NullCallback(),
@@ -519,8 +515,6 @@ TEST_F(ExpectCTReporterTest, FeatureDisabled) {
net::NetworkIsolationKey());
EXPECT_TRUE(sender->latest_report_uri().is_empty());
EXPECT_TRUE(sender->latest_serialized_report().empty());
-
- histograms.ExpectTotalCount(kSendHistogramName, 0);
}
// Enable the feature and send a dummy report. The test will fail if the
@@ -543,9 +537,6 @@ TEST_F(ExpectCTReporterTest, FeatureDisabled) {
// Test that no report is sent if the report URI is empty.
TEST_F(ExpectCTReporterTest, EmptyReportURI) {
- base::HistogramTester histograms;
- histograms.ExpectTotalCount(kSendHistogramName, 0);
-
TestCertificateReportSender* sender = new TestCertificateReportSender();
net::TestURLRequestContext context;
ExpectCTReporter reporter(&context, base::NullCallback(),
@@ -560,36 +551,6 @@ TEST_F(ExpectCTReporterTest, EmptyReportURI) {
net::NetworkIsolationKey());
EXPECT_TRUE(sender->latest_report_uri().is_empty());
EXPECT_TRUE(sender->latest_serialized_report().empty());
-
- histograms.ExpectTotalCount(kSendHistogramName, 0);
-}
-
-// Test that if a report fails to send, the UMA metric is recorded.
-TEST_F(ExpectCTReporterWaitTest, SendReportFailure) {
- base::HistogramTester histograms;
- histograms.ExpectTotalCount(kFailureHistogramName, 0);
- histograms.ExpectTotalCount(kSendHistogramName, 0);
-
- ExpectCTReporter reporter(context(), base::NullCallback(),
- base::NullCallback());
-
- net::SSLInfo ssl_info;
- ssl_info.cert =
- net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
- ssl_info.unverified_cert = net::ImportCertFromFile(
- net::GetTestCertsDirectory(), "localhost_cert.pem");
-
- net::HostPortPair host_port("example.test", 443);
- GURL report_uri(
- net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED));
-
- SendReport(&reporter, host_port, report_uri, base::Time(), ssl_info);
-
- histograms.ExpectTotalCount(kFailureHistogramName, 1);
- histograms.ExpectBucketCount(kFailureHistogramName,
- -net::ERR_CONNECTION_FAILED, 1);
- histograms.ExpectTotalCount(kSendHistogramName, 1);
- histograms.ExpectBucketCount(kSendHistogramName, true, 1);
}
// Test that if a report fails to send, the failure callback is called.
@@ -616,10 +577,6 @@ TEST_F(ExpectCTReporterWaitTest, SendReportFailureCallback) {
// Test that a sent report has the right format.
TEST_F(ExpectCTReporterTest, SendReport) {
- base::HistogramTester histograms;
- histograms.ExpectTotalCount(kFailureHistogramName, 0);
- histograms.ExpectTotalCount(kSendHistogramName, 0);
-
TestCertificateReportSender* sender = new TestCertificateReportSender();
net::TestURLRequestContext context;
ExpectCTReporter reporter(&context, base::NullCallback(),
@@ -714,10 +671,6 @@ TEST_F(ExpectCTReporterTest, SendReport) {
ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport(
sender->latest_serialized_report(),
net::HostPortPair::FromURL(report_uri), kExpirationTimeStr, ssl_info));
-
- histograms.ExpectTotalCount(kFailureHistogramName, 0);
- histograms.ExpectTotalCount(kSendHistogramName, 1);
- histograms.ExpectBucketCount(kSendHistogramName, true, 1);
}
// Test that the success callback is called when a report is successfully sent.
diff --git a/chromium/services/network/first_party_sets/first_party_set_parser.cc b/chromium/services/network/first_party_sets/first_party_set_parser.cc
index 43aa46d79bb..38a9caaf700 100644
--- a/chromium/services/network/first_party_sets/first_party_set_parser.cc
+++ b/chromium/services/network/first_party_sets/first_party_set_parser.cc
@@ -207,4 +207,20 @@ FirstPartySetParser::ParseSetsFromComponentUpdater(base::StringPiece raw_sets) {
return map;
}
+base::flat_map<net::SchemefulSite, net::SchemefulSite>
+FirstPartySetParser::ParseSetsFromStream(std::istream& input) {
+ base::flat_map<net::SchemefulSite, net::SchemefulSite> map;
+ base::flat_set<net::SchemefulSite> elements;
+ for (std::string line; std::getline(input, line);) {
+ absl::optional<base::Value> maybe_value = base::JSONReader::Read(
+ line, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS);
+ if (!maybe_value.has_value())
+ return {};
+ if (!ParseSet(*maybe_value, map, elements))
+ return {};
+ }
+
+ return map;
+}
+
} // namespace network
diff --git a/chromium/services/network/first_party_sets/first_party_set_parser.h b/chromium/services/network/first_party_sets/first_party_set_parser.h
index 56b7db58656..822cf0d9e5d 100644
--- a/chromium/services/network/first_party_sets/first_party_set_parser.h
+++ b/chromium/services/network/first_party_sets/first_party_set_parser.h
@@ -5,6 +5,8 @@
#ifndef SERVICES_NETWORK_FIRST_PARTY_SETS_FIRST_PARTY_SET_PARSER_H_
#define SERVICES_NETWORK_FIRST_PARTY_SETS_FIRST_PARTY_SET_PARSER_H_
+#include <istream>
+
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
@@ -35,6 +37,16 @@ class FirstPartySetParser {
static base::flat_map<net::SchemefulSite, net::SchemefulSite>
ParseSetsFromComponentUpdater(base::StringPiece raw_sets);
+ // Parses newline-delimited First-Party sets (as JSON records) from `input`.
+ // Each record should follow the format specified in this
+ // document:https://github.com/privacycg/first-party-sets. This function does
+ // not check versions or assertions, since it is intended only for sets
+ // received by Component Updater.
+ //
+ // Returns an empty map if parsing or validation of any set failed.
+ static base::flat_map<net::SchemefulSite, net::SchemefulSite>
+ ParseSetsFromStream(std::istream& input);
+
// Canonicalizes the passed in origin to a registered domain. In particular,
// this ensures that the origin is non-opaque, is HTTPS, and has a registered
// domain. Returns absl::nullopt in case of any error.
diff --git a/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc b/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc
index 0dd0d38ea3e..2e5a048c2cb 100644
--- a/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc
+++ b/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc
@@ -4,6 +4,8 @@
#include "services/network/first_party_sets/first_party_set_parser.h"
+#include <sstream>
+
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -46,6 +48,16 @@ TEST(FirstPartySetParser, RejectsNonemptyMalformed) {
IsEmpty());
}
+TEST(FirstPartySetParser, Streamed_RejectsNonemptyMalformed) {
+ // If the input isn't valid JSON, we should
+ // reject it.
+ const std::string input = "certainly not valid JSON";
+
+ ASSERT_FALSE(base::JSONReader::Read(input));
+ std::istringstream stream(input);
+ EXPECT_THAT(FirstPartySetParser::ParseSetsFromStream(stream), IsEmpty());
+}
+
TEST(FirstPartySetParser, RejectsNonListInput) {
// The outermost value should be a list.
const std::string input = "{}";
@@ -96,6 +108,18 @@ TEST(FirstPartySetParser, AcceptsMinimal) {
SerializesTo("https://example.test"))));
}
+TEST(FirstPartySetParser, Streamed_AcceptsMinimal) {
+ const std::string input =
+ R"({"owner": "https://example.test", "members": ["https://aaaa.test"]})";
+
+ std::istringstream stream(input);
+ EXPECT_THAT(FirstPartySetParser::ParseSetsFromStream(stream),
+ UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
+ SerializesTo("https://example.test")),
+ Pair(SerializesTo("https://aaaa.test"),
+ SerializesTo("https://example.test"))));
+}
+
TEST(FirstPartySetParser, RejectsMissingOwner) {
const std::string input = R"( [ { "members": ["https://aaaa.test"] } ] )";
@@ -287,6 +311,25 @@ TEST(FirstPartySetParser, AcceptsMultipleSets) {
SerializesTo("https://foo.test"))));
}
+TEST(FirstPartySetParser, Streamed_AcceptsMultipleSets) {
+ const std::string input =
+ "{\"owner\": \"https://example.test\", \"members\": "
+ "[\"https://member1.test\"]}\n"
+ "{\"owner\": \"https://foo.test\", \"members\": "
+ "[\"https://member2.test\"]}";
+
+ std::istringstream stream(input);
+ EXPECT_THAT(FirstPartySetParser::ParseSetsFromStream(stream),
+ UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
+ SerializesTo("https://example.test")),
+ Pair(SerializesTo("https://member1.test"),
+ SerializesTo("https://example.test")),
+ Pair(SerializesTo("https://foo.test"),
+ SerializesTo("https://foo.test")),
+ Pair(SerializesTo("https://member2.test"),
+ SerializesTo("https://foo.test"))));
+}
+
TEST(FirstPartySetParser, RejectsInvalidSets_InvalidOwner) {
const std::string input = R"(
[
diff --git a/chromium/services/network/first_party_sets/first_party_sets.cc b/chromium/services/network/first_party_sets/first_party_sets.cc
index 826b403a2a9..bd86b31205f 100644
--- a/chromium/services/network/first_party_sets/first_party_sets.cc
+++ b/chromium/services/network/first_party_sets/first_party_sets.cc
@@ -10,12 +10,20 @@
#include <vector>
#include "base/containers/contains.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "base/ranges/algorithm.h"
+#include "base/sequence_checker.h"
#include "base/strings/string_split.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_util.h"
#include "net/cookies/same_party_context.h"
#include "services/network/first_party_sets/first_party_set_parser.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -62,13 +70,25 @@ net::SamePartyContext::Type ContextTypeFromBool(bool is_same_party) {
: net::SamePartyContext::Type::kCrossParty;
}
+std::string ReadSetsFile(base::File sets_file) {
+ std::string raw_sets;
+ base::ScopedFILE file(FileToFILE(std::move(sets_file), "r"));
+ return base::ReadStreamToString(file.get(), &raw_sets) ? raw_sets : "";
+}
+
} // namespace
FirstPartySets::FirstPartySets() = default;
-FirstPartySets::~FirstPartySets() = default;
+FirstPartySets::~FirstPartySets() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
void FirstPartySets::SetManuallySpecifiedSet(const std::string& flag_value) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!net::cookie_util::IsFirstPartySetsEnabled())
+ return;
+
manually_specified_set_ = CanonicalizeSet(base::SplitString(
flag_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY));
@@ -77,13 +97,38 @@ void FirstPartySets::SetManuallySpecifiedSet(const std::string& flag_value) {
ClearSiteDataOnChangedSetsIfReady();
}
-base::flat_map<net::SchemefulSite, net::SchemefulSite>*
-FirstPartySets::ParseAndSet(base::StringPiece raw_sets) {
- sets_ = FirstPartySetParser::ParseSetsFromComponentUpdater(raw_sets);
+void FirstPartySets::ParseAndSet(base::File sets_file) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!net::cookie_util::IsFirstPartySetsEnabled())
+ return;
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&ReadSetsFile, std::move(sets_file)),
+ base::BindOnce(&FirstPartySets::OnReadSetsFile,
+ weak_factory_.GetWeakPtr()));
+}
+
+void FirstPartySets::OnReadSetsFile(const std::string& raw_sets) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!net::cookie_util::IsFirstPartySetsEnabled())
+ return;
+
+ bool is_v1_format = raw_sets.find('[') < raw_sets.find('{');
+ if (is_v1_format) {
+ // The file is a single list of records; V1 format.
+ sets_ = FirstPartySetParser::ParseSetsFromComponentUpdater(raw_sets);
+ } else {
+ // The file is invalid, or is a newline-delimited sequence of
+ // records; V2 format.
+ std::istringstream stream(raw_sets);
+ sets_ = FirstPartySetParser::ParseSetsFromStream(stream);
+ }
+ base::UmaHistogramBoolean("Cookie.FirstPartySets.ComponentIsV1Format",
+ is_v1_format);
+
ApplyManuallySpecifiedSet();
component_sets_ready_ = true;
ClearSiteDataOnChangedSetsIfReady();
- return &sets_;
}
bool FirstPartySets::IsContextSamePartyWithSite(
@@ -91,6 +136,7 @@ bool FirstPartySets::IsContextSamePartyWithSite(
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
bool infer_singleton_sets) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const absl::optional<net::SchemefulSite> site_owner =
FindOwner(site, infer_singleton_sets);
if (!site_owner.has_value())
@@ -114,6 +160,9 @@ net::SamePartyContext FirstPartySets::ComputeContext(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ const base::ElapsedTimer timer;
+
net::SamePartyContext::Type context_type = ContextTypeFromBool(
IsContextSamePartyWithSite(site, top_frame_site, party_context,
false /* infer_singleton_sets */));
@@ -124,6 +173,10 @@ net::SamePartyContext FirstPartySets::ComputeContext(
ContextTypeFromBool(IsContextSamePartyWithSite(
site, top_frame_site, {}, true /* infer_singleton_sets */));
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Cookie.FirstPartySets.ComputeContext.Latency", timer.Elapsed(),
+ base::Microseconds(1), base::Milliseconds(100), 50);
+
return net::SamePartyContext(context_type, ancestors, top_resource);
}
@@ -131,6 +184,7 @@ net::FirstPartySetsContextType FirstPartySets::ComputeContextType(
const net::SchemefulSite& site,
const absl::optional<net::SchemefulSite>& top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
constexpr bool infer_singleton_sets = true;
const absl::optional<net::SchemefulSite> site_owner =
FindOwner(site, infer_singleton_sets);
@@ -157,23 +211,40 @@ net::FirstPartySetsContextType FirstPartySets::ComputeContextType(
const absl::optional<net::SchemefulSite> FirstPartySets::FindOwner(
const net::SchemefulSite& site,
bool infer_singleton_sets) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ const base::ElapsedTimer timer;
+
net::SchemefulSite normalized_site = site;
normalized_site.ConvertWebSocketToHttp();
+
+ absl::optional<net::SchemefulSite> owner;
const auto it = sets_.find(normalized_site);
- if (it != sets_.end())
- return it->second;
- if (infer_singleton_sets)
- return normalized_site;
- return absl::nullopt;
+ if (it != sets_.end()) {
+ owner = it->second;
+ } else if (infer_singleton_sets) {
+ owner = normalized_site;
+ }
+
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Cookie.FirstPartySets.FindOwner.Latency", timer.Elapsed(),
+ base::Microseconds(1), base::Milliseconds(100), 50);
+ return owner;
+}
+
+const absl::optional<net::SchemefulSite> FirstPartySets::FindOwner(
+ const net::SchemefulSite& site) const {
+ return FindOwner(site, /*infer_singleton_sets=*/false);
}
bool FirstPartySets::IsInNontrivialFirstPartySet(
const net::SchemefulSite& site) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return FindOwner(site, /*infer_singleton_sets=*/false).has_value();
}
base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>
FirstPartySets::Sets() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>> sets;
for (const auto& pair : sets_) {
@@ -191,6 +262,7 @@ FirstPartySets::Sets() const {
}
void FirstPartySets::ApplyManuallySpecifiedSet() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!manually_specified_set_)
return;
@@ -230,6 +302,7 @@ void FirstPartySets::ApplyManuallySpecifiedSet() {
}
void FirstPartySets::SetPersistedSets(base::StringPiece raw_sets) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
raw_persisted_sets_ = std::string(raw_sets);
persisted_sets_ready_ = true;
ClearSiteDataOnChangedSetsIfReady();
@@ -237,12 +310,15 @@ void FirstPartySets::SetPersistedSets(base::StringPiece raw_sets) {
void FirstPartySets::SetOnSiteDataCleared(
base::OnceCallback<void(const std::string&)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
on_site_data_cleared_ = std::move(callback);
ClearSiteDataOnChangedSetsIfReady();
}
base::flat_set<net::SchemefulSite> FirstPartySets::ComputeSetsDiff(
- const base::flat_map<net::SchemefulSite, net::SchemefulSite>& old_sets) {
+ const base::flat_map<net::SchemefulSite, net::SchemefulSite>& old_sets)
+ const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (old_sets.empty())
return {};
@@ -261,6 +337,7 @@ base::flat_set<net::SchemefulSite> FirstPartySets::ComputeSetsDiff(
}
void FirstPartySets::ClearSiteDataOnChangedSetsIfReady() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!persisted_sets_ready_ || !component_sets_ready_ || !manual_sets_ready_ ||
on_site_data_cleared_.is_null())
return;
diff --git a/chromium/services/network/first_party_sets/first_party_sets.h b/chromium/services/network/first_party_sets/first_party_sets.h
index fc87e515566..386031e63fd 100644
--- a/chromium/services/network/first_party_sets/first_party_sets.h
+++ b/chromium/services/network/first_party_sets/first_party_sets.h
@@ -12,6 +12,9 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
+#include "base/files/file.h"
+#include "base/sequence_checker.h"
+#include "base/thread_annotations.h"
#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/same_party_context.h"
@@ -30,30 +33,23 @@ class FirstPartySets {
FirstPartySets(const FirstPartySets&) = delete;
FirstPartySets& operator=(const FirstPartySets&) = delete;
+ // Stores the First-Party Set that was provided via the `kUseFirstPartySet`
+ // flag/switch.
+ //
+ // Has no effect if `kFirstPartySets` is disabled.
void SetManuallySpecifiedSet(const std::string& flag_value);
- // Overwrites the current members-to-owners map with the values in |raw_sets|,
- // which should be the JSON-encoded string representation of a collection of
- // set declarations according to the format specified in this document:
- // https://github.com/privacycg/first-party-sets. Returns a pointer to the
- // mapping, for testing.
+ // Asynchronously overwrites the current members-to-owners map with the sets
+ // in `sets_file`. `sets_file` is expected to contain either a JSON-encoded
+ // array of records, or a sequence of newline-delimited JSON records. Each
+ // record is a set declaration in the format specified here:
+ // https://github.com/privacycg/first-party-sets.
//
- // In case of invalid input, clears the current members-to-owners map, but
- // keeps any manually-specified set (i.e. a set provided on the command line).
- base::flat_map<net::SchemefulSite, net::SchemefulSite>* ParseAndSet(
- base::StringPiece raw_sets);
-
- // Returns whether the `site` is same-party with the `party_context`, and
- // `top_frame_site` (if it is not nullptr). That is, is the `site`'s owner the
- // same as the owners of every member of `party_context` and of
- // `top_frame_site`? Note: if `site` is not a member of a First-Party Set
- // (with more than one member), then this returns false. If `top_frame_site`
- // is nullptr, then it is ignored.
- bool IsContextSamePartyWithSite(
- const net::SchemefulSite& site,
- const net::SchemefulSite* top_frame_site,
- const std::set<net::SchemefulSite>& party_context,
- bool infer_singleton_sets) const;
+ // In case of invalid input, the members-to-owners map is cleared, but keeps
+ // any manually-specified set (i.e. a set provided on the command line).
+ //
+ // Has no effect if `kFirstPartySets` is disabled.
+ void ParseAndSet(base::File sets_file);
// Computes the SameParty context, indicating whether `site` is same-party
// with `top_frame_site` (if not nullptr) and `party_context`. The context
@@ -82,7 +78,10 @@ class FirstPartySets {
// non-singleton) First-Party Set.
bool IsInNontrivialFirstPartySet(const net::SchemefulSite& site) const;
- int64_t size() const { return sets_.size(); }
+ int64_t size() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return sets_.size();
+ }
// Returns a mapping from owner to set members. For convenience of iteration,
// the members of the set includes the owner.
@@ -96,7 +95,30 @@ class FirstPartySets {
void SetOnSiteDataCleared(
base::OnceCallback<void(const std::string&)> callback);
+ // Returns nullopt if First-Party Sets are disabled or if the input is not in
+ // a nontrivial set.
+ // If FPS are enabled and the input site is in a nontrivial set, then this
+ // returns the owner site of that set.
+ const absl::optional<net::SchemefulSite> FindOwner(
+ const net::SchemefulSite& site) const;
+
private:
+ // Returns whether the `site` is same-party with the `party_context`, and
+ // `top_frame_site` (if it is not nullptr). That is, is the `site`'s owner the
+ // same as the owners of every member of `party_context` and of
+ // `top_frame_site`? Note: if `site` is not a member of a First-Party Set
+ // (with more than one member), then this returns false. If `top_frame_site`
+ // is nullptr, then it is ignored.
+ bool IsContextSamePartyWithSite(
+ const net::SchemefulSite& site,
+ const net::SchemefulSite* top_frame_site,
+ const std::set<net::SchemefulSite>& party_context,
+ bool infer_singleton_sets) const;
+
+ // Parses the contents of `raw_sets` as a collection of First-Party Set
+ // declarations, and assigns to `sets_`.
+ void OnReadSetsFile(const std::string& raw_sets);
+
// Returns `site`'s owner (optionally inferring a singleton set if necessary),
// or `nullopt` if `site` has no owner. Must not return `nullopt` if
// `infer_singleton_sets` is true.
@@ -115,7 +137,8 @@ class FirstPartySets {
// 1) were in `old_sets` but are no longer in `sets_`, i.e. leave the FPSs;
// or, 2) mapped to a different owner site.
base::flat_set<net::SchemefulSite> ComputeSetsDiff(
- const base::flat_map<net::SchemefulSite, net::SchemefulSite>& old_sets);
+ const base::flat_map<net::SchemefulSite, net::SchemefulSite>& old_sets)
+ const;
// Checks the required inputs have been received, and if so, computes the diff
// between the `sets_` and the parsed `raw_persisted_sets_`, and clears the
@@ -127,26 +150,37 @@ class FirstPartySets {
// Represents the mapping of site -> site, where keys are members of sets, and
// values are owners of the sets. Owners are explicitly represented as members
// of the set.
- base::flat_map<net::SchemefulSite, net::SchemefulSite> sets_;
+ base::flat_map<net::SchemefulSite, net::SchemefulSite> sets_
+ GUARDED_BY_CONTEXT(sequence_checker_);
absl::optional<
std::pair<net::SchemefulSite, base::flat_set<net::SchemefulSite>>>
- manually_specified_set_;
-
- std::string raw_persisted_sets_;
+ manually_specified_set_ GUARDED_BY_CONTEXT(sequence_checker_);
- bool persisted_sets_ready_ = false;
- bool component_sets_ready_ = false;
- bool manual_sets_ready_ = false;
+ std::string raw_persisted_sets_ GUARDED_BY_CONTEXT(sequence_checker_);
+ bool persisted_sets_ready_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+ bool component_sets_ready_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+ bool manual_sets_ready_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
// The callback runs after the site state clearing is completed.
- base::OnceCallback<void(const std::string&)> on_site_data_cleared_;
-
- FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_SitesJoined);
- FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_SitesLeft);
- FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_OwnerChanged);
- FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_OwnerLeft);
- FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate);
- FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_EmptySets);
+ base::OnceCallback<void(const std::string&)> on_site_data_cleared_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<FirstPartySets> weak_factory_{this};
+
+ FRIEND_TEST_ALL_PREFIXES(FirstPartySetsEnabledTest,
+ ComputeSetsDiff_SitesJoined);
+ FRIEND_TEST_ALL_PREFIXES(FirstPartySetsEnabledTest,
+ ComputeSetsDiff_SitesLeft);
+ FRIEND_TEST_ALL_PREFIXES(FirstPartySetsEnabledTest,
+ ComputeSetsDiff_OwnerChanged);
+ FRIEND_TEST_ALL_PREFIXES(FirstPartySetsEnabledTest,
+ ComputeSetsDiff_OwnerLeft);
+ FRIEND_TEST_ALL_PREFIXES(FirstPartySetsEnabledTest,
+ ComputeSetsDiff_OwnerMemberRotate);
+ FRIEND_TEST_ALL_PREFIXES(FirstPartySetsEnabledTest,
+ ComputeSetsDiff_EmptySets);
};
} // namespace network
diff --git a/chromium/services/network/first_party_sets/first_party_sets_unittest.cc b/chromium/services/network/first_party_sets/first_party_sets_unittest.cc
index 52eb8e8a3d8..5e19e77ac81 100644
--- a/chromium/services/network/first_party_sets/first_party_sets_unittest.cc
+++ b/chromium/services/network/first_party_sets/first_party_sets_unittest.cc
@@ -4,13 +4,17 @@
#include "services/network/first_party_sets/first_party_sets.h"
-#include <initializer_list>
-
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "net/base/features.h"
#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/same_party_context.h"
+#include "services/network/first_party_sets/first_party_set_parser.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,12 +22,12 @@
#include "url/gurl.h"
using ::testing::IsEmpty;
-using ::testing::Not;
using ::testing::Pair;
-using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
using ::testing::Value;
+using Type = net::SamePartyContext::Type;
+
// Some of these tests overlap with FirstPartySetParser unittests, but
// overlapping test coverage isn't the worst thing.
@@ -34,15 +38,155 @@ MATCHER_P(SerializesTo, want, "") {
return testing::ExplainMatchResult(testing::Eq(want), got, result_listener);
}
-TEST(FirstPartySets, Sets_IsEmpty) {
+class FirstPartySetsTest : public ::testing::Test {
+ public:
+ explicit FirstPartySetsTest(bool enabled) {
+ if (enabled) {
+ feature_list_.InitAndEnableFeature(net::features::kFirstPartySets);
+ } else {
+ feature_list_.InitAndDisableFeature(net::features::kFirstPartySets);
+ }
+ }
+
+ void SetComponentSetsAndWait(base::StringPiece content) {
+ SetComponentSetsAndWait(sets_, content);
+ }
+
+ void SetComponentSetsAndWait(FirstPartySets& sets,
+ base::StringPiece content) {
+ base::ScopedTempDir temp_dir;
+ CHECK(temp_dir.CreateUniqueTempDir());
+ base::FilePath path =
+ temp_dir.GetPath().Append(FILE_PATH_LITERAL("sets_file.json"));
+ CHECK(base::WriteFile(path, content));
+
+ sets.ParseAndSet(
+ base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ));
+ env_.RunUntilIdle();
+ }
+
+ FirstPartySets& sets() { return sets_; }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+ base::test::TaskEnvironment env_;
+ FirstPartySets sets_;
+};
+
+class FirstPartySetsDisabledTest : public FirstPartySetsTest {
+ public:
+ FirstPartySetsDisabledTest() : FirstPartySetsTest(false) {}
+};
+
+TEST_F(FirstPartySetsDisabledTest, ParseAndSet_IgnoresValid) {
+ const std::string input =
+ R"([{
+ "owner": "https://example.test",
+ "members": ["https://aaaa.test"]
+ }])";
+ ASSERT_TRUE(base::JSONReader::Read(input));
+
+ SetComponentSetsAndWait(input);
+ EXPECT_THAT(sets().Sets(), IsEmpty());
+}
+
+TEST_F(FirstPartySetsDisabledTest, ParseV2Format_IgnoresValid) {
+ const std::string input =
+ "{\"owner\": \"https://example.test\",\"members\": "
+ "[\"https://aaaa.test\"]}";
+
+ SetComponentSetsAndWait(input);
+ EXPECT_THAT(sets().Sets(), IsEmpty());
+}
+
+TEST_F(FirstPartySetsDisabledTest, SetsManuallySpecified_IgnoresValid) {
+ FirstPartySets sets;
+ sets.SetManuallySpecifiedSet("https://example.test,https://member.test");
+ EXPECT_THAT(sets.Sets(), IsEmpty());
+}
+
+TEST_F(FirstPartySetsDisabledTest, IsInNontrivialFirstPartySet) {
+ const std::string input =
+ R"([{
+ "owner": "https://example.test",
+ "members": ["https://aaaa.test"]
+ }])";
+ ASSERT_TRUE(base::JSONReader::Read(input));
+
+ SetComponentSetsAndWait(input);
+
+ // IsInNontrivialFirstPartySet queries should return false, regardless of what
+ // data has been passed to the instance.
+ EXPECT_FALSE(sets().IsInNontrivialFirstPartySet(
+ net::SchemefulSite(GURL("https://example.test"))));
+ EXPECT_FALSE(sets().IsInNontrivialFirstPartySet(
+ net::SchemefulSite(GURL("https://aaaa.test"))));
+ EXPECT_FALSE(sets().IsInNontrivialFirstPartySet(
+ net::SchemefulSite(GURL("https://bbbb.test"))));
+}
+
+TEST_F(FirstPartySetsDisabledTest, ComputeContext_InfersSingletons) {
+ net::SchemefulSite member(GURL("https://member1.test"));
+ net::SchemefulSite example(GURL("https://example.test"));
+ net::SchemefulSite wss_member(GURL("wss://member1.test"));
+
+ FirstPartySets sets;
+
+ // Works if the site is provided with WSS scheme instead of HTTPS.
+ EXPECT_THAT(sets.ComputeContext(wss_member, &member, {member, example}),
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
+
+ EXPECT_THAT(sets.ComputeContext(example, &member, {member}),
+ net::SamePartyContext(Type::kCrossParty));
+ EXPECT_THAT(sets.ComputeContext(member, &example, {member}),
+ net::SamePartyContext(Type::kCrossParty));
+
+ // Top&resource differs from Ancestors.
+ EXPECT_THAT(sets.ComputeContext(member, &member, {example}),
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
+
+ // Metrics values infer singleton sets when appropriate.
+ EXPECT_THAT(sets.ComputeContext(member, &member, {member}),
+ net::SamePartyContext(Type::kCrossParty, Type::kSameParty,
+ Type::kSameParty));
+ EXPECT_THAT(sets.ComputeContext(member, &example, {member}),
+ net::SamePartyContext(Type::kCrossParty));
+ EXPECT_THAT(sets.ComputeContext(example, &member, {member}),
+ net::SamePartyContext(Type::kCrossParty));
+ EXPECT_THAT(sets.ComputeContext(member, &member, {example}),
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
+
+ EXPECT_THAT(sets.ComputeContext(member, &member, {member, example}),
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
+}
+
+TEST_F(FirstPartySetsDisabledTest, FindOwner) {
+ sets().SetManuallySpecifiedSet("https://example.test,https://member.test");
+ EXPECT_FALSE(
+ sets().FindOwner(net::SchemefulSite(GURL("https://example.test"))));
+ EXPECT_FALSE(
+ sets().FindOwner(net::SchemefulSite(GURL("https://member.test"))));
+}
+
+class FirstPartySetsEnabledTest : public FirstPartySetsTest {
+ public:
+ FirstPartySetsEnabledTest() : FirstPartySetsTest(true) {}
+};
+
+TEST_F(FirstPartySetsEnabledTest, Sets_IsEmpty) {
EXPECT_THAT(FirstPartySets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, ParsesJSON) {
- EXPECT_THAT(FirstPartySets().ParseAndSet("[]"), Pointee(IsEmpty()));
+TEST_F(FirstPartySetsEnabledTest, ParsesJSON) {
+ SetComponentSetsAndWait("[]");
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, AcceptsMinimal) {
+TEST_F(FirstPartySetsEnabledTest, AcceptsMinimal) {
const std::string input =
R"([{
"owner": "https://example.test",
@@ -50,15 +194,29 @@ TEST(FirstPartySets, AcceptsMinimal) {
}])";
ASSERT_TRUE(base::JSONReader::Read(input));
- EXPECT_THAT(FirstPartySets().ParseAndSet(input),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://aaaa.test"),
- SerializesTo("https://example.test")))));
+ SetComponentSetsAndWait(input);
+
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://aaaa.test")))));
}
-TEST(FirstPartySets, AcceptsMultipleSets) {
+TEST_F(FirstPartySetsEnabledTest, V2_AcceptsMinimal) {
+ const std::string input =
+ "{\"owner\": \"https://example.test\",\"members\": "
+ "[\"https://aaaa.test\",],}";
+
+ SetComponentSetsAndWait(input);
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://aaaa.test")))));
+}
+
+TEST_F(FirstPartySetsEnabledTest, AcceptsMultipleSets) {
const std::string input = R"(
[
{
@@ -72,20 +230,39 @@ TEST(FirstPartySets, AcceptsMultipleSets) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
+
+ EXPECT_THAT(
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"))),
+ Pair(SerializesTo("https://foo.test"),
+ UnorderedElementsAre(SerializesTo("https://foo.test"),
+ SerializesTo("https://member2.test")))));
+}
+
+TEST_F(FirstPartySetsEnabledTest, V2_AcceptsMultipleSets) {
+ const std::string input =
+ "{\"owner\": \"https://example.test\",\"members\": "
+ "[\"https://member1.test\"]}\n"
+ "{\"owner\": \"https://foo.test\",\"members\": "
+ "[\"https://member2.test\"]}";
+ SetComponentSetsAndWait(input);
EXPECT_THAT(
- FirstPartySets().ParseAndSet(input),
- Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://foo.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://foo.test")))));
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"))),
+ Pair(SerializesTo("https://foo.test"),
+ UnorderedElementsAre(SerializesTo("https://foo.test"),
+ SerializesTo("https://member2.test")))));
}
-TEST(FirstPartySets, ClearsPreloadedOnError) {
+TEST_F(FirstPartySetsEnabledTest, ClearsPreloadedOnError) {
const std::string input = R"(
[
{
@@ -99,23 +276,24 @@ TEST(FirstPartySets, ClearsPreloadedOnError) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
EXPECT_THAT(
- sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://foo.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://foo.test")))));
-
- EXPECT_THAT(sets.ParseAndSet("{}"), Pointee(IsEmpty()));
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"))),
+ Pair(SerializesTo("https://foo.test"),
+ UnorderedElementsAre(SerializesTo("https://foo.test"),
+ SerializesTo("https://member2.test")))));
+
+ SetComponentSetsAndWait("{}");
+
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, OwnerIsOnlyMember) {
+TEST_F(FirstPartySetsEnabledTest, OwnerIsOnlyMember) {
const std::string input = R"(
[
{
@@ -129,11 +307,12 @@ TEST(FirstPartySets, OwnerIsOnlyMember) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- EXPECT_THAT(FirstPartySets().ParseAndSet(input), Pointee(IsEmpty()));
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, OwnerIsMember) {
+TEST_F(FirstPartySetsEnabledTest, OwnerIsMember) {
const std::string input = R"(
[
{
@@ -147,11 +326,12 @@ TEST(FirstPartySets, OwnerIsMember) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- EXPECT_THAT(FirstPartySets().ParseAndSet(input), Pointee(IsEmpty()));
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, RepeatedMember) {
+TEST_F(FirstPartySetsEnabledTest, RepeatedMember) {
const std::string input = R"(
[
{
@@ -169,45 +349,42 @@ TEST(FirstPartySets, RepeatedMember) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- EXPECT_THAT(FirstPartySets().ParseAndSet(input), Pointee(IsEmpty()));
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Invalid_TooSmall) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test");
- EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Invalid_TooSmall) {
+ sets().SetManuallySpecifiedSet("https://example.test");
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Invalid_NotOrigins) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test,member1");
- EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Invalid_NotOrigins) {
+ sets().SetManuallySpecifiedSet("https://example.test,member1");
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Invalid_NotHTTPS) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test,http://member1.test");
- EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Invalid_NotHTTPS) {
+ sets().SetManuallySpecifiedSet("https://example.test,http://member1.test");
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Invalid_RegisteredDomain_Owner) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_Invalid_RegisteredDomain_Owner) {
+ sets().SetManuallySpecifiedSet(
"https://www.example.test..,https://www.member.test");
- EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Invalid_RegisteredDomain_Member) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_Invalid_RegisteredDomain_Member) {
+ sets().SetManuallySpecifiedSet(
"https://www.example.test,https://www.member.test..");
- EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Valid_EmptyValue) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("");
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Valid_EmptyValue) {
+ sets().SetManuallySpecifiedSet("");
// Set non-empty existing sets to distinguish the failure case from the no-op
// case when processing the manually-specified sets.
@@ -220,89 +397,78 @@ TEST(FirstPartySets, SetsManuallySpecified_Valid_EmptyValue) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(existing_sets));
+ SetComponentSetsAndWait(existing_sets);
- EXPECT_THAT(sets.ParseAndSet(existing_sets),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_Valid_SingleMember) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test,https://member.test");
- EXPECT_THAT(sets.ParseAndSet("[]"),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member.test"),
- SerializesTo("https://example.test")))));
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Valid_SingleMember) {
+ sets().SetManuallySpecifiedSet("https://example.test,https://member.test");
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member.test")))));
}
-TEST(FirstPartySets,
- SetsManuallySpecified_Valid_SingleMember_RegisteredDomain) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_Valid_SingleMember_RegisteredDomain) {
+ sets().SetManuallySpecifiedSet(
"https://www.example.test,https://www.member.test");
- EXPECT_THAT(sets.ParseAndSet("[]"),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_Valid_MultipleMembers) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Valid_MultipleMembers) {
+ sets().SetManuallySpecifiedSet(
"https://example.test,https://member1.test,https://member2.test");
- EXPECT_THAT(sets.ParseAndSet("[]"),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_Valid_OwnerIsOnlyMember) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test,https://example.test");
- EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_Valid_OwnerIsOnlyMember) {
+ sets().SetManuallySpecifiedSet("https://example.test,https://example.test");
+ EXPECT_THAT(sets().Sets(), IsEmpty());
}
-TEST(FirstPartySets, SetsManuallySpecified_Valid_OwnerIsMember) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Valid_OwnerIsMember) {
+ sets().SetManuallySpecifiedSet(
"https://example.test,https://example.test,https://member1.test");
- EXPECT_THAT(sets.ParseAndSet("[]"),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_Valid_RepeatedMember) {
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+TEST_F(FirstPartySetsEnabledTest, SetsManuallySpecified_Valid_RepeatedMember) {
+ sets().SetManuallySpecifiedSet(
R"(https://example.test,
https://member1.test,
https://member2.test,
https://member1.test)");
- EXPECT_THAT(sets.ParseAndSet("[]"),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesOwnerOwner) {
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_DeduplicatesOwnerOwner) {
const std::string input = R"(
[
{
@@ -316,25 +482,24 @@ TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesOwnerOwner) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+ sets().SetManuallySpecifiedSet(
"https://example.test,https://member1.test,https://member2.test");
EXPECT_THAT(
- sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://bar.test"),
- SerializesTo("https://bar.test")),
- Pair(SerializesTo("https://member4.test"),
- SerializesTo("https://bar.test")))));
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test"))),
+ Pair(SerializesTo("https://bar.test"),
+ UnorderedElementsAre(SerializesTo("https://bar.test"),
+ SerializesTo("https://member4.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesOwnerMember) {
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_DeduplicatesOwnerMember) {
const std::string input = R"(
[
{
@@ -348,25 +513,24 @@ TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesOwnerMember) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+ sets().SetManuallySpecifiedSet(
"https://example.test,https://member1.test,https://member3.test");
- EXPECT_THAT(sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://bar.test"),
- SerializesTo("https://bar.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://bar.test")),
- Pair(SerializesTo("https://member3.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member3.test"))),
+ Pair(SerializesTo("https://bar.test"),
+ UnorderedElementsAre(SerializesTo("https://bar.test"),
+ SerializesTo("https://member2.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesMemberOwner) {
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_DeduplicatesMemberOwner) {
const std::string input = R"(
[
{
@@ -380,24 +544,23 @@ TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesMemberOwner) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test,https://member3.test");
- EXPECT_THAT(sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://foo.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member3.test"),
- SerializesTo("https://example.test")))));
+ sets().SetManuallySpecifiedSet("https://example.test,https://member3.test");
+ EXPECT_THAT(
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member3.test"))),
+ Pair(SerializesTo("https://foo.test"),
+ UnorderedElementsAre(SerializesTo("https://foo.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesMemberMember) {
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_DeduplicatesMemberMember) {
const std::string input = R"(
[
{
@@ -411,29 +574,27 @@ TEST(FirstPartySets, SetsManuallySpecified_DeduplicatesMemberMember) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+ sets().SetManuallySpecifiedSet(
"https://example.test,https://member1.test,https://member2.test");
EXPECT_THAT(
- sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://foo.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://member3.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://bar.test"),
- SerializesTo("https://bar.test")),
- Pair(SerializesTo("https://member4.test"),
- SerializesTo("https://bar.test")))));
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test"))),
+ Pair(SerializesTo("https://foo.test"),
+ UnorderedElementsAre(SerializesTo("https://foo.test"),
+ SerializesTo("https://member3.test"))),
+ Pair(SerializesTo("https://bar.test"),
+ UnorderedElementsAre(SerializesTo("https://bar.test"),
+ SerializesTo("https://member4.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_ClearsPreloadedOnError) {
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_ClearsPreloadedOnError) {
const std::string input = R"(
[
{
@@ -443,34 +604,33 @@ TEST(FirstPartySets, SetsManuallySpecified_ClearsPreloadedOnError) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet(
+ sets().SetManuallySpecifiedSet(
"https://example.test,https://member1.test,https://member2.test");
EXPECT_THAT(
- sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://bar.test"),
- SerializesTo("https://bar.test")),
- Pair(SerializesTo("https://member3.test"),
- SerializesTo("https://bar.test")))));
-
- EXPECT_THAT(sets.ParseAndSet("{}"),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://example.test")))));
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test"))),
+ Pair(SerializesTo("https://bar.test"),
+ UnorderedElementsAre(SerializesTo("https://bar.test"),
+ SerializesTo("https://member3.test")))));
+
+ SetComponentSetsAndWait("{}");
+
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member2.test")))));
}
-TEST(FirstPartySets, SetsManuallySpecified_PrunesInducedSingletons) {
+TEST_F(FirstPartySetsEnabledTest,
+ SetsManuallySpecified_PrunesInducedSingletons) {
const std::string input = R"(
[
{
@@ -480,21 +640,20 @@ TEST(FirstPartySets, SetsManuallySpecified_PrunesInducedSingletons) {
]
)";
ASSERT_TRUE(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
- FirstPartySets sets;
- sets.SetManuallySpecifiedSet("https://example.test,https://member1.test");
+ sets().SetManuallySpecifiedSet("https://example.test,https://member1.test");
// If we just erased entries that overlapped with the manually-supplied set,
// https://foo.test would be left as a singleton set. But since we disallow
// singleton sets, we ensure that such cases are caught and removed.
- EXPECT_THAT(sets.ParseAndSet(input),
- Pointee(UnorderedElementsAre(
- Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")))));
+ EXPECT_THAT(sets().Sets(),
+ UnorderedElementsAre(Pair(
+ SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test")))));
}
-TEST(FirstPartySets, ComputeSetsDiff_SitesJoined) {
+TEST_F(FirstPartySetsEnabledTest, ComputeSetsDiff_SitesJoined) {
auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
{net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://example.test"))},
@@ -504,7 +663,7 @@ TEST(FirstPartySets, ComputeSetsDiff_SitesJoined) {
net::SchemefulSite(GURL("https://example.test"))}};
// Consistency check the reviewer-friendly JSON format matches the input.
- ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+ ASSERT_THAT(FirstPartySetParser::ParseSetsFromComponentUpdater(R"(
[
{
"owner": "https://example.test",
@@ -512,10 +671,9 @@ TEST(FirstPartySets, ComputeSetsDiff_SitesJoined) {
}
]
)"),
- Pointee(old_sets));
+ old_sets);
- FirstPartySets sets;
- sets.ParseAndSet(R"(
+ SetComponentSetsAndWait(R"(
[
{
"owner": "https://example.test",
@@ -527,12 +685,13 @@ TEST(FirstPartySets, ComputeSetsDiff_SitesJoined) {
}
]
)");
+
// "https://foo.test" and "https://member2.test" joined FPSs. We don't clear
// site data upon joining, so the computed diff should be empty set.
- EXPECT_THAT(sets.ComputeSetsDiff(old_sets), IsEmpty());
+ EXPECT_THAT(sets().ComputeSetsDiff(old_sets), IsEmpty());
}
-TEST(FirstPartySets, ComputeSetsDiff_SitesLeft) {
+TEST_F(FirstPartySetsEnabledTest, ComputeSetsDiff_SitesLeft) {
auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
{net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://example.test"))},
@@ -546,7 +705,7 @@ TEST(FirstPartySets, ComputeSetsDiff_SitesLeft) {
net::SchemefulSite(GURL("https://foo.test"))}};
// Consistency check the reviewer-friendly JSON format matches the input.
- ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+ ASSERT_THAT(FirstPartySetParser::ParseSetsFromComponentUpdater(R"(
[
{
"owner": "https://example.test",
@@ -558,10 +717,9 @@ TEST(FirstPartySets, ComputeSetsDiff_SitesLeft) {
},
]
)"),
- Pointee(old_sets));
+ old_sets);
- FirstPartySets sets;
- sets.ParseAndSet(R"(
+ SetComponentSetsAndWait(R"(
[
{
"owner": "https://example.test",
@@ -571,13 +729,13 @@ TEST(FirstPartySets, ComputeSetsDiff_SitesLeft) {
)");
// Expected diff: "https://foo.test", "https://member2.test" and
// "https://member3.test" left FPSs.
- EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+ EXPECT_THAT(sets().ComputeSetsDiff(old_sets),
UnorderedElementsAre(SerializesTo("https://foo.test"),
SerializesTo("https://member2.test"),
SerializesTo("https://member3.test")));
}
-TEST(FirstPartySets, ComputeSetsDiff_OwnerChanged) {
+TEST_F(FirstPartySetsEnabledTest, ComputeSetsDiff_OwnerChanged) {
auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
{net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://example.test"))},
@@ -591,7 +749,7 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerChanged) {
net::SchemefulSite(GURL("https://foo.test"))}};
// Consistency check the reviewer-friendly JSON format matches the input.
- ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+ ASSERT_THAT(FirstPartySetParser::ParseSetsFromComponentUpdater(R"(
[
{
"owner": "https://example.test",
@@ -603,10 +761,9 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerChanged) {
},
]
)"),
- Pointee(old_sets));
+ old_sets);
- FirstPartySets sets;
- sets.ParseAndSet(R"(
+ SetComponentSetsAndWait(R"(
[
{
"owner": "https://example.test",
@@ -619,11 +776,11 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerChanged) {
]
)");
// Expected diff: "https://member3.test" changed owner.
- EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+ EXPECT_THAT(sets().ComputeSetsDiff(old_sets),
UnorderedElementsAre(SerializesTo("https://member3.test")));
}
-TEST(FirstPartySets, ComputeSetsDiff_OwnerLeft) {
+TEST_F(FirstPartySetsEnabledTest, ComputeSetsDiff_OwnerLeft) {
auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
{net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://example.test"))},
@@ -633,7 +790,7 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerLeft) {
net::SchemefulSite(GURL("https://example.test"))}};
// Consistency check the reviewer-friendly JSON format matches the input.
- ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+ ASSERT_THAT(FirstPartySetParser::ParseSetsFromComponentUpdater(R"(
[
{
"owner": "https://example.test",
@@ -641,10 +798,9 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerLeft) {
}
]
)"),
- Pointee(old_sets));
+ old_sets);
- FirstPartySets sets;
- sets.ParseAndSet(R"(
+ SetComponentSetsAndWait(R"(
[
{
"owner": "https://foo.test",
@@ -657,13 +813,13 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerLeft) {
// It would be valid to only have example.test in the diff, but our logic
// isn't sophisticated enough yet to know that foo.test and bar.test don't
// need to be included in the result.
- EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+ EXPECT_THAT(sets().ComputeSetsDiff(old_sets),
UnorderedElementsAre(SerializesTo("https://example.test"),
SerializesTo("https://foo.test"),
SerializesTo("https://bar.test")));
}
-TEST(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate) {
+TEST_F(FirstPartySetsEnabledTest, ComputeSetsDiff_OwnerMemberRotate) {
auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
{net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://example.test"))},
@@ -671,7 +827,7 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate) {
net::SchemefulSite(GURL("https://example.test"))}};
// Consistency check the reviewer-friendly JSON format matches the input.
- ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+ ASSERT_THAT(FirstPartySetParser::ParseSetsFromComponentUpdater(R"(
[
{
"owner": "https://example.test",
@@ -679,10 +835,9 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate) {
}
]
)"),
- Pointee(old_sets));
+ old_sets);
- FirstPartySets sets;
- sets.ParseAndSet(R"(
+ SetComponentSetsAndWait(R"(
[
{
"owner": "https://foo.test",
@@ -693,15 +848,14 @@ TEST(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate) {
// Expected diff: "https://example.test" and "https://foo.test" changed owner.
// It would be valid to not include example.test and foo.test in the result,
// but our logic isn't sophisticated enough yet to know that.ß
- EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+ EXPECT_THAT(sets().ComputeSetsDiff(old_sets),
UnorderedElementsAre(SerializesTo("https://example.test"),
SerializesTo("https://foo.test")));
}
-TEST(FirstPartySets, ComputeSetsDiff_EmptySets) {
+TEST_F(FirstPartySetsEnabledTest, ComputeSetsDiff_EmptySets) {
// Empty old_sets.
- FirstPartySets sets;
- sets.ParseAndSet(R"(
+ SetComponentSetsAndWait(R"(
[
{
"owner": "https://example.test",
@@ -709,7 +863,7 @@ TEST(FirstPartySets, ComputeSetsDiff_EmptySets) {
},
]
)");
- EXPECT_THAT(sets.ComputeSetsDiff({}), IsEmpty());
+ EXPECT_THAT(sets().ComputeSetsDiff({}), IsEmpty());
// Empty current sets.
auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
@@ -718,7 +872,7 @@ TEST(FirstPartySets, ComputeSetsDiff_EmptySets) {
{net::SchemefulSite(GURL("https://member1.test")),
net::SchemefulSite(GURL("https://example.test"))}};
// Consistency check the reviewer-friendly JSON format matches the input.
- ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+ ASSERT_THAT(FirstPartySetParser::ParseSetsFromComponentUpdater(R"(
[
{
"owner": "https://example.test",
@@ -726,13 +880,13 @@ TEST(FirstPartySets, ComputeSetsDiff_EmptySets) {
}
]
)"),
- Pointee(old_sets));
+ old_sets);
EXPECT_THAT(FirstPartySets().ComputeSetsDiff(old_sets),
UnorderedElementsAre(SerializesTo("https://example.test"),
SerializesTo("https://member1.test")));
}
-TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_NotReady) {
+TEST_F(FirstPartySetsEnabledTest, ClearSiteDataOnChangedSetsIfReady_NotReady) {
int callback_calls = 0;
auto callback = base::BindLambdaForTesting(
[&](const std::string& got) { callback_calls++; });
@@ -749,7 +903,7 @@ TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_NotReady) {
{
FirstPartySets sets;
callback_calls = 0;
- sets.ParseAndSet("[]");
+ SetComponentSetsAndWait(sets, "[]");
sets.SetPersistedSets("{}");
sets.SetOnSiteDataCleared(callback);
EXPECT_EQ(callback_calls, 0);
@@ -758,7 +912,7 @@ TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_NotReady) {
{
FirstPartySets sets;
callback_calls = 0;
- sets.ParseAndSet("[]");
+ SetComponentSetsAndWait(sets, "[]");
sets.SetManuallySpecifiedSet("");
sets.SetOnSiteDataCleared(callback);
EXPECT_EQ(callback_calls, 0);
@@ -767,7 +921,7 @@ TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_NotReady) {
{
FirstPartySets sets;
callback_calls = 0;
- sets.ParseAndSet("[]");
+ SetComponentSetsAndWait(sets, "[]");
sets.SetManuallySpecifiedSet("");
sets.SetPersistedSets("{}");
EXPECT_EQ(callback_calls, 0);
@@ -776,21 +930,20 @@ TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_NotReady) {
// The callback only runs when `old_sets` is generated and `sets` has merged the
// inputs from Component Updater and command line flag.
-TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_Ready) {
- FirstPartySets sets;
+TEST_F(FirstPartySetsEnabledTest, ClearSiteDataOnChangedSetsIfReady_Ready) {
int callback_calls = 0;
- sets.ParseAndSet(R"([
+ SetComponentSetsAndWait(R"([
{
"owner": "https://example.test",
"members": ["https://member1.test"]
}
])");
- sets.SetManuallySpecifiedSet("https://example2.test,https://member2.test");
- sets.SetPersistedSets(
+ sets().SetManuallySpecifiedSet("https://example2.test,https://member2.test");
+ sets().SetPersistedSets(
R"({"https://example.test":"https://example.test",
"https://member1.test":"https://example.test"})");
- sets.SetOnSiteDataCleared(base::BindLambdaForTesting([&](const std::string&
- got) {
+ sets().SetOnSiteDataCleared(base::BindLambdaForTesting([&](const std::string&
+ got) {
EXPECT_EQ(
got,
R"({"https://member1.test":"https://example.test","https://member2.test":"https://example2.test"})");
@@ -799,9 +952,9 @@ TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_Ready) {
EXPECT_EQ(callback_calls, 1);
}
-class FirstPartySetsTest : public ::testing::Test {
+class PopulatedFirstPartySetsTest : public FirstPartySetsEnabledTest {
public:
- FirstPartySetsTest() {
+ PopulatedFirstPartySetsTest() {
const std::string input = R"(
[
{
@@ -815,52 +968,52 @@ class FirstPartySetsTest : public ::testing::Test {
]
)";
CHECK(base::JSONReader::Read(input));
+ SetComponentSetsAndWait(input);
CHECK(Value(
- sets().ParseAndSet(input),
- Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member1.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://member3.test"),
- SerializesTo("https://example.test")),
- Pair(SerializesTo("https://foo.test"),
- SerializesTo("https://foo.test")),
- Pair(SerializesTo("https://member2.test"),
- SerializesTo("https://foo.test"))))));
+ sets().Sets(),
+ UnorderedElementsAre(
+ Pair(SerializesTo("https://example.test"),
+ UnorderedElementsAre(SerializesTo("https://example.test"),
+ SerializesTo("https://member1.test"),
+ SerializesTo("https://member3.test"))),
+ Pair(SerializesTo("https://foo.test"),
+ UnorderedElementsAre(SerializesTo("https://foo.test"),
+ SerializesTo("https://member2.test"))))));
}
-
- FirstPartySets& sets() { return sets_; }
-
- protected:
- FirstPartySets sets_;
};
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_EmptyContext) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_EmptyContext) {
net::SchemefulSite example_site(GURL("https://example.test"));
net::SchemefulSite nonmember(GURL("https://nonmember.test"));
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, {},
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, {})
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- example_site, top_frame, {}, false /* infer_singleton_sets */));
+ EXPECT_EQ(sets().ComputeContext(example_site, top_frame, {}).context_type(),
+ Type::kSameParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, {},
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, {})
+ .context_type(),
+ Type::kCrossParty);
}
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- example_site, &nonmember, {}, false /* infer_singleton_sets */));
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- nonmember, &example_site, {}, false /* infer_singleton_sets */));
+ EXPECT_EQ(sets().ComputeContext(example_site, &nonmember, {}).context_type(),
+ Type::kCrossParty);
+ EXPECT_EQ(sets().ComputeContext(nonmember, &example_site, {}).context_type(),
+ Type::kCrossParty);
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsNonmember) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_ContextIsNonmember) {
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://nonmember.test")),
});
@@ -869,33 +1022,50 @@ TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsNonmember) {
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsOwner) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_ContextIsOwner) {
std::set<net::SchemefulSite> context(
{net::SchemefulSite(GURL("https://example.test"))});
@@ -903,33 +1073,50 @@ TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsOwner) {
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsMember) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_ContextIsMember) {
std::set<net::SchemefulSite> context(
{net::SchemefulSite(GURL("https://member1.test"))});
@@ -937,37 +1124,57 @@ TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsMember) {
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsOwnerAndMember) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_ContextIsOwnerAndMember) {
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
@@ -977,37 +1184,57 @@ TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextIsOwnerAndMember) {
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member3.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member3.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kSameParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextMixesParties) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_ContextMixesParties) {
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
@@ -1018,34 +1245,51 @@ TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextMixesParties) {
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest,
- IsContextSamePartyWithSite_ContextMixesMembersAndNonmembers) {
+TEST_F(PopulatedFirstPartySetsTest,
+ ComputeContext_ContextMixesMembersAndNonmembers) {
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
@@ -1056,33 +1300,50 @@ TEST_F(FirstPartySetsTest,
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextMixesSchemes) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext_ContextMixesSchemes) {
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
@@ -1093,76 +1354,50 @@ TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_ContextMixesSchemes) {
for (const net::SchemefulSite* top_frame :
std::initializer_list<net::SchemefulSite*>{&example_site, nullptr}) {
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
-
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("http://example.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member1.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("http://example.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://foo.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member1.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
+
+ EXPECT_EQ(sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://foo.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://member2.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://member2.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context,
- false /* infer_singleton_sets */));
+ EXPECT_EQ(
+ sets()
+ .ComputeContext(net::SchemefulSite(GURL("https://nonmember.test")),
+ top_frame, context)
+ .context_type(),
+ Type::kCrossParty);
}
}
-TEST_F(FirstPartySetsTest, IsContextSamePartyWithSite_InfersSingletonSets) {
- std::set<net::SchemefulSite> context({
- net::SchemefulSite(GURL("https://nonmember.test")),
- });
- net::SchemefulSite nonmember(GURL("https://nonmember.test"));
- net::SchemefulSite nonmember2(GURL("https://nonmember2.test"));
- net::SchemefulSite member(GURL("https://member1.test"));
-
- EXPECT_TRUE(sets().IsContextSamePartyWithSite(nonmember, nullptr, {}, true));
-
- EXPECT_TRUE(
- sets().IsContextSamePartyWithSite(nonmember, &nonmember, {}, true));
-
- EXPECT_TRUE(
- sets().IsContextSamePartyWithSite(nonmember, nullptr, context, true));
-
- EXPECT_TRUE(
- sets().IsContextSamePartyWithSite(nonmember, &nonmember, context, true));
-
- // Context mismatches.
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(nonmember, &nonmember,
- {nonmember2}, true));
-
- // Context mismatches (but is a member of some set).
- EXPECT_FALSE(
- sets().IsContextSamePartyWithSite(nonmember, &nonmember, {member}, true));
-
- // Top frame mismatches.
- EXPECT_FALSE(
- sets().IsContextSamePartyWithSite(nonmember, &member, {nonmember}, true));
-
- // Request URL mismatches.
- EXPECT_FALSE(sets().IsContextSamePartyWithSite(
- net::SchemefulSite(GURL("https://nonmember1.test")), &nonmember2,
- {nonmember2}, true));
-
- // Request URL mismatches (but is a member of some set).
- EXPECT_FALSE(
- sets().IsContextSamePartyWithSite(member, &nonmember, {nonmember}, true));
-}
-
-TEST_F(FirstPartySetsTest, ComputeContext) {
- using SamePartyContextType = net::SamePartyContext::Type;
-
+TEST_F(PopulatedFirstPartySetsTest, ComputeContext) {
net::SchemefulSite nonmember(GURL("https://nonmember.test"));
net::SchemefulSite nonmember1(GURL("https://nonmember1.test"));
net::SchemefulSite member(GURL("https://member1.test"));
@@ -1172,59 +1407,54 @@ TEST_F(FirstPartySetsTest, ComputeContext) {
// Works as usual for sites that are in First-Party sets.
EXPECT_THAT(sets().ComputeContext(member, &member, {member}),
- net::SamePartyContext(SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(owner, &member, {member}),
- net::SamePartyContext(SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(member, &owner, {member}),
- net::SamePartyContext(SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(member, &member, {owner}),
- net::SamePartyContext(SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(member, &member, {member, owner}),
- net::SamePartyContext(SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kSameParty));
// Works if the site is provided with WSS scheme instead of HTTPS.
EXPECT_THAT(sets().ComputeContext(wss_member, &member, {member, owner}),
- net::SamePartyContext(SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(nonmember, &member, {member}),
- net::SamePartyContext(SamePartyContextType::kCrossParty));
+ net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(sets().ComputeContext(member, &nonmember, {member}),
- net::SamePartyContext(SamePartyContextType::kCrossParty));
+ net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(
sets().ComputeContext(wss_nonmember, &wss_member, {member, owner}),
- net::SamePartyContext(SamePartyContextType::kCrossParty));
+ net::SamePartyContext(Type::kCrossParty));
// Top&resource differs from Ancestors.
EXPECT_THAT(sets().ComputeContext(member, &member, {nonmember}),
- net::SamePartyContext(SamePartyContextType::kCrossParty,
- SamePartyContextType::kCrossParty,
- SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
// Metrics values infer singleton sets when appropriate.
EXPECT_THAT(sets().ComputeContext(nonmember, &nonmember, {nonmember}),
- net::SamePartyContext(SamePartyContextType::kCrossParty,
- SamePartyContextType::kSameParty,
- SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kCrossParty, Type::kSameParty,
+ Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(nonmember, &nonmember1, {nonmember}),
- net::SamePartyContext(SamePartyContextType::kCrossParty));
+ net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(sets().ComputeContext(nonmember1, &nonmember, {nonmember}),
- net::SamePartyContext(SamePartyContextType::kCrossParty));
+ net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(sets().ComputeContext(nonmember, &nonmember, {nonmember1}),
- net::SamePartyContext(SamePartyContextType::kCrossParty,
- SamePartyContextType::kCrossParty,
- SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(member, &member, {member, nonmember}),
- net::SamePartyContext(SamePartyContextType::kCrossParty,
- SamePartyContextType::kCrossParty,
- SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
EXPECT_THAT(sets().ComputeContext(nonmember, &nonmember, {member, nonmember}),
- net::SamePartyContext(SamePartyContextType::kCrossParty,
- SamePartyContextType::kCrossParty,
- SamePartyContextType::kSameParty));
+ net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
+ Type::kSameParty));
}
-TEST_F(FirstPartySetsTest, IsInNontrivialFirstPartySet) {
+TEST_F(PopulatedFirstPartySetsTest, IsInNontrivialFirstPartySet) {
EXPECT_TRUE(sets().IsInNontrivialFirstPartySet(
net::SchemefulSite(GURL("https://example.test"))));
@@ -1244,7 +1474,36 @@ TEST_F(FirstPartySetsTest, IsInNontrivialFirstPartySet) {
net::SchemefulSite(GURL("https://nonmember.test"))));
}
-TEST_F(FirstPartySetsTest, Sets_NonEmpty) {
+TEST_F(PopulatedFirstPartySetsTest, FindOwner) {
+ const absl::optional<net::SchemefulSite> kSetOwner1 =
+ absl::make_optional(net::SchemefulSite(GURL("https://example.test")));
+ const absl::optional<net::SchemefulSite> kSetOwner2 =
+ absl::make_optional(net::SchemefulSite(GURL("https://foo.test")));
+
+ struct TestCase {
+ const std::string url;
+ const absl::optional<net::SchemefulSite> expected;
+ } test_cases[] = {
+ {"https://example.test", kSetOwner1},
+ // Insecure URL
+ {"http://example.test", absl::nullopt},
+ // Test member
+ {"https://member1.test", kSetOwner1},
+ {"http://member1.test", absl::nullopt},
+ // Test another disjoint set
+ {"https://foo.test", kSetOwner2},
+ {"https://member2.test", kSetOwner2},
+ // Test a site not in a set
+ {"https://nonmember.test", absl::nullopt},
+ };
+
+ for (const auto& test_case : test_cases) {
+ EXPECT_EQ(test_case.expected,
+ sets().FindOwner(net::SchemefulSite(GURL(test_case.url))));
+ }
+}
+
+TEST_F(PopulatedFirstPartySetsTest, Sets_NonEmpty) {
EXPECT_THAT(
sets().Sets(),
UnorderedElementsAre(
@@ -1257,7 +1516,7 @@ TEST_F(FirstPartySetsTest, Sets_NonEmpty) {
SerializesTo("https://member2.test")))));
}
-TEST_F(FirstPartySetsTest, ComputeContextType) {
+TEST_F(PopulatedFirstPartySetsTest, ComputeContextType) {
std::set<net::SchemefulSite> homogeneous_context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
diff --git a/chromium/services/network/host_resolver.cc b/chromium/services/network/host_resolver.cc
index dcf4aad988b..1829e9473e2 100644
--- a/chromium/services/network/host_resolver.cc
+++ b/chromium/services/network/host_resolver.cc
@@ -26,7 +26,7 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_ANDROID)
-#include "services/network/public/cpp/features.h"
+#include "net/base/features.h"
#include "services/network/radio_monitor_android.h"
#endif
@@ -128,9 +128,8 @@ void HostResolver::ResolveHost(
return;
#if defined(OS_ANDROID)
- if (base::FeatureList::IsEnabled(features::kRecordRadioWakeupTrigger)) {
- RadioMonitorAndroid::GetInstance().MaybeRecordResolveHost(
- optional_parameters);
+ if (base::FeatureList::IsEnabled(net::features::kRecordRadioWakeupTrigger)) {
+ MaybeRecordResolveHostForWakeupTrigger(optional_parameters);
}
#endif
diff --git a/chromium/services/network/host_resolver.h b/chromium/services/network/host_resolver.h
index 7072d19188e..7d8540c6053 100644
--- a/chromium/services/network/host_resolver.h
+++ b/chromium/services/network/host_resolver.h
@@ -12,7 +12,7 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -86,8 +86,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) HostResolver
std::set<std::unique_ptr<HostResolverMdnsListener>, base::UniquePtrComparator>
listeners_;
- net::HostResolver* const internal_resolver_;
- net::NetLog* const net_log_;
+ const raw_ptr<net::HostResolver> internal_resolver_;
+ const raw_ptr<net::NetLog> net_log_;
base::WeakPtrFactory<HostResolver> weak_factory_{this};
};
diff --git a/chromium/services/network/host_resolver_mdns_listener.h b/chromium/services/network/host_resolver_mdns_listener.h
index 7d393304778..308341bd1c5 100644
--- a/chromium/services/network/host_resolver_mdns_listener.h
+++ b/chromium/services/network/host_resolver_mdns_listener.h
@@ -10,7 +10,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/ip_endpoint.h"
diff --git a/chromium/services/network/host_resolver_unittest.cc b/chromium/services/network/host_resolver_unittest.cc
index f0c822fe1a8..c5c8c529b1d 100644
--- a/chromium/services/network/host_resolver_unittest.cc
+++ b/chromium/services/network/host_resolver_unittest.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/check.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -30,6 +31,7 @@
#include "net/dns/host_resolver_manager.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/dns_protocol.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/dns/public/mdns_listener_update_type.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/log/net_log.h"
@@ -43,7 +45,8 @@
#include "base/android/radio_utils.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "services/network/public/cpp/features.h"
+#include "net/android/radio_activity_tracker.h"
+#include "net/base/features.h"
#include "services/network/radio_monitor_android.h"
#endif
@@ -139,7 +142,7 @@ class TestResolveHostClient : public mojom::ResolveHostClient {
absl::optional<net::AddressList> result_addresses_;
absl::optional<std::vector<std::string>> result_text_;
absl::optional<std::vector<net::HostPortPair>> result_hosts_;
- base::RunLoop* const run_loop_;
+ const raw_ptr<base::RunLoop> run_loop_;
};
class TestMdnsListenClient : public mojom::MdnsListenClient {
@@ -212,6 +215,7 @@ class TestMdnsListenClient : public mojom::MdnsListenClient {
TEST_F(HostResolverTest, Sync) {
auto inner_resolver = std::make_unique<net::MockHostResolver>();
inner_resolver->set_synchronous_mode(true);
+ inner_resolver->rules()->AddRule("example.test", "1.2.3.4");
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -225,14 +229,14 @@ TEST_F(HostResolverTest, Sync) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
resolver.ResolveHost(
- net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
+ net::HostPortPair("example.test", 160), net::NetworkIsolationKey(),
std::move(optional_parameters), std::move(pending_response_client));
run_loop.Run();
EXPECT_EQ(net::OK, response_client.top_level_result_error());
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(response_client.result_addresses().value().endpoints(),
- testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
+ testing::ElementsAre(CreateExpectedEndPoint("1.2.3.4", 160)));
EXPECT_FALSE(response_client.result_text());
EXPECT_FALSE(response_client.result_hosts());
EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
@@ -242,6 +246,7 @@ TEST_F(HostResolverTest, Sync) {
TEST_F(HostResolverTest, Async) {
auto inner_resolver = std::make_unique<net::MockHostResolver>();
inner_resolver->set_synchronous_mode(false);
+ inner_resolver->rules()->AddRule("example.test", "1.2.3.4");
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -255,7 +260,7 @@ TEST_F(HostResolverTest, Async) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
resolver.ResolveHost(
- net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
+ net::HostPortPair("example.test", 160), net::NetworkIsolationKey(),
std::move(optional_parameters), std::move(pending_response_client));
bool control_handle_closed = false;
@@ -266,7 +271,7 @@ TEST_F(HostResolverTest, Async) {
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(response_client.result_addresses().value().endpoints(),
- testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
+ testing::ElementsAre(CreateExpectedEndPoint("1.2.3.4", 160)));
EXPECT_FALSE(response_client.result_text());
EXPECT_FALSE(response_client.result_hosts());
EXPECT_TRUE(control_handle_closed);
@@ -300,6 +305,7 @@ TEST_F(HostResolverTest, DnsQueryType) {
TEST_F(HostResolverTest, InitialPriority) {
auto inner_resolver = std::make_unique<net::MockHostResolver>();
+ inner_resolver->rules()->AddRule("priority.test", "1.2.3.4");
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -312,13 +318,13 @@ TEST_F(HostResolverTest, InitialPriority) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
resolver.ResolveHost(
- net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
+ net::HostPortPair("priority.test", 80), net::NetworkIsolationKey(),
std::move(optional_parameters), std::move(pending_response_client));
run_loop.Run();
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(response_client.result_addresses().value().endpoints(),
- testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 80)));
+ testing::ElementsAre(CreateExpectedEndPoint("1.2.3.4", 80)));
EXPECT_EQ(net::HIGHEST, inner_resolver->last_request_priority());
}
@@ -331,14 +337,26 @@ TEST_F(HostResolverTest, Source) {
constexpr char kDnsResult[] = "168.100.12.23";
constexpr char kMdnsResult[] = "200.1.2.3";
auto inner_resolver = std::make_unique<net::MockHostResolver>();
- inner_resolver->rules_map()[net::HostResolverSource::ANY]->AddRule(
- kDomain, kAnyResult);
- inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->AddRule(
- kDomain, kSystemResult);
- inner_resolver->rules_map()[net::HostResolverSource::DNS]->AddRule(
- kDomain, kDnsResult);
- inner_resolver->rules_map()[net::HostResolverSource::MULTICAST_DNS]->AddRule(
- kDomain, kMdnsResult);
+
+ net::MockHostResolverBase::RuleResolver::RuleKey any_key;
+ any_key.hostname_pattern = kDomain;
+ any_key.query_source = net::HostResolverSource::ANY;
+ inner_resolver->rules()->AddRule(std::move(any_key), kAnyResult);
+
+ net::MockHostResolverBase::RuleResolver::RuleKey system_key;
+ system_key.hostname_pattern = kDomain;
+ system_key.query_source = net::HostResolverSource::SYSTEM;
+ inner_resolver->rules()->AddRule(std::move(system_key), kSystemResult);
+
+ net::MockHostResolverBase::RuleResolver::RuleKey dns_key;
+ dns_key.hostname_pattern = kDomain;
+ dns_key.query_source = net::HostResolverSource::DNS;
+ inner_resolver->rules()->AddRule(std::move(dns_key), kDnsResult);
+
+ net::MockHostResolverBase::RuleResolver::RuleKey mdns_key;
+ mdns_key.hostname_pattern = kDomain;
+ mdns_key.query_source = net::HostResolverSource::MULTICAST_DNS;
+ inner_resolver->rules()->AddRule(std::move(mdns_key), kMdnsResult);
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -411,10 +429,14 @@ TEST_F(HostResolverTest, SeparateCacheBySource) {
constexpr char kAnyResultOriginal[] = "1.2.3.4";
constexpr char kSystemResultOriginal[] = "127.0.0.1";
auto inner_resolver = std::make_unique<net::MockCachingHostResolver>();
- inner_resolver->rules_map()[net::HostResolverSource::ANY]->AddRule(
- kDomain, kAnyResultOriginal);
- inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->AddRule(
- kDomain, kSystemResultOriginal);
+ net::MockHostResolverBase::RuleResolver::RuleKey any_key;
+ any_key.hostname_pattern = kDomain;
+ any_key.query_source = net::HostResolverSource::ANY;
+ inner_resolver->rules()->AddRule(any_key, kAnyResultOriginal);
+ net::MockHostResolverBase::RuleResolver::RuleKey system_key;
+ system_key.hostname_pattern = kDomain;
+ system_key.query_source = net::HostResolverSource::SYSTEM;
+ inner_resolver->rules()->AddRule(system_key, kSystemResultOriginal);
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -439,12 +461,9 @@ TEST_F(HostResolverTest, SeparateCacheBySource) {
// not based on whether they resolve to the old or new value.
constexpr char kAnyResultFresh[] = "111.222.1.1";
constexpr char kSystemResultFresh[] = "111.222.1.2";
- inner_resolver->rules_map()[net::HostResolverSource::ANY]->ClearRules();
- inner_resolver->rules_map()[net::HostResolverSource::ANY]->AddRule(
- kDomain, kAnyResultFresh);
- inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->ClearRules();
- inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->AddRule(
- kDomain, kSystemResultFresh);
+ inner_resolver->rules()->ClearRules();
+ inner_resolver->rules()->AddRule(any_key, kAnyResultFresh);
+ inner_resolver->rules()->AddRule(system_key, kSystemResultFresh);
base::RunLoop cached_run_loop;
mojo::PendingRemote<mojom::ResolveHostClient> pending_cached_client;
@@ -721,6 +740,7 @@ TEST_F(HostResolverTest, LoopbackOnly) {
TEST_F(HostResolverTest, HandlesSecureDnsPolicyParameter) {
auto inner_resolver = std::make_unique<net::MockHostResolver>();
+ inner_resolver->rules()->AddRule("secure.test", "1.2.3.4");
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -734,13 +754,13 @@ TEST_F(HostResolverTest, HandlesSecureDnsPolicyParameter) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
resolver.ResolveHost(
- net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
+ net::HostPortPair("secure.test", 80), net::NetworkIsolationKey(),
std::move(optional_parameters), std::move(pending_response_client));
run_loop.Run();
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(response_client.result_addresses().value().endpoints(),
- testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 80)));
+ testing::ElementsAre(CreateExpectedEndPoint("1.2.3.4", 80)));
EXPECT_EQ(net::SecureDnsPolicy::kDisable,
inner_resolver->last_secure_dns_policy());
}
@@ -810,6 +830,7 @@ TEST_F(HostResolverTest, NetworkIsolationKey) {
const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
auto inner_resolver = std::make_unique<net::MockHostResolver>();
+ inner_resolver->rules()->AddRule("nik.test", "1.2.3.4");
HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
@@ -822,14 +843,14 @@ TEST_F(HostResolverTest, NetworkIsolationKey) {
mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
TestResolveHostClient response_client(&pending_response_client, &run_loop);
- resolver.ResolveHost(net::HostPortPair("localhost", 160),
- kNetworkIsolationKey, std::move(optional_parameters),
+ resolver.ResolveHost(net::HostPortPair("nik.test", 160), kNetworkIsolationKey,
+ std::move(optional_parameters),
std::move(pending_response_client));
run_loop.Run();
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(response_client.result_addresses().value().endpoints(),
- testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
+ testing::ElementsAre(CreateExpectedEndPoint("1.2.3.4", 160)));
EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
EXPECT_EQ(kNetworkIsolationKey,
inner_resolver->last_request_network_isolation_key());
@@ -1559,7 +1580,7 @@ class HostResolverRecordRadioWakeupTest : public HostResolverTest {
public:
HostResolverRecordRadioWakeupTest() {
scoped_feature_list_.InitAndEnableFeature(
- features::kRecordRadioWakeupTrigger);
+ net::features::kRecordRadioWakeupTrigger);
}
private:
@@ -1569,9 +1590,10 @@ class HostResolverRecordRadioWakeupTest : public HostResolverTest {
TEST_F(HostResolverRecordRadioWakeupTest, RecordPreconnect) {
base::HistogramTester histograms;
- RadioMonitorAndroid::GetInstance().OverrideRadioActivityForTesting(
- base::android::RadioDataActivity::kDormant);
- RadioMonitorAndroid::GetInstance().OverrideRadioTypeForTesting(
+ net::android::RadioActivityTracker::GetInstance()
+ .OverrideRadioActivityForTesting(
+ base::android::RadioDataActivity::kDormant);
+ net::android::RadioActivityTracker::GetInstance().OverrideRadioTypeForTesting(
base::android::RadioConnectionType::kCell);
auto inner_resolver = std::make_unique<net::MockHostResolver>();
diff --git a/chromium/services/network/http_auth_cache_copier.h b/chromium/services/network/http_auth_cache_copier.h
index 1961f6aad74..a1e2ba3acea 100644
--- a/chromium/services/network/http_auth_cache_copier.h
+++ b/chromium/services/network/http_auth_cache_copier.h
@@ -8,7 +8,6 @@
#include <map>
#include <memory>
-#include "base/macros.h"
#include "base/unguessable_token.h"
namespace net {
diff --git a/chromium/services/network/http_cache_data_counter.h b/chromium/services/network/http_cache_data_counter.h
index 050cdf46dca..ffb63d4b9c5 100644
--- a/chromium/services/network/http_cache_data_counter.h
+++ b/chromium/services/network/http_cache_data_counter.h
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
diff --git a/chromium/services/network/http_cache_data_remover.h b/chromium/services/network/http_cache_data_remover.h
index 82e669a9f97..586cc63a822 100644
--- a/chromium/services/network/http_cache_data_remover.h
+++ b/chromium/services/network/http_cache_data_remover.h
@@ -9,7 +9,6 @@
#include "base/callback_forward.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "services/network/conditional_cache_deletion_helper.h"
diff --git a/chromium/services/network/http_cache_data_remover_unittest.cc b/chromium/services/network/http_cache_data_remover_unittest.cc
index 97a737f8f68..87872210f5d 100644
--- a/chromium/services/network/http_cache_data_remover_unittest.cc
+++ b/chromium/services/network/http_cache_data_remover_unittest.cc
@@ -10,6 +10,7 @@
#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/location.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -172,7 +173,7 @@ class HttpCacheDataRemoverTest : public testing::Test {
disk_cache::Backend* backend_ = nullptr;
private:
- net::HttpCache* cache_;
+ raw_ptr<net::HttpCache> cache_;
};
class HttpCacheDataRemoverSplitCacheTest : public HttpCacheDataRemoverTest {
@@ -371,7 +372,14 @@ TEST_F(HttpCacheDataRemoverTest, TestDelayedBackend) {
RemoveData(/*filter=*/nullptr, base::Time(), base::Time());
}
-TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterDeleteByDomain) {
+// TODO(crbug.com/1265408): Flaky.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_FilterDeleteByDomain DISABLED_FilterDeleteByDomain
+#else
+#define MAYBE_FilterDeleteByDomain FilterDeleteByDomain
+#endif
+
+TEST_F(HttpCacheDataRemoverSplitCacheTest, MAYBE_FilterDeleteByDomain) {
mojom::ClearDataFilterPtr filter = mojom::ClearDataFilter::New();
filter->type = mojom::ClearDataFilter_Type::DELETE_MATCHES;
filter->domains.push_back("wikipedia.com");
@@ -384,7 +392,14 @@ TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterDeleteByDomain) {
EXPECT_EQ(4, backend_->GetEntryCount());
}
-TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterKeepByDomain) {
+// TODO(crbug.com/1265408): Flaky.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_FilterKeepByDomain DISABLED_FilterKeepByDomain
+#else
+#define MAYBE_FilterKeepByDomain FilterKeepByDomain
+#endif
+
+TEST_F(HttpCacheDataRemoverSplitCacheTest, MAYBE_FilterKeepByDomain) {
mojom::ClearDataFilterPtr filter = mojom::ClearDataFilter::New();
filter->type = mojom::ClearDataFilter_Type::KEEP_MATCHES;
filter->domains.push_back("wikipedia.com");
@@ -397,7 +412,14 @@ TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterKeepByDomain) {
EXPECT_EQ(4, backend_->GetEntryCount());
}
-TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterDeleteByOrigin) {
+// TODO(crbug.com/1265408): Flaky.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_FilterDeleteByOrigin DISABLED_FilterDeleteByOrigin
+#else
+#define MAYBE_FilterDeleteByOrigin FilterDeleteByOrigin
+#endif
+
+TEST_F(HttpCacheDataRemoverSplitCacheTest, MAYBE_FilterDeleteByOrigin) {
mojom::ClearDataFilterPtr filter = mojom::ClearDataFilter::New();
filter->type = mojom::ClearDataFilter_Type::DELETE_MATCHES;
filter->origins.push_back(url::Origin::Create(GURL("http://www.google.com")));
@@ -408,7 +430,14 @@ TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterDeleteByOrigin) {
EXPECT_EQ(6, backend_->GetEntryCount());
}
-TEST_F(HttpCacheDataRemoverSplitCacheTest, FilterKeepByOrigin) {
+// TODO(crbug.com/1265408): Flaky.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_FilterKeepByOrigin DISABLED_FilterKeepByOrigin
+#else
+#define MAYBE_FilterKeepByOrigin FilterKeepByOrigin
+#endif
+
+TEST_F(HttpCacheDataRemoverSplitCacheTest, MAYBE_FilterKeepByOrigin) {
mojom::ClearDataFilterPtr filter = mojom::ClearDataFilter::New();
filter->type = mojom::ClearDataFilter_Type::KEEP_MATCHES;
filter->origins.push_back(url::Origin::Create(GURL("http://www.google.com")));
diff --git a/chromium/services/network/http_server_properties_pref_delegate.h b/chromium/services/network/http_server_properties_pref_delegate.h
index 97b4325c077..ed5fe36a2a5 100644
--- a/chromium/services/network/http_server_properties_pref_delegate.h
+++ b/chromium/services/network/http_server_properties_pref_delegate.h
@@ -6,7 +6,7 @@
#define SERVICES_NETWORK_HTTP_SERVER_PROPERTIES_PREF_DELEGATE_H_
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "components/prefs/pref_change_registrar.h"
#include "net/http/http_server_properties.h"
@@ -37,7 +37,7 @@ class HttpServerPropertiesPrefDelegate
void WaitForPrefLoad(base::OnceClosure callback) override;
private:
- PrefService* pref_service_;
+ raw_ptr<PrefService> pref_service_;
PrefChangeRegistrar pref_change_registrar_;
};
diff --git a/chromium/services/network/ignore_errors_cert_verifier_unittest.cc b/chromium/services/network/ignore_errors_cert_verifier_unittest.cc
index 699018a6069..ed842a3f454 100644
--- a/chromium/services/network/ignore_errors_cert_verifier_unittest.cc
+++ b/chromium/services/network/ignore_errors_cert_verifier_unittest.cc
@@ -7,6 +7,7 @@
#include "base/base64.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
@@ -69,7 +70,7 @@ class IgnoreErrorsCertVerifierTest : public ::testing::Test {
public:
IgnoreErrorsCertVerifierTest()
: mock_verifier_(new MockCertVerifier()),
- verifier_(base::WrapUnique(mock_verifier_), SPKIHashSet()) {}
+ verifier_(base::WrapUnique(mock_verifier_.get()), SPKIHashSet()) {}
~IgnoreErrorsCertVerifierTest() override {}
protected:
@@ -79,7 +80,7 @@ class IgnoreErrorsCertVerifierTest : public ::testing::Test {
// The wrapped CertVerifier. Defaults to returning ERR_CERT_INVALID. Owned by
// |verifier_|.
- MockCertVerifier* mock_verifier_;
+ raw_ptr<MockCertVerifier> mock_verifier_;
IgnoreErrorsCertVerifier verifier_;
};
diff --git a/chromium/services/network/keepalive_statistics_recorder.h b/chromium/services/network/keepalive_statistics_recorder.h
index 7bc4d26e933..620de51526c 100644
--- a/chromium/services/network/keepalive_statistics_recorder.h
+++ b/chromium/services/network/keepalive_statistics_recorder.h
@@ -8,7 +8,6 @@
#include <map>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/unguessable_token.h"
diff --git a/chromium/services/network/mdns_responder.cc b/chromium/services/network/mdns_responder.cc
index 42cd098a6b3..c582a25e91d 100644
--- a/chromium/services/network/mdns_responder.cc
+++ b/chromium/services/network/mdns_responder.cc
@@ -15,6 +15,7 @@
#include "base/bind.h"
#include "base/guid.h"
#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
@@ -496,7 +497,7 @@ class MdnsResponderManager::SocketHandler {
// handler should be destroyed before |responder_manager_| becomes invalid or
// a weak reference should be used to access the manager when there is no such
// guarantee in an operation.
- MdnsResponderManager* const responder_manager_;
+ const raw_ptr<MdnsResponderManager> responder_manager_;
scoped_refptr<net::IOBufferWithSize> io_buffer_;
net::IPEndPoint recv_addr_;
net::IPEndPoint multicast_addr_;
@@ -631,8 +632,8 @@ class MdnsResponderManager::SocketHandler::ResponseScheduler {
// scheduler should be destroyed before |handler_| becomes invalid or a weak
// reference should be used to access the handler when there is no such
// guarantee in an operation.
- MdnsResponderManager::SocketHandler* const handler_;
- const base::TickClock* tick_clock_;
+ const raw_ptr<MdnsResponderManager::SocketHandler> handler_;
+ raw_ptr<const base::TickClock> tick_clock_;
std::unique_ptr<base::OneShotTimer> dispatch_timer_;
std::map<std::string, base::TimeTicks> next_available_time_for_name_;
base::TimeTicks next_available_time_per_resp_sched_;
diff --git a/chromium/services/network/mdns_responder.h b/chromium/services/network/mdns_responder.h
index b9af8dae305..0b53036fd87 100644
--- a/chromium/services/network/mdns_responder.h
+++ b/chromium/services/network/mdns_responder.h
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
@@ -245,7 +246,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) MdnsResponderManager {
void SendGoodbyePacketForMdnsNameGeneratorServiceIfNecessary();
std::unique_ptr<net::MDnsSocketFactory> owned_socket_factory_;
- net::MDnsSocketFactory* socket_factory_;
+ raw_ptr<net::MDnsSocketFactory> socket_factory_;
// Only the socket handlers that have successfully bound and started are kept.
std::map<uint16_t, std::unique_ptr<SocketHandler>> socket_handler_by_id_;
SocketHandlerStartResult start_result_ =
@@ -262,7 +263,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) MdnsResponderManager {
std::set<std::unique_ptr<MdnsResponder>, base::UniquePtrComparator>
responders_;
- const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance();
+ raw_ptr<const base::TickClock> tick_clock_ =
+ base::DefaultTickClock::GetInstance();
// If not `base::TimeTicks()`, represents the end of the throttling period for
// calls to `StartIfNeeded()`.
@@ -335,10 +337,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) MdnsResponder
// responder should be destroyed before |manager_| becomes invalid or a weak
// reference should be used to access the manager when there is no such
// guarantee in an operation.
- MdnsResponderManager* const manager_;
+ const raw_ptr<MdnsResponderManager> manager_;
std::map<std::string, net::IPAddress> name_addr_map_;
std::map<std::string, uint16_t> name_refcount_map_;
- MdnsResponderManager::NameGenerator* name_generator_;
+ raw_ptr<MdnsResponderManager::NameGenerator> name_generator_;
};
} // namespace network
diff --git a/chromium/services/network/mock_mojo_dhcp_wpad_url_client.h b/chromium/services/network/mock_mojo_dhcp_wpad_url_client.h
index 63f9f293536..923e0f19302 100644
--- a/chromium/services/network/mock_mojo_dhcp_wpad_url_client.h
+++ b/chromium/services/network/mock_mojo_dhcp_wpad_url_client.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/dhcp_wpad_url_client.mojom.h"
diff --git a/chromium/services/network/mojo_host_resolver_impl.cc b/chromium/services/network/mojo_host_resolver_impl.cc
index b7765ec3fd6..a8d8d8a46da 100644
--- a/chromium/services/network/mojo_host_resolver_impl.cc
+++ b/chromium/services/network/mojo_host_resolver_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
@@ -45,7 +46,7 @@ class MojoHostResolverImpl::Job {
// Mojo disconnect handler.
void OnMojoDisconnect();
- MojoHostResolverImpl* resolver_service_;
+ raw_ptr<MojoHostResolverImpl> resolver_service_;
// This Job's iterator in |resolver_service_|, so the Job may be removed on
// completion.
std::list<Job>::iterator iter_;
diff --git a/chromium/services/network/mojo_host_resolver_impl.h b/chromium/services/network/mojo_host_resolver_impl.h
index 89259a7cb09..63ee4026b9d 100644
--- a/chromium/services/network/mojo_host_resolver_impl.h
+++ b/chromium/services/network/mojo_host_resolver_impl.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/log/net_log_with_source.h"
@@ -59,7 +59,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) MojoHostResolverImpl {
void DeleteJob(std::list<Job>::iterator job);
// Resolver for resolving incoming requests. Not owned.
- net::HostResolver* resolver_;
+ raw_ptr<net::HostResolver> resolver_;
// The NetLogWithSource to be passed to |resolver_| for all requests.
const net::NetLogWithSource net_log_;
diff --git a/chromium/services/network/mojo_host_resolver_impl_unittest.cc b/chromium/services/network/mojo_host_resolver_impl_unittest.cc
index a0b40ddc1f3..16a1e153110 100644
--- a/chromium/services/network/mojo_host_resolver_impl_unittest.cc
+++ b/chromium/services/network/mojo_host_resolver_impl_unittest.cc
@@ -16,7 +16,9 @@
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/address_family.h"
+#include "net/base/address_list.h"
#include "net/base/ip_address.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/network_isolation_key.h"
#include "net/dns/mock_host_resolver.h"
@@ -108,13 +110,16 @@ class MojoHostResolverImplTest : public testing::Test {
const net::IPAddress kChromiumOrgAddress{8, 8, 8, 8};
void SetUp() override {
- mock_host_resolver_.rules()->AddRuleForAddressFamily(
- "example.com", net::ADDRESS_FAMILY_IPV4, kExampleComAddress.ToString());
+ net::AddressList example_com_addresses;
+ example_com_addresses.push_back(net::IPEndPoint(kExampleComAddress, 0));
+ example_com_addresses.push_back(net::IPEndPoint(kExampleComAddressIpv6, 0));
mock_host_resolver_.rules()->AddRule("example.com",
- kExampleComAddressIpv6.ToString());
+ std::move(example_com_addresses));
+
mock_host_resolver_.rules()->AddRule("chromium.org",
kChromiumOrgAddress.ToString());
- mock_host_resolver_.rules()->AddSimulatedFailure("failure.fail");
+ mock_host_resolver_.rules()->AddRule("failure.fail",
+ net::ERR_NAME_NOT_RESOLVED);
resolver_service_ = std::make_unique<MojoHostResolverImpl>(
&mock_host_resolver_, net::NetLogWithSource());
@@ -237,7 +242,8 @@ TEST_F(MojoHostResolverImplTest, ResolveEx) {
client.WaitForResult();
EXPECT_THAT(client.error_, IsOk());
- EXPECT_THAT(client.results_, testing::ElementsAre(kExampleComAddressIpv6));
+ EXPECT_THAT(client.results_, testing::UnorderedElementsAre(
+ kExampleComAddress, kExampleComAddressIpv6));
}
// Makes sure that the passed in NetworkIsolationKey is passed to the
diff --git a/chromium/services/network/mojo_socket_test_util.h b/chromium/services/network/mojo_socket_test_util.h
index 8f33e4cb8b5..f0b4be61a4d 100644
--- a/chromium/services/network/mojo_socket_test_util.h
+++ b/chromium/services/network/mojo_socket_test_util.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_NETWORK_MOJO_SOCKET_TEST_UTIL_H_
#define SERVICES_NETWORK_MOJO_SOCKET_TEST_UTIL_H_
-#include "base/macros.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chromium/services/network/net_log_exporter.h b/chromium/services/network/net_log_exporter.h
index 3d9cca990da..084047a5e6f 100644
--- a/chromium/services/network/net_log_exporter.h
+++ b/chromium/services/network/net_log_exporter.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/files/file.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "net/log/net_log.h"
@@ -73,7 +73,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetLogExporter
// NetworkContext owns |this| via UniqueReceiverSet, so this object can't
// outlive it.
- NetworkContext* network_context_;
+ raw_ptr<NetworkContext> network_context_;
enum State { STATE_IDLE, STATE_WAITING_DIR, STATE_RUNNING } state_;
std::unique_ptr<net::FileNetLogObserver> file_net_observer_;
diff --git a/chromium/services/network/network_change_manager.h b/chromium/services/network/network_change_manager.h
index abbe88f0af1..fd20629585f 100644
--- a/chromium/services/network/network_change_manager.h
+++ b/chromium/services/network/network_change_manager.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
diff --git a/chromium/services/network/network_change_manager_unittest.cc b/chromium/services/network/network_change_manager_unittest.cc
index 38d82fa81c2..3dfc0d779a4 100644
--- a/chromium/services/network/network_change_manager_unittest.cc
+++ b/chromium/services/network/network_change_manager_unittest.cc
@@ -8,7 +8,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/network/network_context.cc b/chromium/services/network/network_context.cc
index f8fddf1b0a2..4a3f4fe1fb9 100644
--- a/chromium/services/network/network_context.cc
+++ b/chromium/services/network/network_context.cc
@@ -16,15 +16,16 @@
#include "base/containers/unique_ptr_adapters.h"
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
+#include "base/ignore_result.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_functions.h"
-#include "base/sequenced_task_runner.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/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -84,7 +85,6 @@
#include "services/network/network_service.h"
#include "services/network/network_service_network_delegate.h"
#include "services/network/network_service_proxy_delegate.h"
-#include "services/network/p2p/socket_manager.h"
#include "services/network/proxy_config_service_mojo.h"
#include "services/network/proxy_lookup_request.h"
#include "services/network/proxy_resolving_socket_factory_mojo.h"
@@ -95,7 +95,7 @@
#include "services/network/public/cpp/parsed_headers.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "services/network/public/mojom/network_context.mojom.h"
-#include "services/network/public/mojom/reporting_report.mojom.h"
+#include "services/network/public/mojom/reporting_service.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom-forward.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/resolve_host_request.h"
@@ -129,6 +129,7 @@
#include "services/network/ct_log_list_distributor.h"
#include "services/network/expect_ct_reporter.h"
#include "services/network/sct_auditing/sct_auditing_cache.h"
+#include "services/network/sct_auditing/sct_auditing_handler.h"
#endif // BUILDFLAG(IS_CT_SUPPORTED)
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -152,6 +153,10 @@
#include "services/network/mdns_responder.h"
#endif // BUILDFLAG(ENABLE_MDNS)
+#if BUILDFLAG(IS_P2P_ENABLED)
+#include "services/network/p2p/socket_manager.h"
+#endif
+
#if defined(OS_ANDROID)
#include "base/android/application_status_listener.h"
#endif
@@ -367,7 +372,7 @@ void SCTAuditingDelegate::MaybeEnqueueReport(
bool SCTAuditingDelegate::IsSCTAuditingEnabled() {
if (!context_)
return false;
- return context_->is_sct_auditing_enabled();
+ return context_->sct_auditing_handler()->is_enabled();
}
// Filters `log_list` for disqualified or Google-operated logs,
@@ -376,17 +381,25 @@ bool SCTAuditingDelegate::IsSCTAuditingEnabled() {
void GetCTPolicyConfigForCTLogInfo(
const std::vector<mojom::CTLogInfoPtr>& log_list,
std::vector<std::pair<std::string, base::TimeDelta>>* disqualified_logs,
- std::vector<std::string>* operated_by_google_logs) {
+ std::vector<std::string>* operated_by_google_logs,
+ std::map<std::string, certificate_transparency::OperatorHistoryEntry>*
+ operator_history) {
for (const auto& log : log_list) {
+ std::string log_id = crypto::SHA256HashString(log->public_key);
if (log->operated_by_google || log->disqualified_at) {
- std::string log_id = crypto::SHA256HashString(log->public_key);
if (log->operated_by_google)
operated_by_google_logs->push_back(log_id);
if (log->disqualified_at) {
- disqualified_logs->emplace_back(std::move(log_id),
- log->disqualified_at.value());
+ disqualified_logs->emplace_back(log_id, log->disqualified_at.value());
}
}
+ certificate_transparency::OperatorHistoryEntry entry;
+ entry.current_operator_ = log->current_operator;
+ for (const auto& previous_operator : log->previous_operators) {
+ entry.previous_operators_.emplace_back(previous_operator->name,
+ previous_operator->end_time);
+ }
+ (*operator_history)[log_id] = entry;
}
std::sort(std::begin(*operated_by_google_logs),
@@ -443,7 +456,9 @@ NetworkContext::NetworkContext(
std::make_unique<NetworkContextApplicationStatusListener>()),
#endif
receiver_(this, std::move(receiver)),
- cors_preflight_controller_(network_service) {
+ cors_preflight_controller_(network_service),
+ cors_non_wildcard_request_headers_support_(base::FeatureList::IsEnabled(
+ features::kCorsNonWildcardRequestHeadersSupport)) {
#if defined(OS_WIN) && DCHECK_IS_ON()
if (params_->file_paths) {
DCHECK(params_->win_permissions_set)
@@ -500,7 +515,7 @@ NetworkContext::NetworkContext(
#if BUILDFLAG(IS_CT_SUPPORTED)
if (params_->ct_policy)
SetCTPolicy(std::move(params_->ct_policy));
- SetSCTAuditingEnabled(params_->enable_sct_auditing);
+ sct_auditing_handler()->SetEnabled(params_->enable_sct_auditing);
#endif
#if defined(OS_ANDROID)
@@ -1065,6 +1080,14 @@ void NetworkContext::AddReportingApiObserver(
for (const auto* service_report : service_reports) {
reporting_api_observers_.Get(id)->OnReportAdded(*service_report);
}
+
+ base::flat_map<url::Origin, std::vector<net::ReportingEndpoint>>
+ endpoints_by_origin = url_request_context()
+ ->reporting_service()
+ ->GetV1ReportingEndpointsByOrigin();
+ for (auto const& origin_and_endpoints : endpoints_by_origin) {
+ OnEndpointsUpdatedForOrigin(origin_and_endpoints.second);
+ }
}
}
@@ -1074,6 +1097,13 @@ void NetworkContext::OnReportAdded(const net::ReportingReport* service_report) {
}
}
+void NetworkContext::OnEndpointsUpdatedForOrigin(
+ const std::vector<net::ReportingEndpoint>& endpoints) {
+ for (const auto& observer : reporting_api_observers_) {
+ observer->OnEndpointsUpdatedForOrigin(endpoints);
+ }
+}
+
void NetworkContext::OnReportUpdated(
const net::ReportingReport* service_report) {
for (const auto& observer : reporting_api_observers_) {
@@ -1373,15 +1403,15 @@ void NetworkContext::MaybeEnqueueSCTReport(
const net::X509Certificate* validated_certificate_chain,
const net::SignedCertificateTimestampAndStatusList&
signed_certificate_timestamps) {
- if (!this->is_sct_auditing_enabled())
+ if (!sct_auditing_handler()->is_enabled())
return;
network_service()->sct_auditing_cache()->MaybeEnqueueReport(
- host_port_pair, validated_certificate_chain,
+ this, host_port_pair, validated_certificate_chain,
signed_certificate_timestamps);
}
void NetworkContext::SetSCTAuditingEnabled(bool enabled) {
- is_sct_auditing_enabled_ = enabled;
+ sct_auditing_handler()->SetEnabled(enabled);
}
void NetworkContext::OnCTLogListUpdated(
@@ -1391,11 +1421,14 @@ void NetworkContext::OnCTLogListUpdated(
return;
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
std::vector<std::string> operated_by_google_logs;
+ std::map<std::string, certificate_transparency::OperatorHistoryEntry>
+ log_operator_history;
GetCTPolicyConfigForCTLogInfo(log_list, &disqualified_logs,
- &operated_by_google_logs);
- ct_policy_enforcer_->UpdateCTLogList(update_time,
- std::move(disqualified_logs),
- std::move(operated_by_google_logs));
+ &operated_by_google_logs,
+ &log_operator_history);
+ ct_policy_enforcer_->UpdateCTLogList(
+ update_time, std::move(disqualified_logs),
+ std::move(operated_by_google_logs), std::move(log_operator_history));
}
#endif // BUILDFLAG(IS_CT_SUPPORTED)
@@ -1833,6 +1866,7 @@ void NetworkContext::PreconnectSockets(
base::saturated_cast<int32_t>(num_streams), request_info);
}
+#if BUILDFLAG(IS_P2P_ENABLED)
void NetworkContext::CreateP2PSocketManager(
const net::NetworkIsolationKey& network_isolation_key,
mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> client,
@@ -1848,6 +1882,7 @@ void NetworkContext::CreateP2PSocketManager(
url_request_context_);
socket_managers_[socket_manager.get()] = std::move(socket_manager);
}
+#endif // BUILDFLAG(IS_P2P_ENABLED)
void NetworkContext::CreateMdnsResponder(
mojo::PendingReceiver<mojom::MdnsResponder> responder_receiver) {
@@ -1924,7 +1959,9 @@ void NetworkContext::AddAuthCacheEntry(
->GetSession()
->http_auth_cache();
http_auth_cache->Add(
- challenge.challenger.GetURL(),
+ // TODO(https://crbug.com/): Convert AuthCredentials::challenger field to
+ // a SchemeHostPort.
+ challenge.challenger.GetTupleOrPrecursorTupleIfOpaque(),
challenge.is_proxy ? net::HttpAuth::AUTH_PROXY
: net::HttpAuth::AUTH_SERVER,
challenge.realm, net::HttpAuth::StringToScheme(challenge.scheme),
@@ -1932,6 +1969,15 @@ void NetworkContext::AddAuthCacheEntry(
std::move(callback).Run();
}
+void NetworkContext::SetCorsNonWildcardRequestHeadersSupport(bool value) {
+ if (!base::FeatureList::IsEnabled(
+ features::kCorsNonWildcardRequestHeadersSupport)) {
+ return;
+ }
+ cors_non_wildcard_request_headers_support_ =
+ cors::NonWildcardRequestHeadersSupport(value);
+}
+
void NetworkContext::LookupServerBasicAuthCredentials(
const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
@@ -1940,9 +1986,9 @@ void NetworkContext::LookupServerBasicAuthCredentials(
url_request_context_->http_transaction_factory()
->GetSession()
->http_auth_cache();
- net::HttpAuthCache::Entry* entry =
- http_auth_cache->LookupByPath(url.GetOrigin(), net::HttpAuth::AUTH_SERVER,
- network_isolation_key, url.path());
+ net::HttpAuthCache::Entry* entry = http_auth_cache->LookupByPath(
+ url::SchemeHostPort(url), net::HttpAuth::AUTH_SERVER,
+ network_isolation_key, url.path());
if (entry && entry->scheme() == net::HttpAuth::AUTH_SCHEME_BASIC)
std::move(callback).Run(entry->credentials());
else
@@ -1969,8 +2015,9 @@ void NetworkContext::LookupProxyAuthCredentials(
// 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()) {
+ url::SchemeHostPort scheme_host_port(
+ GURL(scheme + proxy_server.host_port_pair().ToString()));
+ if (!scheme_host_port.IsValid()) {
std::move(callback).Run(absl::nullopt);
return;
}
@@ -1978,8 +2025,8 @@ void NetworkContext::LookupProxyAuthCredentials(
// 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());
+ http_auth_cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ realm, net_scheme, net::NetworkIsolationKey());
if (entry)
std::move(callback).Run(entry->credentials());
else
@@ -2097,12 +2144,16 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
if (params_->enforce_chrome_ct_policy) {
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
std::vector<std::string> operated_by_google_logs;
+ std::map<std::string, certificate_transparency::OperatorHistoryEntry>
+ log_operator_history;
GetCTPolicyConfigForCTLogInfo(network_service_->log_list(),
- &disqualified_logs, &operated_by_google_logs);
+ &disqualified_logs, &operated_by_google_logs,
+ &log_operator_history);
auto ct_policy_enforcer =
std::make_unique<certificate_transparency::ChromeCTPolicyEnforcer>(
network_service_->ct_log_list_update_time(),
- std::move(disqualified_logs), std::move(operated_by_google_logs));
+ std::move(disqualified_logs), std::move(operated_by_google_logs),
+ std::move(log_operator_history));
ct_policy_enforcer_ = ct_policy_enforcer.get();
builder.set_ct_policy_enforcer(std::move(ct_policy_enforcer));
}
@@ -2191,6 +2242,12 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
std::move(params_->proxy_resolver_factory));
}
+#if defined(OS_WIN)
+ if (params_->windows_system_proxy_resolver) {
+ // TODO(https://crbug.com/1032820): Connect to proxy_resolver_win service.
+ }
+#endif
+
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (params_->dhcp_wpad_url_client) {
builder.SetDhcpWpadUrlClient(std::move(params_->dhcp_wpad_url_client));
@@ -2556,11 +2613,13 @@ GURL NetworkContext::GetHSTSRedirect(const GURL& original_url) {
return original_url.ReplaceComponents(replacements);
}
+#if BUILDFLAG(IS_P2P_ENABLED)
void NetworkContext::DestroySocketManager(P2PSocketManager* socket_manager) {
auto iter = socket_managers_.find(socket_manager);
DCHECK(iter != socket_managers_.end());
socket_managers_.erase(iter);
}
+#endif // BUILDFLAG(IS_P2P_ENABLED)
void NetworkContext::CanUploadDomainReliability(
const GURL& origin,
diff --git a/chromium/services/network/network_context.h b/chromium/services/network/network_context.h
index 9f204502a1d..6784d76ced7 100644
--- a/chromium/services/network/network_context.h
+++ b/chromium/services/network/network_context.h
@@ -19,7 +19,7 @@
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
@@ -72,6 +72,10 @@
#include "net/reporting/reporting_report.h"
#endif // BUILDFLAG(ENABLE_REPORTING)
+#if BUILDFLAG(IS_CT_SUPPORTED)
+#include "services/network/sct_auditing/sct_auditing_handler.h"
+#endif // BUILDFLAG(IS_CT_SUPPORTED)
+
namespace base {
class UnguessableToken;
} // namespace base
@@ -299,7 +303,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void OnCTLogListUpdated(
const std::vector<network::mojom::CTLogInfoPtr>& log_list,
base::Time update_time);
- bool is_sct_auditing_enabled() { return is_sct_auditing_enabled_; }
+ SCTAuditingHandler* sct_auditing_handler() { return &sct_auditing_handler_; }
#endif // BUILDFLAG(IS_CT_SUPPORTED)
void CreateUDPSocket(
mojo::PendingReceiver<mojom::UDPSocket> receiver,
@@ -402,6 +406,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const GURL& url,
bool allow_credentials,
const net::NetworkIsolationKey& network_isolation_key) override;
+#if BUILDFLAG(IS_P2P_ENABLED)
void CreateP2PSocketManager(
const net::NetworkIsolationKey& network_isolation_key,
mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> client,
@@ -409,6 +414,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
trusted_socket_manager,
mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver)
override;
+#endif // BUILDFLAG(IS_P2P_ENABLED)
void CreateMdnsResponder(
mojo::PendingReceiver<mojom::MdnsResponder> responder_receiver) override;
void SetDocumentReportingEndpoints(
@@ -446,6 +452,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const net::NetworkIsolationKey& network_isolation_key,
const net::AuthCredentials& credentials,
AddAuthCacheEntryCallback callback) override;
+ void SetCorsNonWildcardRequestHeadersSupport(bool value) override;
// TODO(mmenke): Rename this method and update Mojo docs to make it clear this
// doesn't give proxy auth credentials.
void LookupServerBasicAuthCredentials(
@@ -553,12 +560,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
WebBundleManager& GetWebBundleManager() { return web_bundle_manager_; }
-#if BUILDFLAG(IS_CT_SUPPORTED)
- void SetIsSCTAuditingEnabledForTesting(bool enabled) {
- is_sct_auditing_enabled_ = enabled;
- }
-#endif // BUILDFLAG(IS_CT_SUPPORTED)
-
// Returns the current same-origin-policy exceptions. For more details see
// network::mojom::NetworkContextParams::cors_origin_access_list and
// network::mojom::NetworkContext::SetCorsOriginAccessListsForOrigin.
@@ -570,6 +571,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
return require_network_isolation_key_;
}
+ cors::NonWildcardRequestHeadersSupport
+ cors_non_wildcard_request_headers_support() const {
+ return cors_non_wildcard_request_headers_support_;
+ }
+
#if BUILDFLAG(ENABLE_REPORTING)
void AddReportingApiObserver(
mojo::PendingRemote<network::mojom::ReportingApiObserver> observer)
@@ -577,6 +583,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void OnReportAdded(const net::ReportingReport* service_report) override;
void OnReportUpdated(const net::ReportingReport* service_report) override;
void OnReportingObserverDisconnect(mojo::RemoteSetElementId mojo_id);
+ void OnEndpointsUpdatedForOrigin(
+ const std::vector<net::ReportingEndpoint>& endpoints) override;
#endif // BUILDFLAG(ENABLE_REPORTING)
private:
@@ -605,7 +613,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
GURL GetHSTSRedirect(const GURL& original_url);
+#if BUILDFLAG(IS_P2P_ENABLED)
void DestroySocketManager(P2PSocketManager* socket_manager);
+#endif // BUILDFLAG(IS_P2P_ENABLED)
void CanUploadDomainReliability(const GURL& origin,
base::OnceCallback<void(bool)> callback);
@@ -633,7 +643,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void FinishConstructingTrustTokenStore(
std::unique_ptr<SQLiteTrustTokenPersister> persister);
- NetworkService* const network_service_;
+ const raw_ptr<NetworkService> network_service_;
mojo::Remote<mojom::NetworkContextClient> client_;
@@ -644,7 +654,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// URLRequestContext.
URLRequestContextOwner url_request_context_owner_;
- net::URLRequestContext* url_request_context_;
+ raw_ptr<net::URLRequestContext> url_request_context_;
#if BUILDFLAG(ENABLE_REPORTING)
bool is_observing_reporting_service_;
@@ -653,7 +663,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
#endif // BUILDFLAG(ENABLE_REPORTING)
// Owned by URLRequestContext.
- NetworkServiceNetworkDelegate* network_delegate_ = nullptr;
+ raw_ptr<NetworkServiceNetworkDelegate> network_delegate_ = nullptr;
mojom::NetworkContextParamsPtr params_;
@@ -703,8 +713,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
static constexpr uint32_t kMaxOutstandingRequestsPerProcess = 2700;
uint32_t max_loaders_per_process_ = kMaxOutstandingRequestsPerProcess;
+#if BUILDFLAG(IS_P2P_ENABLED)
base::flat_map<P2PSocketManager*, std::unique_ptr<P2PSocketManager>>
socket_managers_;
+#endif // BUILDFLAG(IS_P2P_ENABLED)
#if BUILDFLAG(ENABLE_MDNS)
std::unique_ptr<MdnsResponderManager> mdns_responder_manager_;
@@ -720,7 +732,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
int current_resource_scheduler_client_id_ = 0;
// Owned by the URLRequestContext
- net::StaticHttpUserAgentSettings* user_agent_settings_ = nullptr;
+ raw_ptr<net::StaticHttpUserAgentSettings> user_agent_settings_ = nullptr;
// Pointed to by the TransportSecurityState (owned by the
// URLRequestContext), and must be disconnected from it before it's destroyed.
@@ -736,10 +748,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
outstanding_set_expect_ct_callbacks_;
// Owned by the URLRequestContext.
- certificate_transparency::ChromeCTPolicyEnforcer* ct_policy_enforcer_ =
- nullptr;
+ raw_ptr<certificate_transparency::ChromeCTPolicyEnforcer>
+ ct_policy_enforcer_ = nullptr;
- bool is_sct_auditing_enabled_ = false;
+ SCTAuditingHandler sct_auditing_handler_;
#endif // BUILDFLAG(IS_CT_SUPPORTED)
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -761,7 +773,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
host_resolvers_;
std::unique_ptr<net::HostResolver::ProbeRequest> doh_probes_request_;
- NetworkServiceProxyDelegate* proxy_delegate_ = nullptr;
+ raw_ptr<NetworkServiceProxyDelegate> proxy_delegate_ = nullptr;
// Used for Signed Exchange certificate verification.
int next_cert_verify_id_ = 0;
@@ -816,6 +828,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// DCHECKs on APIs used by external callers.
bool require_network_isolation_key_ = false;
+ // Indicating whether
+ // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name is
+ // supported.
+ cors::NonWildcardRequestHeadersSupport
+ cors_non_wildcard_request_headers_support_;
+
// CorsURLLoaderFactory assumes that fields owned by the NetworkContext always
// live longer than the factory. Therefore we want the factories to be
// destroyed before other fields above. In particular:
diff --git a/chromium/services/network/network_context_unittest.cc b/chromium/services/network/network_context_unittest.cc
index 844bc0cac9a..adef22bd591 100644
--- a/chromium/services/network/network_context_unittest.cc
+++ b/chromium/services/network/network_context_unittest.cc
@@ -22,6 +22,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_source.h"
@@ -122,8 +123,6 @@
#include "services/network/public/mojom/net_log.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
-#include "services/network/public/mojom/p2p.mojom.h"
-#include "services/network/public/mojom/p2p_trusted.mojom.h"
#include "services/network/public/mojom/proxy_config.mojom.h"
#include "services/network/public/mojom/url_loader.mojom-shared.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
@@ -159,6 +158,11 @@
#include "services/network/mock_mojo_dhcp_wpad_url_client.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_P2P_ENABLED)
+#include "services/network/public/mojom/p2p.mojom.h"
+#include "services/network/public/mojom/p2p_trusted.mojom.h"
+#endif // BUILDFLAG(IS_P2P_ENABLED)
+
namespace network {
namespace {
@@ -373,6 +377,7 @@ class TestProxyLookupClient : public mojom::ProxyLookupClient {
base::RunLoop run_loop_;
};
+#if BUILDFLAG(IS_P2P_ENABLED)
class MockP2PTrustedSocketManagerClient
: public mojom::P2PTrustedSocketManagerClient {
public:
@@ -385,6 +390,7 @@ class MockP2PTrustedSocketManagerClient
uint64_t packet_length,
bool incoming) override {}
};
+#endif // BUILDFLAG(IS_P2P_ENABLED)
class NetworkContextTest : public testing::Test {
public:
@@ -1347,6 +1353,7 @@ TEST_F(NetworkContextTest, HostResolutionFailure) {
client.completion_status().resolve_error_info.error);
}
+#if BUILDFLAG(IS_P2P_ENABLED)
// Test the P2PSocketManager::GetHostAddress() works and uses the correct
// NetworkIsolationKey.
TEST_F(NetworkContextTest, P2PHostResolution) {
@@ -1425,6 +1432,7 @@ TEST_F(NetworkContextTest, P2PHostResolution) {
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, callback2.GetResult(result));
}
}
+#endif // BUILDFLAG(IS_P2P_ENABLED)
// Test that valid referrers are allowed, while invalid ones result in errors.
TEST_F(NetworkContextTest, Referrers) {
@@ -1839,7 +1847,7 @@ TEST_F(NetworkContextTest, ClearHostCache) {
}
TEST_F(NetworkContextTest, ClearHttpAuthCache) {
- GURL origin("http://google.com");
+ url::SchemeHostPort scheme_host_port(GURL("http://google.com"));
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateNetworkContextParamsForTesting());
net::HttpAuthCache* cache = network_context->url_request_context()
@@ -1855,21 +1863,21 @@ TEST_F(NetworkContextTest, ClearHttpAuthCache) {
std::u16string user = u"user";
std::u16string password = u"pass";
- cache->Add(origin, net::HttpAuth::AUTH_SERVER, "Realm1",
+ cache->Add(scheme_host_port, net::HttpAuth::AUTH_SERVER, "Realm1",
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
"basic realm=Realm1", net::AuthCredentials(user, password), "/");
test_clock.Advance(base::Hours(1)); // Time now 13:00
- cache->Add(origin, net::HttpAuth::AUTH_PROXY, "Realm2",
+ cache->Add(scheme_host_port, net::HttpAuth::AUTH_PROXY, "Realm2",
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
"basic realm=Realm2", net::AuthCredentials(user, password), "/");
ASSERT_EQ(2u, cache->GetEntriesSizeForTesting());
- ASSERT_NE(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_SERVER, "Realm1",
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ ASSERT_NE(nullptr, cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
- ASSERT_NE(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_PROXY, "Realm2",
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ ASSERT_NE(nullptr, cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
{
base::RunLoop run_loop;
@@ -1880,12 +1888,14 @@ TEST_F(NetworkContextTest, ClearHttpAuthCache) {
run_loop.Run();
EXPECT_EQ(1u, cache->GetEntriesSizeForTesting());
- EXPECT_EQ(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_SERVER,
- "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey()));
- EXPECT_NE(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_PROXY,
- "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey()));
+ EXPECT_EQ(nullptr,
+ cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
+ net::NetworkIsolationKey()));
+ EXPECT_NE(nullptr,
+ cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
+ net::NetworkIsolationKey()));
}
{
base::RunLoop run_loop;
@@ -1896,17 +1906,19 @@ TEST_F(NetworkContextTest, ClearHttpAuthCache) {
run_loop.Run();
EXPECT_EQ(0u, cache->GetEntriesSizeForTesting());
- EXPECT_EQ(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_SERVER,
- "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey()));
- EXPECT_EQ(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_PROXY,
- "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey()));
+ EXPECT_EQ(nullptr,
+ cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
+ net::NetworkIsolationKey()));
+ EXPECT_EQ(nullptr,
+ cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
+ net::NetworkIsolationKey()));
}
}
TEST_F(NetworkContextTest, ClearAllHttpAuthCache) {
- GURL origin("http://google.com");
+ url::SchemeHostPort scheme_host_port(GURL("http://google.com"));
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateNetworkContextParamsForTesting());
net::HttpAuthCache* cache = network_context->url_request_context()
@@ -1922,21 +1934,21 @@ TEST_F(NetworkContextTest, ClearAllHttpAuthCache) {
std::u16string user = u"user";
std::u16string password = u"pass";
- cache->Add(origin, net::HttpAuth::AUTH_SERVER, "Realm1",
+ cache->Add(scheme_host_port, net::HttpAuth::AUTH_SERVER, "Realm1",
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
"basic realm=Realm1", net::AuthCredentials(user, password), "/");
test_clock.Advance(base::Hours(1)); // Time now 13:00
- cache->Add(origin, net::HttpAuth::AUTH_PROXY, "Realm2",
+ cache->Add(scheme_host_port, net::HttpAuth::AUTH_PROXY, "Realm2",
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
"basic realm=Realm2", net::AuthCredentials(user, password), "/");
ASSERT_EQ(2u, cache->GetEntriesSizeForTesting());
- ASSERT_NE(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_SERVER, "Realm1",
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ ASSERT_NE(nullptr, cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
- ASSERT_NE(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_PROXY, "Realm2",
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ ASSERT_NE(nullptr, cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
base::RunLoop run_loop;
@@ -1945,11 +1957,11 @@ TEST_F(NetworkContextTest, ClearAllHttpAuthCache) {
run_loop.Run();
EXPECT_EQ(0u, cache->GetEntriesSizeForTesting());
- EXPECT_EQ(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_SERVER, "Realm1",
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ EXPECT_EQ(nullptr, cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ "Realm1", net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
- EXPECT_EQ(nullptr, cache->Lookup(origin, net::HttpAuth::AUTH_PROXY, "Realm2",
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ EXPECT_EQ(nullptr, cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ "Realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
}
@@ -2007,10 +2019,10 @@ TEST_F(NetworkContextTest, LookupServerBasicAuthCredentials) {
std::u16string user = u"user";
std::u16string password = u"pass";
- cache->Add(origin, net::HttpAuth::AUTH_SERVER, "Realm",
+ cache->Add(url::SchemeHostPort(origin), net::HttpAuth::AUTH_SERVER, "Realm",
net::HttpAuth::AUTH_SCHEME_BASIC, network_isolation_key1,
"basic realm=Realm", net::AuthCredentials(user, password), "/");
- cache->Add(origin2, net::HttpAuth::AUTH_PROXY, "Realm",
+ cache->Add(url::SchemeHostPort(origin2), net::HttpAuth::AUTH_PROXY, "Realm",
net::HttpAuth::AUTH_SCHEME_BASIC, network_isolation_key1,
"basic realm=Realm", net::AuthCredentials(user, password), "/");
@@ -2067,17 +2079,20 @@ TEST_F(NetworkContextTest, LookupProxyAuthCredentials) {
std::u16string user = u"user";
std::u16string password = u"pass";
- cache->Add(http_proxy, net::HttpAuth::AUTH_PROXY, "Realm",
- net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
- "basic realm=Realm", net::AuthCredentials(user, password),
+ cache->Add(url::SchemeHostPort(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),
+ cache->Add(url::SchemeHostPort(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),
+ cache->Add(url::SchemeHostPort(server_origin), net::HttpAuth::AUTH_SERVER,
+ "Realm", net::HttpAuth::AUTH_SCHEME_BASIC,
+ net::NetworkIsolationKey(), "basic realm=Realm",
+ net::AuthCredentials(user, password),
/* path = */ "/");
absl::optional<net::AuthCredentials> result = GetProxyAuthCredentials(
network_context.get(),
@@ -2575,7 +2590,7 @@ TEST_F(NetworkContextTest, CookieManager) {
->GetCookieListWithOptionsAsync(
GURL("http://www.test.com/whatever"),
net::CookieOptions::MakeAllInclusive(),
- net::CookiePartitionKeychain(),
+ net::CookiePartitionKeyCollection(),
base::BindOnce(&GetCookieListCallback, &run_loop2, &cookies));
run_loop2.Run();
ASSERT_EQ(1u, cookies.size());
@@ -2872,6 +2887,9 @@ class MockMojoProxyResolver : public proxy_resolver::mojom::ProxyResolver {
public:
MockMojoProxyResolver() {}
+ MockMojoProxyResolver(const MockMojoProxyResolver&) = delete;
+ MockMojoProxyResolver& operator=(const MockMojoProxyResolver&) = delete;
+
private:
// Overridden from proxy_resolver::mojom::ProxyResolver:
void GetProxyForUrl(
@@ -2890,8 +2908,6 @@ class MockMojoProxyResolver : public proxy_resolver::mojom::ProxyResolver {
client->ReportResult(net::OK, result);
}
-
- DISALLOW_COPY_AND_ASSIGN(MockMojoProxyResolver);
};
// Test mojom::ProxyResolverFactory implementation that successfully completes
@@ -2902,6 +2918,10 @@ class MockMojoProxyResolverFactory
public:
MockMojoProxyResolverFactory() {}
+ MockMojoProxyResolverFactory(const MockMojoProxyResolverFactory&) = delete;
+ MockMojoProxyResolverFactory& operator=(const MockMojoProxyResolverFactory&) =
+ delete;
+
// Binds and returns a mock ProxyResolverFactory whose lifetime is bound to
// the message pipe.
static mojo::PendingRemote<proxy_resolver::mojom::ProxyResolverFactory>
@@ -2928,8 +2948,6 @@ class MockMojoProxyResolverFactory
client(std::move(pending_client));
client->ReportResult(net::OK);
}
-
- DISALLOW_COPY_AND_ASSIGN(MockMojoProxyResolverFactory);
};
TEST_F(NetworkContextTest, PacQuickCheck) {
@@ -3291,11 +3309,12 @@ class TestResolveHostClient : public ResolveHostClientBase {
int top_level_result_error_;
int result_error_;
absl::optional<net::AddressList> result_addresses_;
- base::RunLoop* const run_loop_;
+ const raw_ptr<base::RunLoop> run_loop_;
};
TEST_F(NetworkContextTest, ResolveHost_Sync) {
auto resolver = std::make_unique<net::MockHostResolver>();
+ resolver->rules()->AddRule("sync.test", "1.2.3.4");
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateNetworkContextParamsForTesting());
@@ -3312,7 +3331,7 @@ TEST_F(NetworkContextTest, ResolveHost_Sync) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
network_context->ResolveHost(
- net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
+ net::HostPortPair("sync.test", 160), net::NetworkIsolationKey(),
std::move(optional_parameters), std::move(pending_response_client));
run_loop.Run();
@@ -3320,13 +3339,14 @@ TEST_F(NetworkContextTest, ResolveHost_Sync) {
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(
response_client.result_addresses().value().endpoints(),
- testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
+ testing::UnorderedElementsAre(CreateExpectedEndPoint("1.2.3.4", 160)));
EXPECT_EQ(0u,
network_context->GetNumOutstandingResolveHostRequestsForTesting());
}
TEST_F(NetworkContextTest, ResolveHost_Async) {
auto resolver = std::make_unique<net::MockHostResolver>();
+ resolver->rules()->AddRule("async.test", "1.2.3.4");
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateNetworkContextParamsForTesting());
@@ -3343,7 +3363,7 @@ TEST_F(NetworkContextTest, ResolveHost_Async) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
network_context->ResolveHost(
- net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
+ net::HostPortPair("async.test", 160), net::NetworkIsolationKey(),
std::move(optional_parameters), std::move(pending_response_client));
bool control_handle_closed = false;
@@ -3356,7 +3376,7 @@ TEST_F(NetworkContextTest, ResolveHost_Async) {
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(
response_client.result_addresses().value().endpoints(),
- testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
+ testing::UnorderedElementsAre(CreateExpectedEndPoint("1.2.3.4", 160)));
EXPECT_TRUE(control_handle_closed);
EXPECT_EQ(0u,
network_context->GetNumOutstandingResolveHostRequestsForTesting());
@@ -3435,6 +3455,7 @@ TEST_F(NetworkContextTest, ResolveHost_NetworkIsolationKey) {
const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
net::MockHostResolver resolver;
+ resolver.rules()->AddRule("nik.test", "1.2.3.4");
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateNetworkContextParamsForTesting());
@@ -3450,14 +3471,14 @@ TEST_F(NetworkContextTest, ResolveHost_NetworkIsolationKey) {
TestResolveHostClient response_client(&pending_response_client, &run_loop);
network_context->ResolveHost(
- net::HostPortPair("localhost", 160), kNetworkIsolationKey,
+ net::HostPortPair("nik.test", 160), kNetworkIsolationKey,
std::move(optional_parameters), std::move(pending_response_client));
run_loop.Run();
EXPECT_EQ(net::OK, response_client.result_error());
EXPECT_THAT(
response_client.result_addresses().value().endpoints(),
- testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
+ testing::UnorderedElementsAre(CreateExpectedEndPoint("1.2.3.4", 160)));
EXPECT_EQ(0u,
network_context->GetNumOutstandingResolveHostRequestsForTesting());
EXPECT_EQ(kNetworkIsolationKey,
@@ -4602,8 +4623,14 @@ TEST_F(NetworkContextTest, TrustedParams) {
// Test that the disable_secure_dns trusted param is passed through to the
// host resolver.
TEST_F(NetworkContextTest, TrustedParams_DisableSecureDns) {
+ net::EmbeddedTestServer test_server;
+ test_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("services/test/data")));
+ ASSERT_TRUE(test_server.Start());
+
std::unique_ptr<net::MockHostResolver> resolver =
std::make_unique<net::MockHostResolver>();
+ resolver->rules()->AddRule("example.test", test_server.GetIPLiteralString());
std::unique_ptr<net::TestURLRequestContext> url_request_context =
std::make_unique<net::TestURLRequestContext>(
true /* delay_initialization */);
@@ -4629,7 +4656,7 @@ TEST_F(NetworkContextTest, TrustedParams_DisableSecureDns) {
for (bool disable_secure_dns : {false, true}) {
ResourceRequest request;
- request.url = GURL("http://example.test");
+ request.url = GURL("http://example.test/echo");
request.load_flags = net::LOAD_BYPASS_CACHE;
request.trusted_params = ResourceRequest::TrustedParams();
request.trusted_params->disable_secure_dns = disable_secure_dns;
@@ -4654,7 +4681,13 @@ TEST_F(NetworkContextTest, TrustedParams_DisableSecureDns) {
// Test that the disable_secure_dns factory param is passed through to the
// host resolver.
TEST_F(NetworkContextTest, FactoryParams_DisableSecureDns) {
+ net::EmbeddedTestServer test_server;
+ test_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("services/test/data")));
+ ASSERT_TRUE(test_server.Start());
+
net::MockHostResolver resolver;
+ resolver.rules()->AddRule("example.test", test_server.GetIPLiteralString());
net::TestURLRequestContext url_request_context(
true /* delay_initialization */);
url_request_context.set_host_resolver(&resolver);
@@ -4678,7 +4711,7 @@ TEST_F(NetworkContextTest, FactoryParams_DisableSecureDns) {
loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
ResourceRequest request;
- request.url = GURL("http://example.test");
+ request.url = GURL("http://example.test/echo");
request.load_flags = net::LOAD_BYPASS_CACHE;
auto client = std::make_unique<TestURLLoaderClient>();
mojo::Remote<mojom::URLLoader> loader;
@@ -5365,6 +5398,9 @@ class TestURLLoaderHeaderClient : public mojom::TrustedURLLoaderHeaderClient {
public:
TestHeaderClient() {}
+ TestHeaderClient(const TestHeaderClient&) = delete;
+ TestHeaderClient& operator=(const TestHeaderClient&) = delete;
+
// network::mojom::TrustedHeaderClient:
void OnBeforeSendHeaders(const net::HttpRequestHeaders& headers,
OnBeforeSendHeadersCallback callback) override {
@@ -5401,14 +5437,16 @@ class TestURLLoaderHeaderClient : public mojom::TrustedURLLoaderHeaderClient {
int on_before_send_headers_result_ = net::OK;
int on_headers_received_result_ = net::OK;
mojo::Receiver<mojom::TrustedHeaderClient> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(TestHeaderClient);
};
explicit TestURLLoaderHeaderClient(
mojo::PendingReceiver<mojom::TrustedURLLoaderHeaderClient> receiver)
: receiver_(this, std::move(receiver)) {}
+ TestURLLoaderHeaderClient(const TestURLLoaderHeaderClient&) = delete;
+ TestURLLoaderHeaderClient& operator=(const TestURLLoaderHeaderClient&) =
+ delete;
+
// network::mojom::TrustedURLLoaderHeaderClient:
void OnLoaderCreated(
int32_t request_id,
@@ -5433,8 +5471,6 @@ class TestURLLoaderHeaderClient : public mojom::TrustedURLLoaderHeaderClient {
private:
TestHeaderClient header_client_;
mojo::Receiver<mojom::TrustedURLLoaderHeaderClient> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(TestURLLoaderHeaderClient);
};
TEST_F(NetworkContextTest, HeaderClientModifiesHeaders) {
@@ -5561,6 +5597,9 @@ class HangingTestURLLoaderHeaderClient
public:
TestHeaderClient() {}
+ TestHeaderClient(const TestHeaderClient&) = delete;
+ TestHeaderClient& operator=(const TestHeaderClient&) = delete;
+
// network::mojom::TrustedHeaderClient:
void OnBeforeSendHeaders(const net::HttpRequestHeaders& headers,
OnBeforeSendHeadersCallback callback) override {
@@ -5610,14 +5649,17 @@ class HangingTestURLLoaderHeaderClient
std::string saved_received_headers_;
OnHeadersReceivedCallback saved_on_headers_received_callback_;
mojo::Receiver<mojom::TrustedHeaderClient> receiver_{this};
-
- DISALLOW_COPY_AND_ASSIGN(TestHeaderClient);
};
explicit HangingTestURLLoaderHeaderClient(
mojo::PendingReceiver<mojom::TrustedURLLoaderHeaderClient> receiver)
: receiver_(this, std::move(receiver)) {}
+ HangingTestURLLoaderHeaderClient(const HangingTestURLLoaderHeaderClient&) =
+ delete;
+ HangingTestURLLoaderHeaderClient& operator=(
+ const HangingTestURLLoaderHeaderClient&) = delete;
+
// network::mojom::TrustedURLLoaderHeaderClient:
void OnLoaderCreated(
int32_t request_id,
@@ -5648,8 +5690,6 @@ class HangingTestURLLoaderHeaderClient
private:
TestHeaderClient header_client_;
mojo::Receiver<mojom::TrustedURLLoaderHeaderClient> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(HangingTestURLLoaderHeaderClient);
};
// Test waiting on the OnHeadersReceived event, then proceeding to call the
@@ -5799,9 +5839,8 @@ TEST_F(NetworkContextTest, HangingHeaderClientAbortDuringOnHeadersReceived) {
class NetworkContextMockHostTest : public NetworkContextTest {
public:
NetworkContextMockHostTest() {
- scoped_refptr<net::RuleBasedHostResolverProc> rules =
- net::CreateCatchAllHostResolverProc();
- rules->AddRule(kMockHost, "127.0.0.1");
+ net::MockHostResolverBase::RuleResolver rules;
+ rules.AddRule(kMockHost, "127.0.0.1");
network_service_->set_host_resolver_factory_for_testing(
std::make_unique<net::MockHostResolverFactory>(std::move(rules)));
@@ -5854,8 +5893,10 @@ TEST_F(NetworkContextMockHostTest, MAYBE_CustomProxyUsesSpecifiedProxyList) {
config->rules.ParseFromString(
"http=" +
net::ProxyServerToProxyUri(ConvertToProxyServer(proxy_test_server)));
- proxy_config_client->OnCustomProxyConfigUpdated(std::move(config));
- task_environment_.RunUntilIdle();
+ base::RunLoop loop;
+ proxy_config_client->OnCustomProxyConfigUpdated(std::move(config),
+ loop.QuitClosure());
+ loop.Run();
ResourceRequest request;
request.url = GURL("http://does.not.resolve/echo");
@@ -6104,7 +6145,11 @@ TEST_F(NetworkContextTest, CertificateTransparencyConfig) {
log_info->public_key = std::string(4, 0x30 + static_cast<char>(i));
log_info->name = std::string(4, 0x30 + static_cast<char>(i));
log_info->operated_by_google = i % 2;
-
+ if (log_info->operated_by_google) {
+ log_info->current_operator = "Google";
+ } else {
+ log_info->current_operator = "Not Google";
+ }
log_list_mojo.push_back(std::move(log_info));
}
for (int i = 0; i < 3; ++i) {
@@ -6114,6 +6159,7 @@ TEST_F(NetworkContextTest, CertificateTransparencyConfig) {
log_info->name = std::string(4, 0x41 + static_cast<char>(i));
log_info->operated_by_google = false;
log_info->disqualified_at = base::Seconds(i);
+ log_info->current_operator = "Not Google Either";
log_list_mojo.push_back(std::move(log_info));
}
@@ -6155,6 +6201,88 @@ TEST_F(NetworkContextTest, CertificateTransparencyConfig) {
::testing::Pair(crypto::SHA256HashString("AAAA"), base::Seconds(0)),
::testing::Pair(crypto::SHA256HashString("BBBB"), base::Seconds(1)),
::testing::Pair(crypto::SHA256HashString("CCCC"), base::Seconds(2))));
+
+ std::map<std::string, certificate_transparency::OperatorHistoryEntry>
+ operator_history = policy_enforcer->operator_history_for_testing();
+
+ for (auto log : policy_enforcer->operated_by_google_logs_for_testing()) {
+ EXPECT_EQ(operator_history[log].current_operator_, "Google");
+ EXPECT_TRUE(operator_history[log].previous_operators_.empty());
+ }
+
+ for (auto log : policy_enforcer->disqualified_logs_for_testing()) {
+ EXPECT_EQ(operator_history[log.first].current_operator_,
+ "Not Google Either");
+ EXPECT_TRUE(operator_history[log.first].previous_operators_.empty());
+ }
+}
+
+TEST_F(NetworkContextTest, CertificateTransparencyConfigWithOperatorSwitches) {
+ // Configure CT logs in network service.
+ std::vector<network::mojom::CTLogInfoPtr> log_list_mojo;
+
+ // The log public keys do not matter for the test, so invalid keys are used.
+ // However, because the log IDs are derived from the SHA-256 hash of the log
+ // key, the log keys are generated such that the log that never switched
+ // operator is "0000", while the one that did is "AAAA".
+ network::mojom::CTLogInfoPtr log_info = network::mojom::CTLogInfo::New();
+ // Shift to ASCII '0' (0x30)
+ log_info->public_key = std::string(4, 0x30);
+ log_info->name = std::string(4, 0x30);
+ log_info->current_operator = "Forever Operator";
+ log_list_mojo.push_back(std::move(log_info));
+
+ log_info = network::mojom::CTLogInfo::New();
+ // Shift to ASCII 'A' (0x41)
+ log_info->public_key = std::string(4, 0x41);
+ log_info->name = std::string(4, 0x41);
+ log_info->current_operator = "Changed Operator";
+ for (int i = 0; i < 3; i++) {
+ network::mojom::PreviousOperatorEntryPtr previous_operator =
+ network::mojom::PreviousOperatorEntry::New();
+ previous_operator->name = "Operator " + base::NumberToString(i);
+ previous_operator->end_time = base::Seconds(i);
+ log_info->previous_operators.push_back(std::move(previous_operator));
+ }
+ log_list_mojo.push_back(std::move(log_info));
+
+ network_service()->UpdateCtLogList(std::move(log_list_mojo),
+ base::Time::Now());
+
+ // Configure CT params in network context.
+ mojom::NetworkContextParamsPtr params =
+ CreateNetworkContextParamsForTesting();
+ params->enforce_chrome_ct_policy = true;
+
+ std::unique_ptr<NetworkContext> network_context =
+ CreateContextWithParams(std::move(params));
+
+ net::CTPolicyEnforcer* request_enforcer =
+ network_context->url_request_context()->ct_policy_enforcer();
+ ASSERT_TRUE(request_enforcer);
+
+ // Completely unsafe if |enforce_chrome_ct_policy| is false.
+ certificate_transparency::ChromeCTPolicyEnforcer* policy_enforcer =
+ reinterpret_cast<certificate_transparency::ChromeCTPolicyEnforcer*>(
+ request_enforcer);
+
+ std::map<std::string, certificate_transparency::OperatorHistoryEntry>
+ operator_history = policy_enforcer->operator_history_for_testing();
+
+ EXPECT_EQ(
+ operator_history[crypto::SHA256HashString("0000")].current_operator_,
+ "Forever Operator");
+ EXPECT_TRUE(operator_history[crypto::SHA256HashString("0000")]
+ .previous_operators_.empty());
+
+ EXPECT_EQ(
+ operator_history[crypto::SHA256HashString("AAAA")].current_operator_,
+ "Changed Operator");
+ EXPECT_THAT(
+ operator_history[crypto::SHA256HashString("AAAA")].previous_operators_,
+ ::testing::ElementsAre(::testing::Pair("Operator 0", base::Seconds(0)),
+ ::testing::Pair("Operator 1", base::Seconds(1)),
+ ::testing::Pair("Operator 2", base::Seconds(2))));
}
#endif
@@ -6172,16 +6300,16 @@ TEST_F(NetworkContextTest, AddHttpAuthCacheEntry) {
EXPECT_FALSE(cache->key_server_entries_by_network_isolation_key());
// Add an AUTH_SERVER cache entry.
- GURL url("http://example.test/");
+ url::SchemeHostPort scheme_host_port(GURL("http://example.test/"));
net::AuthChallengeInfo challenge;
challenge.is_proxy = false;
- challenge.challenger = url::Origin::Create(url);
+ challenge.challenger = url::Origin::Create(scheme_host_port.GetURL());
challenge.scheme = "basic";
challenge.realm = "testrealm";
const char16_t kUsername[] = u"test_user";
const char16_t kPassword[] = u"test_pass";
- ASSERT_FALSE(cache->Lookup(url, net::HttpAuth::AUTH_SERVER, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ ASSERT_FALSE(cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
base::RunLoop run_loop;
network_context->AddAuthCacheEntry(challenge, net::NetworkIsolationKey(),
@@ -6189,26 +6317,26 @@ TEST_F(NetworkContextTest, AddHttpAuthCacheEntry) {
run_loop.QuitClosure());
run_loop.Run();
net::HttpAuthCache::Entry* entry = cache->Lookup(
- url, net::HttpAuth::AUTH_SERVER, challenge.realm,
+ scheme_host_port, net::HttpAuth::AUTH_SERVER, challenge.realm,
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey());
ASSERT_TRUE(entry);
- EXPECT_EQ(url, entry->origin());
+ EXPECT_EQ(scheme_host_port, entry->scheme_host_port());
EXPECT_EQ(challenge.realm, entry->realm());
EXPECT_EQ(net::HttpAuth::StringToScheme(challenge.scheme), entry->scheme());
EXPECT_EQ(kUsername, entry->credentials().username());
EXPECT_EQ(kPassword, entry->credentials().password());
// Entry should only have been added for server auth.
- EXPECT_FALSE(cache->Lookup(url, net::HttpAuth::AUTH_PROXY, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ EXPECT_FALSE(cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
// Add an AUTH_PROXY cache entry.
- GURL proxy_url("http://proxy.test/");
+ url::SchemeHostPort proxy_scheme_host_port(GURL("http://proxy.test/"));
challenge.is_proxy = true;
- challenge.challenger = url::Origin::Create(proxy_url);
+ challenge.challenger = url::Origin::Create(proxy_scheme_host_port.GetURL());
const char16_t kProxyUsername[] = u"test_proxy_user";
const char16_t kProxyPassword[] = u"test_proxy_pass";
- ASSERT_FALSE(cache->Lookup(proxy_url, net::HttpAuth::AUTH_PROXY,
+ ASSERT_FALSE(cache->Lookup(proxy_scheme_host_port, net::HttpAuth::AUTH_PROXY,
challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
base::RunLoop run_loop2;
@@ -6217,17 +6345,17 @@ TEST_F(NetworkContextTest, AddHttpAuthCacheEntry) {
net::AuthCredentials(kProxyUsername, kProxyPassword),
run_loop2.QuitClosure());
run_loop2.Run();
- entry = cache->Lookup(proxy_url, net::HttpAuth::AUTH_PROXY, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ entry = cache->Lookup(proxy_scheme_host_port, net::HttpAuth::AUTH_PROXY,
+ challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey());
ASSERT_TRUE(entry);
- EXPECT_EQ(proxy_url, entry->origin());
+ EXPECT_EQ(proxy_scheme_host_port, entry->scheme_host_port());
EXPECT_EQ(challenge.realm, entry->realm());
EXPECT_EQ(net::HttpAuth::StringToScheme(challenge.scheme), entry->scheme());
EXPECT_EQ(kProxyUsername, entry->credentials().username());
EXPECT_EQ(kProxyPassword, entry->credentials().password());
// Entry should only have been added for proxy auth.
- EXPECT_FALSE(cache->Lookup(proxy_url, net::HttpAuth::AUTH_SERVER,
+ EXPECT_FALSE(cache->Lookup(proxy_scheme_host_port, net::HttpAuth::AUTH_SERVER,
challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
}
@@ -6248,34 +6376,36 @@ TEST_F(NetworkContextTest, AddHttpAuthCacheEntryWithNetworkIsolationKey) {
// Add an AUTH_SERVER cache entry.
GURL url("http://example.test/");
url::Origin origin = url::Origin::Create(url);
+ url::SchemeHostPort scheme_host_port =
+ origin.GetTupleOrPrecursorTupleIfOpaque();
net::NetworkIsolationKey network_isolation_key(origin, origin);
net::AuthChallengeInfo challenge;
challenge.is_proxy = false;
- challenge.challenger = origin;
+ challenge.challenger = url::Origin::Create(scheme_host_port.GetURL());
challenge.scheme = "basic";
challenge.realm = "testrealm";
const char16_t kUsername[] = u"test_user";
const char16_t kPassword[] = u"test_pass";
- ASSERT_FALSE(cache->Lookup(url, net::HttpAuth::AUTH_SERVER, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ ASSERT_FALSE(cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
network_isolation_key));
base::RunLoop run_loop;
network_context->AddAuthCacheEntry(challenge, network_isolation_key,
net::AuthCredentials(kUsername, kPassword),
run_loop.QuitClosure());
run_loop.Run();
- net::HttpAuthCache::Entry* entry =
- cache->Lookup(url, net::HttpAuth::AUTH_SERVER, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC, network_isolation_key);
+ net::HttpAuthCache::Entry* entry = cache->Lookup(
+ scheme_host_port, net::HttpAuth::AUTH_SERVER, challenge.realm,
+ net::HttpAuth::AUTH_SCHEME_BASIC, network_isolation_key);
ASSERT_TRUE(entry);
- EXPECT_EQ(url, entry->origin());
+ EXPECT_EQ(scheme_host_port, entry->scheme_host_port());
EXPECT_EQ(challenge.realm, entry->realm());
EXPECT_EQ(net::HttpAuth::StringToScheme(challenge.scheme), entry->scheme());
EXPECT_EQ(kUsername, entry->credentials().username());
EXPECT_EQ(kPassword, entry->credentials().password());
// Entry should only be accessibly when using the correct NetworkIsolationKey.
- EXPECT_FALSE(cache->Lookup(url, net::HttpAuth::AUTH_SERVER, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC,
+ EXPECT_FALSE(cache->Lookup(scheme_host_port, net::HttpAuth::AUTH_SERVER,
+ challenge.realm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
}
@@ -6339,11 +6469,13 @@ TEST_F(NetworkContextTest, CopyHttpAuthCacheProxyEntries) {
->GetSession()
->http_auth_cache();
// The server credentials should not have been copied.
- EXPECT_FALSE(cache->Lookup(kURL, net::HttpAuth::AUTH_SERVER, challenge.realm,
- net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey()));
+ EXPECT_FALSE(cache->Lookup(
+ challenge.challenger.GetTupleOrPrecursorTupleIfOpaque(),
+ net::HttpAuth::AUTH_SERVER, challenge.realm,
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey()));
net::HttpAuthCache::Entry* entry = cache->Lookup(
- kURL, net::HttpAuth::AUTH_PROXY, challenge.realm,
+ challenge.challenger.GetTupleOrPrecursorTupleIfOpaque(),
+ net::HttpAuth::AUTH_PROXY, challenge.realm,
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey());
ASSERT_TRUE(entry);
EXPECT_EQ(kProxyUsername, entry->credentials().username());
@@ -6404,12 +6536,14 @@ TEST_F(NetworkContextTest, SplitAuthCacheByNetworkIsolationKey) {
// The server credentials should have been deleted.
EXPECT_FALSE(cache->Lookup(
- kURL, net::HttpAuth::AUTH_SERVER, challenge.realm,
+ challenge.challenger.GetTupleOrPrecursorTupleIfOpaque(),
+ net::HttpAuth::AUTH_SERVER, challenge.realm,
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey()));
// The proxy credentials should still be in the cache.
net::HttpAuthCache::Entry* entry = cache->Lookup(
- kURL, net::HttpAuth::AUTH_PROXY, challenge.realm,
+ challenge.challenger.GetTupleOrPrecursorTupleIfOpaque(),
+ net::HttpAuth::AUTH_PROXY, challenge.realm,
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey());
ASSERT_TRUE(entry);
EXPECT_EQ(kProxyUsername, entry->credentials().username());
diff --git a/chromium/services/network/network_qualities_pref_delegate.cc b/chromium/services/network/network_qualities_pref_delegate.cc
index 331e78d50b3..c838c44db34 100644
--- a/chromium/services/network/network_qualities_pref_delegate.cc
+++ b/chromium/services/network/network_qualities_pref_delegate.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/values.h"
#include "components/prefs/pref_registry.h"
@@ -49,7 +50,7 @@ class PrefDelegateImpl
}
private:
- PrefService* pref_service_;
+ raw_ptr<PrefService> pref_service_;
// |path_| is the location of the network quality estimator prefs.
const std::string path_;
diff --git a/chromium/services/network/network_qualities_pref_delegate.h b/chromium/services/network/network_qualities_pref_delegate.h
index f60ba7406a8..5d7e71e152c 100644
--- a/chromium/services/network/network_qualities_pref_delegate.h
+++ b/chromium/services/network/network_qualities_pref_delegate.h
@@ -8,7 +8,7 @@
#include <map>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "net/nqe/cached_network_quality.h"
@@ -58,7 +58,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkQualitiesPrefDelegate {
net::NetworkQualitiesPrefsManager prefs_manager_;
// Guaranteed to be non-null during the lifetime of |this|.
- net::NetworkQualityEstimator* network_quality_estimator_;
+ raw_ptr<net::NetworkQualityEstimator> network_quality_estimator_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/services/network/network_qualities_pref_delegate_unittest.cc b/chromium/services/network/network_qualities_pref_delegate_unittest.cc
index 5e5d264fb2f..b07284cf7fb 100644
--- a/chromium/services/network/network_qualities_pref_delegate_unittest.cc
+++ b/chromium/services/network/network_qualities_pref_delegate_unittest.cc
@@ -8,7 +8,6 @@
#include <string>
#include "base/bind.h"
-#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
diff --git a/chromium/services/network/network_quality_estimator_manager.h b/chromium/services/network/network_quality_estimator_manager.h
index 28e4e9ad983..56417fff515 100644
--- a/chromium/services/network/network_quality_estimator_manager.h
+++ b/chromium/services/network/network_quality_estimator_manager.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/network_quality_estimator_manager_unittest.cc b/chromium/services/network/network_quality_estimator_manager_unittest.cc
index 5d9c36dfce3..bc9a4c0ab5c 100644
--- a/chromium/services/network/network_quality_estimator_manager_unittest.cc
+++ b/chromium/services/network/network_quality_estimator_manager_unittest.cc
@@ -8,12 +8,12 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/receiver.h"
-#include "net/log/test_net_log.h"
+#include "net/log/net_log.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator.h"
#include "services/network/public/mojom/network_quality_estimator_manager.mojom.h"
@@ -85,7 +85,7 @@ class TestNetworkQualityEstimatorManagerClient
int32_t downlink_bandwidth_kbps() const { return downlink_bandwidth_kbps_; }
private:
- NetworkQualityEstimatorManager* network_quality_estimator_manager_;
+ raw_ptr<NetworkQualityEstimatorManager> network_quality_estimator_manager_;
size_t num_network_quality_changed_;
std::unique_ptr<base::RunLoop> run_loop_;
net::EffectiveConnectionType run_loop_wait_effective_connection_type_;
@@ -101,10 +101,9 @@ class TestNetworkQualityEstimatorManagerClient
class NetworkQualityEstimatorManagerTest : public testing::Test {
public:
NetworkQualityEstimatorManagerTest()
- : net_log_(std::make_unique<net::RecordingBoundTestNetLog>()),
- network_quality_estimator_manager_(
+ : network_quality_estimator_manager_(
std::make_unique<NetworkQualityEstimatorManager>(
- net_log_->bound().net_log())) {
+ net::NetLog::Get())) {
// Change the network quality to UNKNOWN to prevent any spurious
// notifications.
SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
@@ -136,7 +135,6 @@ class NetworkQualityEstimatorManagerTest : public testing::Test {
private:
base::test::TaskEnvironment task_environment_;
- std::unique_ptr<net::RecordingBoundTestNetLog> net_log_;
std::unique_ptr<NetworkQualityEstimatorManager>
network_quality_estimator_manager_;
std::unique_ptr<TestNetworkQualityEstimatorManagerClient>
diff --git a/chromium/services/network/network_service.cc b/chromium/services/network/network_service.cc
index c326bb908f8..adfbc2ac8a1 100644
--- a/chromium/services/network/network_service.cc
+++ b/chromium/services/network/network_service.cc
@@ -16,8 +16,11 @@
#include "base/debug/dump_without_crashing.h"
#include "base/environment.h"
#include "base/feature_list.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
@@ -173,7 +176,7 @@ class NetworkServiceAuthNegotiateAndroid : public net::HttpAuthMechanism {
std::move(callback).Run(result);
}
- NetworkContext* network_context_ = nullptr;
+ raw_ptr<NetworkContext> network_context_ = nullptr;
net::android::HttpAuthNegotiateAndroid auth_negotiate_;
base::WeakPtrFactory<NetworkServiceAuthNegotiateAndroid> weak_factory_{this};
};
@@ -242,7 +245,7 @@ class NetworkService::DelayedDohProbeActivator {
}
private:
- NetworkService* const network_service_;
+ const raw_ptr<NetworkService> network_service_;
// If running, DoH probes will be started on completion. If not running, DoH
// probes may be started at any time.
@@ -780,8 +783,8 @@ void NetworkService::BindTestInterface(
}
}
-void NetworkService::SetFirstPartySets(const std::string& raw_sets) {
- first_party_sets_->ParseAndSet(raw_sets);
+void NetworkService::SetFirstPartySets(base::File sets_file) {
+ first_party_sets_->ParseAndSet(std::move(sets_file));
}
void NetworkService::SetPersistedFirstPartySetsAndGetCurrentSets(
diff --git a/chromium/services/network/network_service.h b/chromium/services/network/network_service.h
index a84874654c9..89f5cf0410d 100644
--- a/chromium/services/network/network_service.h
+++ b/chromium/services/network/network_service.h
@@ -17,7 +17,7 @@
#include "base/containers/span.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/feature_list.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -206,7 +206,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
#endif
void BindTestInterface(
mojo::PendingReceiver<mojom::NetworkServiceTest> receiver) override;
- void SetFirstPartySets(const std::string& raw_sets) override;
+ void SetFirstPartySets(base::File sets_file) override;
void SetPersistedFirstPartySetsAndGetCurrentSets(
const std::string& persisted_sets,
mojom::NetworkService::SetPersistedFirstPartySetsAndGetCurrentSetsCallback
@@ -297,9 +297,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
// context.
void OnNetworkContextConnectionClosed(NetworkContext* network_context);
+ // Sets First-Party Set data after having read it from a file.
+ void OnReadFirstPartySetsFile(const std::string& raw_sets);
+
bool initialized_ = false;
- net::NetLog* net_log_;
+ raw_ptr<net::NetLog> net_log_;
std::unique_ptr<NetLogProxySink> net_log_proxy_sink_;
@@ -318,6 +321,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
std::unique_ptr<service_manager::BinderRegistry> registry_;
+ // Globally-scoped state for First-Party Sets. Must be above the `receiver_`
+ // so it's destroyed after, to make sure even when the reply callback owned by
+ // the `first_party_sets_` is never run when destroyed, the receiver which the
+ // reply callback associated with is already disconnected.
+ std::unique_ptr<FirstPartySets> first_party_sets_;
+
mojo::Receiver<mojom::NetworkService> receiver_{this};
mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
@@ -338,9 +347,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
mojom::HttpAuthDynamicParamsPtr http_auth_dynamic_network_service_params_;
mojom::HttpAuthStaticParamsPtr http_auth_static_network_service_params_;
- // Globally-scoped state for First-Party Sets.
- std::unique_ptr<FirstPartySets> first_party_sets_;
-
// NetworkContexts created by CreateNetworkContext(). They call into the
// NetworkService when their connection is closed so that it can delete
// them. It will also delete them when the NetworkService itself is torn
diff --git a/chromium/services/network/network_service_network_delegate.h b/chromium/services/network/network_service_network_delegate.h
index b0c2f3f2edd..e43920f5ee9 100644
--- a/chromium/services/network/network_service_network_delegate.h
+++ b/chromium/services/network/network_service_network_delegate.h
@@ -6,7 +6,7 @@
#define SERVICES_NETWORK_NETWORK_SERVICE_NETWORK_DELEGATE_H_
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
@@ -115,7 +115,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceNetworkDelegate
bool enable_referrers_;
bool validate_referrer_policy_on_initial_request_;
mojo::Remote<mojom::ProxyErrorClient> proxy_error_client_;
- NetworkContext* network_context_;
+ raw_ptr<NetworkContext> network_context_;
mutable base::WeakPtrFactory<NetworkServiceNetworkDelegate> weak_ptr_factory_{
this};
diff --git a/chromium/services/network/network_service_proxy_delegate.cc b/chromium/services/network/network_service_proxy_delegate.cc
index bdc8f4e50a9..828ef10a290 100644
--- a/chromium/services/network/network_service_proxy_delegate.cc
+++ b/chromium/services/network/network_service_proxy_delegate.cc
@@ -163,9 +163,11 @@ net::Error NetworkServiceProxyDelegate::OnTunnelHeadersReceived(
}
void NetworkServiceProxyDelegate::OnCustomProxyConfigUpdated(
- mojom::CustomProxyConfigPtr proxy_config) {
+ mojom::CustomProxyConfigPtr proxy_config,
+ OnCustomProxyConfigUpdatedCallback callback) {
DCHECK(IsValidCustomProxyConfig(*proxy_config));
proxy_config_ = std::move(proxy_config);
+ std::move(callback).Run();
}
void NetworkServiceProxyDelegate::MarkProxiesAsBad(
diff --git a/chromium/services/network/network_service_proxy_delegate.h b/chromium/services/network/network_service_proxy_delegate.h
index 21cd83117c3..819192324be 100644
--- a/chromium/services/network/network_service_proxy_delegate.h
+++ b/chromium/services/network/network_service_proxy_delegate.h
@@ -8,7 +8,7 @@
#include <deque>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/proxy_delegate.h"
@@ -74,7 +74,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceProxyDelegate
// mojom::CustomProxyConfigClient implementation:
void OnCustomProxyConfigUpdated(
- mojom::CustomProxyConfigPtr proxy_config) override;
+ mojom::CustomProxyConfigPtr proxy_config,
+ OnCustomProxyConfigUpdatedCallback callback) override;
void MarkProxiesAsBad(base::TimeDelta bypass_duration,
const net::ProxyList& bad_proxies,
MarkProxiesAsBadCallback callback) override;
@@ -84,7 +85,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceProxyDelegate
mojo::Receiver<mojom::CustomProxyConfigClient> receiver_;
mojo::Remote<mojom::CustomProxyConnectionObserver> observer_;
- net::ProxyResolutionService* proxy_resolution_service_ = nullptr;
+ raw_ptr<net::ProxyResolutionService> proxy_resolution_service_ = nullptr;
};
} // namespace network
diff --git a/chromium/services/network/network_service_proxy_delegate_unittest.cc b/chromium/services/network/network_service_proxy_delegate_unittest.cc
index 6e03813410c..636848c96e0 100644
--- a/chromium/services/network/network_service_proxy_delegate_unittest.cc
+++ b/chromium/services/network/network_service_proxy_delegate_unittest.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -103,8 +104,9 @@ class NetworkServiceProxyDelegateTest : public testing::Test {
}
void SetConfig(mojom::CustomProxyConfigPtr config) {
- client_->OnCustomProxyConfigUpdated(std::move(config));
- task_environment_.RunUntilIdle();
+ base::RunLoop loop;
+ client_->OnCustomProxyConfigUpdated(std::move(config), loop.QuitClosure());
+ loop.Run();
}
void RunUntilIdle() { task_environment_.RunUntilIdle(); }
@@ -114,7 +116,7 @@ class NetworkServiceProxyDelegateTest : public testing::Test {
private:
mojo::Remote<mojom::CustomProxyConfigClient> client_;
// Owned by the proxy delegate returned by |CreateDelegate|.
- TestCustomProxyConnectionObserver* observer_ = nullptr;
+ raw_ptr<TestCustomProxyConnectionObserver> observer_ = nullptr;
std::unique_ptr<net::TestURLRequestContext> context_;
base::test::TaskEnvironment task_environment_;
};
diff --git a/chromium/services/network/network_service_unittest.cc b/chromium/services/network/network_service_unittest.cc
index 369509ad93e..083463aa958 100644
--- a/chromium/services/network/network_service_unittest.cc
+++ b/chromium/services/network/network_service_unittest.cc
@@ -1177,13 +1177,19 @@ TEST_F(NetworkServiceTestWithService, GetNetworkList) {
TEST_F(NetworkServiceTestWithService,
SetPersistedFirstPartySetsAndGetCurrentSets) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath sets_file_path(temp_dir.GetPath().AppendASCII("sets_file"));
+ ASSERT_TRUE(base::WriteFile(sets_file_path, ""));
+
base::RunLoop run_loop;
network_service_->SetPersistedFirstPartySetsAndGetCurrentSets(
"", base::BindLambdaForTesting([&](const std::string& got) {
EXPECT_EQ(got, "{}");
run_loop.Quit();
}));
- network_service_->SetFirstPartySets("");
+ network_service_->SetFirstPartySets(base::File(
+ sets_file_path, base::File::FLAG_OPEN | base::File::FLAG_READ));
run_loop.Run();
}
diff --git a/chromium/services/network/nss_temp_certs_cache_chromeos.h b/chromium/services/network/nss_temp_certs_cache_chromeos.h
index 625b4f2152e..6eedb15022a 100644
--- a/chromium/services/network/nss_temp_certs_cache_chromeos.h
+++ b/chromium/services/network/nss_temp_certs_cache_chromeos.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_NSS_TEMP_CERTS_CACHE_CHROMEOS_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "net/cert/scoped_nss_types.h"
#include "net/cert/x509_certificate.h"
diff --git a/chromium/services/network/nss_temp_certs_cache_chromeos_unittest.cc b/chromium/services/network/nss_temp_certs_cache_chromeos_unittest.cc
index d619b6185e8..b2eb193944d 100644
--- a/chromium/services/network/nss_temp_certs_cache_chromeos_unittest.cc
+++ b/chromium/services/network/nss_temp_certs_cache_chromeos_unittest.cc
@@ -13,7 +13,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parse_certificate.h"
diff --git a/chromium/services/network/origin_policy/origin_policy_fetcher.h b/chromium/services/network/origin_policy/origin_policy_fetcher.h
index 639fa062a5d..00c31e97c53 100644
--- a/chromium/services/network/origin_policy/origin_policy_fetcher.h
+++ b/chromium/services/network/origin_policy/origin_policy_fetcher.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/memory/raw_ptr.h"
#include "net/base/isolation_info.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/origin_policy_manager.mojom.h"
@@ -51,7 +52,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyFetcher {
void FetchPolicy(mojom::URLLoaderFactory* factory);
// The owner of this object. When it is destroyed, this is destroyed too.
- OriginPolicyManager* const owner_policy_manager_;
+ const raw_ptr<OriginPolicyManager> owner_policy_manager_;
// We may need the SimpleURLLoader to download the policy. The loader must
// be kept alive while the load is ongoing.
diff --git a/chromium/services/network/origin_policy/origin_policy_manager.h b/chromium/services/network/origin_policy/origin_policy_manager.h
index a2e1d585db0..723a907dfd0 100644
--- a/chromium/services/network/origin_policy/origin_policy_manager.h
+++ b/chromium/services/network/origin_policy/origin_policy_manager.h
@@ -12,7 +12,7 @@
#include "base/component_export.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -81,7 +81,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyManager
// Owner of this object. It needs to always outlive this object.
// Used for queueing reports and creating a URLLoaderFactory.
- NetworkContext* const owner_network_context_;
+ const raw_ptr<NetworkContext> owner_network_context_;
// Exempted origins are added using AddExceptionFor.
std::set<url::Origin> exempted_origins_;
diff --git a/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc b/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc
index 4377be2dc97..6b9e7cad42e 100644
--- a/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc
+++ b/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc
@@ -46,6 +46,9 @@ class OriginPolicyManagerTest : public testing::Test {
manager_ = std::make_unique<OriginPolicyManager>(network_context_.get());
}
+ OriginPolicyManagerTest(const OriginPolicyManagerTest&) = delete;
+ OriginPolicyManagerTest& operator=(const OriginPolicyManagerTest&) = delete;
+
void RetrieveOriginPolicyAndStoreResult(
const url::Origin& origin,
const absl::optional<std::string>& header) {
@@ -75,8 +78,6 @@ class OriginPolicyManagerTest : public testing::Test {
mojo::Remote<mojom::NetworkContext> network_context_remote_;
std::unique_ptr<OriginPolicyManager> manager_;
std::unique_ptr<OriginPolicy> result_;
-
- DISALLOW_COPY_AND_ASSIGN(OriginPolicyManagerTest);
};
TEST_F(OriginPolicyManagerTest, AddReceiver) {
diff --git a/chromium/services/network/origin_policy/origin_policy_parser.h b/chromium/services/network/origin_policy/origin_policy_parser.h
index 8588efe888e..f98e824bddc 100644
--- a/chromium/services/network/origin_policy/origin_policy_parser.h
+++ b/chromium/services/network/origin_policy/origin_policy_parser.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
#include "services/network/public/cpp/origin_policy.h"
namespace base {
@@ -21,6 +20,9 @@ namespace network {
// https://wicg.github.io/origin-policy/#parsing
class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyParser {
public:
+ OriginPolicyParser(const OriginPolicyParser&) = delete;
+ OriginPolicyParser& operator=(const OriginPolicyParser&) = delete;
+
// Parse the given origin policy. Returns an empty policy if parsing is not
// successful.
static OriginPolicyContentsPtr Parse(base::StringPiece);
@@ -42,8 +44,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyParser {
static bool IsValidOriginPolicyId(const std::string&);
OriginPolicyContentsPtr policy_contents_;
-
- DISALLOW_COPY_AND_ASSIGN(OriginPolicyParser);
};
} // namespace network
diff --git a/chromium/services/network/p2p/socket.h b/chromium/services/network/p2p/socket.h
index 63a42ac6b29..61b13bb4b64 100644
--- a/chromium/services/network/p2p/socket.h
+++ b/chromium/services/network/p2p/socket.h
@@ -12,7 +12,7 @@
#include "base/component_export.h"
#include "base/containers/span.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -69,6 +69,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocket : public mojom::P2PSocket {
ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory,
P2PMessageThrottler* throttler);
+ P2PSocket(const P2PSocket&) = delete;
+ P2PSocket& operator=(const P2PSocket&) = delete;
+
~P2PSocket() override;
// Initializes the socket. Returns false when initialization fails.
@@ -153,7 +156,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocket : public mojom::P2PSocket {
void IncrementDelayedBytes(uint32_t size);
void DecrementDelayedBytes(uint32_t size);
- Delegate* delegate_;
+ raw_ptr<Delegate> delegate_;
mojo::Remote<mojom::P2PSocketClient> client_;
mojo::Receiver<mojom::P2PSocket> receiver_;
@@ -171,8 +174,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocket : public mojom::P2PSocket {
int32_t send_bytes_delayed_cur_ = 0;
base::WeakPtrFactory<P2PSocket> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocket);
};
} // namespace network
diff --git a/chromium/services/network/p2p/socket_manager.cc b/chromium/services/network/p2p/socket_manager.cc
index 05f3c8c4eb4..10181a9af70 100644
--- a/chromium/services/network/p2p/socket_manager.cc
+++ b/chromium/services/network/p2p/socket_manager.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -138,7 +139,7 @@ class P2PSocketManager::DnsRequest {
}
std::string host_name_;
- net::HostResolver* resolver_;
+ raw_ptr<net::HostResolver> resolver_;
std::unique_ptr<net::HostResolver::ResolveHostRequest> request_;
DoneCallback done_callback_;
diff --git a/chromium/services/network/p2p/socket_manager.h b/chromium/services/network/p2p/socket_manager.h
index 764070ccdae..8221534efc0 100644
--- a/chromium/services/network/p2p/socket_manager.h
+++ b/chromium/services/network/p2p/socket_manager.h
@@ -15,10 +15,10 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -126,7 +126,7 @@ class P2PSocketManager
void OnConnectionError();
DeleteCallback delete_callback_;
- net::URLRequestContext* url_request_context_;
+ raw_ptr<net::URLRequestContext> url_request_context_;
const net::NetworkIsolationKey network_isolation_key_;
std::unique_ptr<ProxyResolvingClientSocketFactory>
diff --git a/chromium/services/network/p2p/socket_tcp.h b/chromium/services/network/p2p/socket_tcp.h
index 7398804610e..a98a93e2a12 100644
--- a/chromium/services/network/p2p/socket_tcp.h
+++ b/chromium/services/network/p2p/socket_tcp.h
@@ -13,7 +13,7 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/queue.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -121,7 +121,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocketTcpBase : public P2PSocket {
bool connected_ = false;
const P2PSocketType type_;
- ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory_;
+ raw_ptr<ProxyResolvingClientSocketFactory> proxy_resolving_socket_factory_;
};
class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocketTcp : public P2PSocketTcpBase {
diff --git a/chromium/services/network/p2p/socket_tcp_unittest.cc b/chromium/services/network/p2p/socket_tcp_unittest.cc
index edcecb6e293..d6b7663393e 100644
--- a/chromium/services/network/p2p/socket_tcp_unittest.cc
+++ b/chromium/services/network/p2p/socket_tcp_unittest.cc
@@ -10,6 +10,7 @@
#include <memory>
#include "base/cxx17_backports.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
@@ -85,7 +86,7 @@ class P2PSocketTcpTestBase : public testing::Test {
base::test::TaskEnvironment task_environment_;
std::string sent_data_;
- FakeSocket* socket_; // Owned by |socket_impl_|.
+ raw_ptr<FakeSocket> socket_; // Owned by |socket_impl_|.
std::unique_ptr<P2PSocketTcpBase> socket_impl_;
FakeP2PSocketDelegate socket_delegate_;
std::unique_ptr<FakeSocketClient> fake_client_;
diff --git a/chromium/services/network/p2p/socket_test_utils.h b/chromium/services/network/p2p/socket_test_utils.h
index 8799f4f7169..2466c71c067 100644
--- a/chromium/services/network/p2p/socket_test_utils.h
+++ b/chromium/services/network/p2p/socket_test_utils.h
@@ -7,10 +7,13 @@
#include <stdint.h>
+#include <list>
+#include <memory>
#include <string>
#include <tuple>
#include <vector>
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -106,7 +109,7 @@ class FakeSocket : public net::StreamSocket {
std::string input_data_;
int input_pos_;
- std::string* written_data_;
+ raw_ptr<std::string> written_data_;
bool async_write_;
bool write_pending_;
diff --git a/chromium/services/network/p2p/socket_throttler.h b/chromium/services/network/p2p/socket_throttler.h
index a41d585726b..fa3bdd6b597 100644
--- a/chromium/services/network/p2p/socket_throttler.h
+++ b/chromium/services/network/p2p/socket_throttler.h
@@ -10,7 +10,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
namespace rtc {
class DataRateLimiter;
diff --git a/chromium/services/network/p2p/socket_udp.cc b/chromium/services/network/p2p/socket_udp.cc
index 9e262b049e1..6db686ee658 100644
--- a/chromium/services/network/p2p/socket_udp.cc
+++ b/chromium/services/network/p2p/socket_udp.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/containers/contains.h"
+#include "base/ignore_result.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
@@ -135,7 +136,7 @@ void P2PSocketUdp::Init(const net::IPEndPoint& local_address,
DCHECK((min_port == 0 && max_port == 0) || min_port > 0);
DCHECK_LE(min_port, max_port);
- socket_ = socket_factory_.Run(net_log_);
+ socket_ = socket_factory_.Run(net_log_.get());
int result = -1;
if (min_port == 0) {
@@ -144,7 +145,7 @@ void P2PSocketUdp::Init(const net::IPEndPoint& local_address,
for (unsigned port = min_port; port <= max_port && result < 0; ++port) {
result = socket_->Listen(net::IPEndPoint(local_address.address(), port));
if (result < 0 && port != max_port)
- socket_ = socket_factory_.Run(net_log_);
+ socket_ = socket_factory_.Run(net_log_.get());
}
} else if (local_address.port() >= min_port &&
local_address.port() <= max_port) {
diff --git a/chromium/services/network/p2p/socket_udp.h b/chromium/services/network/p2p/socket_udp.h
index 9233898a5d9..b0944937acb 100644
--- a/chromium/services/network/p2p/socket_udp.h
+++ b/chromium/services/network/p2p/socket_udp.h
@@ -16,7 +16,7 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/circular_deque.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -123,9 +123,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocketUdp : public P2PSocket {
// Set of peer for which we have received STUN binding request or
// response or relay allocation request or response.
ConnectedPeerSet connected_peers_;
- P2PMessageThrottler* throttler_;
+ raw_ptr<P2PMessageThrottler> throttler_;
- net::NetLog* net_log_;
+ raw_ptr<net::NetLog> net_log_;
// Callback object that returns a new socket when invoked.
DatagramServerSocketFactory socket_factory_;
diff --git a/chromium/services/network/p2p/socket_udp_unittest.cc b/chromium/services/network/p2p/socket_udp_unittest.cc
index c815d53eef0..c2cd84ccda3 100644
--- a/chromium/services/network/p2p/socket_udp_unittest.cc
+++ b/chromium/services/network/p2p/socket_udp_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/containers/circular_deque.h"
+#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/sys_byteorder.h"
@@ -51,7 +52,7 @@ class ScopedFakeClock : public rtc::ClockInterface {
void SetTimeNanos(uint64_t time_nanos) { time_nanos_ = time_nanos; }
private:
- ClockInterface* prev_clock_;
+ raw_ptr<ClockInterface> prev_clock_;
uint64_t time_nanos_ = 0;
};
@@ -189,15 +190,15 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
private:
net::IPEndPoint address_;
- base::circular_deque<UDPPacket>* sent_packets_;
+ raw_ptr<base::circular_deque<UDPPacket>> sent_packets_;
base::circular_deque<UDPPacket> incoming_packets_;
net::NetLogWithSource net_log_;
scoped_refptr<net::IOBuffer> recv_buffer_;
- net::IPEndPoint* recv_address_;
+ raw_ptr<net::IPEndPoint> recv_address_;
int recv_size_;
net::CompletionOnceCallback recv_callback_;
- std::vector<uint16_t>* used_ports_;
+ raw_ptr<std::vector<uint16_t>> used_ports_;
};
std::unique_ptr<net::DatagramServerSocket> CreateFakeDatagramServerSocket(
@@ -251,7 +252,7 @@ class P2PSocketUdpTest : public testing::Test {
P2PMessageThrottler throttler_;
ScopedFakeClock fake_clock_;
base::circular_deque<FakeDatagramServerSocket::UDPPacket> sent_packets_;
- FakeDatagramServerSocket* socket_; // Owned by |socket_impl_|.
+ raw_ptr<FakeDatagramServerSocket> socket_; // Owned by |socket_impl_|.
FakeP2PSocketDelegate socket_delegate_;
std::unique_ptr<P2PSocketUdp> socket_impl_;
std::unique_ptr<FakeSocketClient> fake_client_;
diff --git a/chromium/services/network/proxy_auto_config_library.cc b/chromium/services/network/proxy_auto_config_library.cc
index 74a0cc42abe..e2afd2535b0 100644
--- a/chromium/services/network/proxy_auto_config_library.cc
+++ b/chromium/services/network/proxy_auto_config_library.cc
@@ -4,6 +4,9 @@
#include "services/network/proxy_auto_config_library.h"
+#include <set>
+
+#include "base/memory/raw_ptr.h"
#include "net/base/address_list.h"
#include "net/base/ip_address.h"
#include "net/base/network_interfaces.h"
@@ -47,6 +50,9 @@ class MyIpAddressImpl {
public:
MyIpAddressImpl() = default;
+ MyIpAddressImpl(const MyIpAddressImpl&) = delete;
+ MyIpAddressImpl& operator=(const MyIpAddressImpl&) = delete;
+
// Used for mocking the socket dependency.
void SetSocketFactoryForTest(net::ClientSocketFactory* socket_factory) {
override_socket_factory_ = socket_factory;
@@ -139,7 +145,7 @@ class MyIpAddressImpl {
net::ClientSocketFactory* socket_factory =
override_socket_factory_
- ? override_socket_factory_
+ ? override_socket_factory_.get()
: net::ClientSocketFactory::GetDefaultFactory();
auto socket = socket_factory->CreateDatagramClientSocket(
@@ -256,10 +262,8 @@ class MyIpAddressImpl {
// to short-circuit early.
bool done_ = false;
- net::ClientSocketFactory* override_socket_factory_ = nullptr;
+ raw_ptr<net::ClientSocketFactory> override_socket_factory_ = nullptr;
std::unique_ptr<net::AddressList> override_dns_result_;
-
- DISALLOW_COPY_AND_ASSIGN(MyIpAddressImpl);
};
} // namespace
diff --git a/chromium/services/network/proxy_config_service_mojo.h b/chromium/services/network/proxy_config_service_mojo.h
index de0c365513c..03ee69f860c 100644
--- a/chromium/services/network/proxy_config_service_mojo.h
+++ b/chromium/services/network/proxy_config_service_mojo.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_PROXY_CONFIG_SERVICE_MOJO_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/observer_list.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/proxy_config_service_mojo_unittest.cc b/chromium/services/network/proxy_config_service_mojo_unittest.cc
index 089df904bb4..70752d973d8 100644
--- a/chromium/services/network/proxy_config_service_mojo_unittest.cc
+++ b/chromium/services/network/proxy_config_service_mojo_unittest.cc
@@ -4,7 +4,7 @@
#include "services/network/proxy_config_service_mojo.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/test/task_environment.h"
#include "net/proxy_resolution/proxy_config.h"
#include "net/proxy_resolution/proxy_config_service.h"
@@ -62,7 +62,7 @@ class TestProxyConfigServiceObserver
private:
net::ProxyConfigWithAnnotation observed_config_;
- net::ProxyConfigService* const service_;
+ const raw_ptr<net::ProxyConfigService> service_;
int config_changes_ = 0;
};
diff --git a/chromium/services/network/proxy_lookup_request.h b/chromium/services/network/proxy_lookup_request.h
index 4abf9a5f92a..91a8a912a68 100644
--- a/chromium/services/network/proxy_lookup_request.h
+++ b/chromium/services/network/proxy_lookup_request.h
@@ -10,7 +10,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/network_isolation_key.h"
@@ -54,7 +54,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyLookupRequest {
// Cancels |request_| and tells |network_context_| to delete |this|.
void DestroySelf();
- NetworkContext* const network_context_;
+ const raw_ptr<NetworkContext> network_context_;
const net::NetworkIsolationKey network_isolation_key_;
mojo::Remote<mojom::ProxyLookupClient> proxy_lookup_client_;
diff --git a/chromium/services/network/proxy_resolver_factory_mojo.cc b/chromium/services/network/proxy_resolver_factory_mojo.cc
index 2672a3fc97a..d4d618212e0 100644
--- a/chromium/services/network/proxy_resolver_factory_mojo.cc
+++ b/chromium/services/network/proxy_resolver_factory_mojo.cc
@@ -12,12 +12,12 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/task_runner.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner.h"
#include "base/values.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -162,8 +162,8 @@ class ClientMixin : public ClientInterface {
private:
MojoHostResolverImpl host_resolver_;
- net::ProxyResolverErrorObserver* const error_observer_;
- net::NetLog* const net_log_;
+ const raw_ptr<net::ProxyResolverErrorObserver> error_observer_;
+ const raw_ptr<net::NetLog> net_log_;
const net::NetLogWithSource net_log_with_source_;
};
@@ -211,11 +211,11 @@ class ProxyResolverMojo : public net::ProxyResolver {
mojo::Remote<proxy_resolver::mojom::ProxyResolver>
mojo_proxy_resolver_remote_;
- net::HostResolver* host_resolver_;
+ raw_ptr<net::HostResolver> host_resolver_;
std::unique_ptr<net::ProxyResolverErrorObserver> error_observer_;
- net::NetLog* net_log_;
+ raw_ptr<net::NetLog> net_log_;
};
class ProxyResolverMojo::Job
@@ -248,7 +248,7 @@ class ProxyResolverMojo::Job
void CompleteRequest(int result);
const GURL url_;
- net::ProxyInfo* results_;
+ raw_ptr<net::ProxyInfo> results_;
net::CompletionOnceCallback callback_;
SEQUENCE_CHECKER(sequence_checker_);
@@ -404,8 +404,8 @@ class ProxyResolverFactoryMojo::Job
std::move(callback_).Run(error);
}
- ProxyResolverFactoryMojo* const factory_;
- std::unique_ptr<net::ProxyResolver>* resolver_;
+ const raw_ptr<ProxyResolverFactoryMojo> factory_;
+ raw_ptr<std::unique_ptr<net::ProxyResolver>> resolver_;
net::CompletionOnceCallback callback_;
mojo::PendingRemote<proxy_resolver::mojom::ProxyResolver> resolver_remote_;
mojo::Receiver<proxy_resolver::mojom::ProxyResolverFactoryRequestClient>
diff --git a/chromium/services/network/proxy_resolver_factory_mojo.h b/chromium/services/network/proxy_resolver_factory_mojo.h
index 08680c0baca..d77369502d8 100644
--- a/chromium/services/network/proxy_resolver_factory_mojo.h
+++ b/chromium/services/network/proxy_resolver_factory_mojo.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -55,11 +55,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolverFactoryMojo
class Job;
mojo::Remote<proxy_resolver::mojom::ProxyResolverFactory> mojo_proxy_factory_;
- net::HostResolver* const host_resolver_;
+ const raw_ptr<net::HostResolver> host_resolver_;
const base::RepeatingCallback<
std::unique_ptr<net::ProxyResolverErrorObserver>()>
error_observer_factory_;
- net::NetLog* const net_log_;
+ const raw_ptr<net::NetLog> net_log_;
base::WeakPtrFactory<ProxyResolverFactoryMojo> weak_ptr_factory_{this};
};
diff --git a/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc b/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc
index 6f900e1fdbb..3247b2d6df6 100644
--- a/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc
+++ b/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc
@@ -14,6 +14,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/queue.h"
+#include "base/ignore_result.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/values.h"
@@ -24,6 +26,7 @@
#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
@@ -308,18 +311,19 @@ class Request {
const net::ProxyInfo& results() const { return results_; }
net::LoadState load_state() { return request_->GetLoadState(); }
- net::RecordingBoundTestNetLog& net_log() { return net_log_; }
+ net::NetLogWithSource& net_log_with_source() { return net_log_with_source_; }
const net::TestCompletionCallback& callback() const { return callback_; }
private:
- net::ProxyResolver* resolver_;
+ raw_ptr<net::ProxyResolver> resolver_;
const GURL url_;
const net::NetworkIsolationKey network_isolation_key_;
net::ProxyInfo results_;
std::unique_ptr<net::ProxyResolver::Request> request_;
int error_;
net::TestCompletionCallback callback_;
- net::RecordingBoundTestNetLog net_log_;
+ net::NetLogWithSource net_log_with_source_{
+ net::NetLogWithSource::Make(net::NetLogSourceType::NONE)};
};
Request::Request(net::ProxyResolver* resolver,
@@ -333,7 +337,7 @@ Request::Request(net::ProxyResolver* resolver,
int Request::Resolve() {
error_ = resolver_->GetProxyForURL(url_, network_isolation_key_, &results_,
callback_.callback(), &request_,
- net_log_.bound());
+ net_log_with_source_);
return error_;
}
@@ -374,7 +378,7 @@ class MockMojoProxyResolverFactory
void WakeWaiter();
- MockMojoProxyResolver* resolver_;
+ raw_ptr<MockMojoProxyResolver> resolver_;
base::queue<CreateProxyResolverAction> create_resolver_actions_;
base::OnceClosure quit_closure_;
@@ -517,7 +521,7 @@ class ProxyResolverFactoryMojoTest : public testing::Test {
factory_remote.InitWithNewPipeAndPassReceiver());
proxy_resolver_factory_mojo_ = std::make_unique<ProxyResolverFactoryMojo>(
std::move(factory_remote), &host_resolver_, base::NullCallback(),
- &net_log_);
+ net::NetLog::Get());
}
std::unique_ptr<Request> MakeRequest(
@@ -557,7 +561,7 @@ class ProxyResolverFactoryMojoTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
net::HangingHostResolver host_resolver_;
- net::RecordingTestNetLog net_log_;
+ net::RecordingNetLogObserver net_log_observer_;
std::unique_ptr<MockMojoProxyResolverFactory> mock_proxy_resolver_factory_;
std::unique_ptr<net::ProxyResolverFactory> proxy_resolver_factory_mojo_;
@@ -567,7 +571,7 @@ class ProxyResolverFactoryMojoTest : public testing::Test {
TEST_F(ProxyResolverFactoryMojoTest, CreateProxyResolver) {
CreateProxyResolver();
- CheckCapturedNetLogEntries(kScriptData, net_log_.GetEntries());
+ CheckCapturedNetLogEntries(kScriptData, net_log_observer_.GetEntries());
}
TEST_F(ProxyResolverFactoryMojoTest, CreateProxyResolver_Empty) {
@@ -775,16 +779,16 @@ TEST_F(ProxyResolverFactoryMojoTest, GetProxyForURL) {
mock_proxy_resolver_.AddGetProxyAction(GetProxyForUrlAction::ReturnServers(
url, ProxyServersFromPacString("DIRECT")));
CreateProxyResolver();
- net_log_.Clear();
+ net_log_observer_.Clear();
std::unique_ptr<Request> request(MakeRequest(GURL(kExampleUrl)));
EXPECT_THAT(request->Resolve(), IsError(net::ERR_IO_PENDING));
EXPECT_THAT(request->WaitForResult(), IsOk());
EXPECT_EQ("DIRECT", request->results().ToPacString());
-
- CheckCapturedNetLogEntries(url.spec(), net_log_.GetEntries());
- CheckCapturedNetLogEntries(url.spec(), request->net_log().GetEntries());
+ CheckCapturedNetLogEntries(url.spec(),
+ net_log_observer_.GetEntriesForSource(
+ request->net_log_with_source().source()));
}
TEST_F(ProxyResolverFactoryMojoTest, GetProxyForURL_MultipleResults) {
diff --git a/chromium/services/network/proxy_resolving_client_socket.h b/chromium/services/network/proxy_resolving_client_socket.h
index dca35f38e9e..13563db20b4 100644
--- a/chromium/services/network/proxy_resolving_client_socket.h
+++ b/chromium/services/network/proxy_resolving_client_socket.h
@@ -12,7 +12,7 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "net/base/host_port_pair.h"
@@ -133,10 +133,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocket
int ReconsiderProxyAfterError(int error);
- net::HttpNetworkSession* network_session_;
+ raw_ptr<net::HttpNetworkSession> network_session_;
- const net::CommonConnectJobParams* common_connect_job_params_;
- const net::ConnectJobFactory* connect_job_factory_;
+ raw_ptr<const net::CommonConnectJobParams> common_connect_job_params_;
+ raw_ptr<const net::ConnectJobFactory> connect_job_factory_;
std::unique_ptr<net::ConnectJob> connect_job_;
std::unique_ptr<net::StreamSocket> socket_;
diff --git a/chromium/services/network/proxy_resolving_client_socket_factory.h b/chromium/services/network/proxy_resolving_client_socket_factory.h
index 9f9ee6a49b6..e8af2710b13 100644
--- a/chromium/services/network/proxy_resolving_client_socket_factory.h
+++ b/chromium/services/network/proxy_resolving_client_socket_factory.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "net/socket/connect_job_factory.h"
#include "net/ssl/ssl_config.h"
@@ -63,7 +63,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocketFactory {
private:
std::unique_ptr<net::HttpNetworkSession> network_session_;
std::unique_ptr<net::CommonConnectJobParams> common_connect_job_params_;
- net::URLRequestContext* request_context_;
+ raw_ptr<net::URLRequestContext> request_context_;
std::unique_ptr<net::ConnectJobFactory> connect_job_factory_ =
std::make_unique<net::ConnectJobFactory>();
};
diff --git a/chromium/services/network/proxy_resolving_client_socket_unittest.cc b/chromium/services/network/proxy_resolving_client_socket_unittest.cc
index e5ea85d3158..2112c1c0a89 100644
--- a/chromium/services/network/proxy_resolving_client_socket_unittest.cc
+++ b/chromium/services/network/proxy_resolving_client_socket_unittest.cc
@@ -9,7 +9,6 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -34,6 +33,8 @@
#include "net/url_request/url_request_test_util.h"
#include "services/network/proxy_resolving_client_socket_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
namespace network {
@@ -48,8 +49,10 @@ class TestURLRequestContextWithProxy : public net::TestURLRequestContext {
context_storage_.set_proxy_resolution_service(
net::ConfiguredProxyResolutionService::CreateFixedFromPacResult(
pac_result, TRAFFIC_ANNOTATION_FOR_TESTS));
- // net::MockHostResolver maps all hosts to localhost.
- auto host_resolver = std::make_unique<net::MockCachingHostResolver>();
+ auto host_resolver = std::make_unique<net::MockCachingHostResolver>(
+ /*cache_invalidation_num=*/0,
+ /*default_result=*/net::MockHostResolverBase::RuleResolver::
+ GetLocalhostResult());
context_storage_.set_host_resolver(std::move(host_resolver));
set_client_socket_factory(client_socket_factory);
Init();
@@ -665,14 +668,16 @@ TEST_P(ProxyResolvingClientSocketTest, MultiroundAuth) {
->GetSession()
->http_auth_cache();
- auth_cache->Add(GURL("http://bad:99"), net::HttpAuth::AUTH_PROXY,
- "test_realm", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey(), "Basic realm=\"test_realm\"",
+ auth_cache->Add(url::SchemeHostPort(GURL("http://bad:99")),
+ net::HttpAuth::AUTH_PROXY, "test_realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "Basic realm=\"test_realm\"",
net::AuthCredentials(u"user", u"password"), std::string());
- auth_cache->Add(GURL("http://bad:99"), net::HttpAuth::AUTH_PROXY,
- "test_realm2", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey(), "Basic realm=\"test_realm2\"",
+ auth_cache->Add(url::SchemeHostPort(GURL("http://bad:99")),
+ net::HttpAuth::AUTH_PROXY, "test_realm2",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "Basic realm=\"test_realm2\"",
net::AuthCredentials(u"user2", u"password2"), std::string());
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
@@ -726,9 +731,10 @@ TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) {
// We are adding these credentials at an empty path so that it won't be picked
// up by the preemptive authentication step and will only be picked up via
// origin + realm + scheme lookup.
- auth_cache->Add(GURL("http://bad:99"), net::HttpAuth::AUTH_PROXY,
- "test_realm", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey(), "Basic realm=\"test_realm\"",
+ auth_cache->Add(url::SchemeHostPort(GURL("http://bad:99")),
+ net::HttpAuth::AUTH_PROXY, "test_realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "Basic realm=\"test_realm\"",
net::AuthCredentials(u"user", u"password"), std::string());
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
@@ -759,9 +765,10 @@ TEST_P(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) {
// We are adding these credentials at an empty path so that it won't be picked
// up by the preemptive authentication step and will only be picked up via
// origin + realm + scheme lookup.
- auth_cache->Add(GURL("http://bad:99"), net::HttpAuth::AUTH_PROXY,
- "test_realm", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey(), "Basic realm=\"test_realm\"",
+ auth_cache->Add(url::SchemeHostPort(GURL("http://bad:99")),
+ net::HttpAuth::AUTH_PROXY, "test_realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "Basic realm=\"test_realm\"",
net::AuthCredentials(u"user", u"password"), std::string());
const GURL kDestination("https://example.com:443");
@@ -822,9 +829,10 @@ TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) {
->GetSession()
->http_auth_cache();
- auth_cache->Add(GURL("http://bad:99"), net::HttpAuth::AUTH_PROXY,
- "test_realm", net::HttpAuth::AUTH_SCHEME_BASIC,
- net::NetworkIsolationKey(), "Basic realm=\"test_realm\"",
+ auth_cache->Add(url::SchemeHostPort(GURL("http://bad:99")),
+ net::HttpAuth::AUTH_PROXY, "test_realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "Basic realm=\"test_realm\"",
net::AuthCredentials(u"user", u"password"), "/");
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
diff --git a/chromium/services/network/proxy_resolving_socket_factory_mojo.h b/chromium/services/network/proxy_resolving_socket_factory_mojo.h
index 63e3953e842..978b503cb4d 100644
--- a/chromium/services/network/proxy_resolving_socket_factory_mojo.h
+++ b/chromium/services/network/proxy_resolving_socket_factory_mojo.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_PROXY_RESOLVING_SOCKET_FACTORY_MOJO_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/proxy_resolving_socket_mojo.h b/chromium/services/network/proxy_resolving_socket_mojo.h
index aa543c79aa5..8e49fed0b97 100644
--- a/chromium/services/network/proxy_resolving_socket_mojo.h
+++ b/chromium/services/network/proxy_resolving_socket_mojo.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -63,7 +63,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingSocketMojo
std::unique_ptr<net::StreamSocket> TakeSocket() override;
mojo::Remote<mojom::SocketObserver> observer_;
- TLSSocketFactory* tls_socket_factory_;
+ raw_ptr<TLSSocketFactory> tls_socket_factory_;
std::unique_ptr<net::StreamSocket> socket_;
const net::NetworkTrafficAnnotationTag traffic_annotation_;
mojom::ProxyResolvingSocketFactory::CreateProxyResolvingSocketCallback
diff --git a/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc b/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc
index f314357e831..7bfdf53a055 100644
--- a/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc
+++ b/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc
@@ -7,7 +7,6 @@
#include <vector>
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
@@ -45,8 +44,9 @@ class TestURLRequestContextWithProxy : public net::TestURLRequestContext {
context_storage_.set_proxy_resolution_service(
net::ConfiguredProxyResolutionService::CreateFixedFromPacResult(
pac_result, TRAFFIC_ANNOTATION_FOR_TESTS));
- // net::MockHostResolver maps all hosts to localhost.
- auto host_resolver = std::make_unique<net::MockHostResolver>();
+ auto host_resolver = std::make_unique<net::MockHostResolver>(
+ /*default_result=*/net::MockHostResolverBase::RuleResolver::
+ GetLocalhostResult());
context_storage_.set_host_resolver(std::move(host_resolver));
}
diff --git a/chromium/services/network/proxy_service_mojo_unittest.cc b/chromium/services/network/proxy_service_mojo_unittest.cc
index 25b3bc9b846..7b725e52951 100644
--- a/chromium/services/network/proxy_service_mojo_unittest.cc
+++ b/chromium/services/network/proxy_service_mojo_unittest.cc
@@ -11,6 +11,7 @@
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
#include "base/values.h"
@@ -20,6 +21,7 @@
#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
@@ -125,10 +127,10 @@ class ProxyServiceMojoTest : public testing::Test {
net::ProxyConfigWithAnnotation(
net::ProxyConfig::CreateFromCustomPacURL(GURL(kPacUrl)),
TRAFFIC_ANNOTATION_FOR_TESTS)),
- base::WrapUnique(fetcher_),
+ base::WrapUnique(fetcher_.get()),
std::make_unique<net::DoNothingDhcpPacFileFetcher>(),
- &mock_host_resolver_, &net_log_, true /* pac_quick_check_enabled */,
- &network_delegate_);
+ &mock_host_resolver_, net::NetLog::Get(),
+ true /* pac_quick_check_enabled */, &network_delegate_);
}
base::test::TaskEnvironment task_environment_;
@@ -136,8 +138,8 @@ class ProxyServiceMojoTest : public testing::Test {
TestNetworkDelegate network_delegate_;
net::MockHostResolver mock_host_resolver_;
// Owned by |proxy_resolution_service_|.
- net::MockPacFileFetcher* fetcher_;
- net::RecordingTestNetLog net_log_;
+ raw_ptr<net::MockPacFileFetcher> fetcher_;
+ net::RecordingNetLogObserver net_log_observer_;
std::unique_ptr<net::ConfiguredProxyResolutionService>
proxy_resolution_service_;
};
@@ -188,12 +190,13 @@ TEST_F(ProxyServiceMojoTest, DnsResolution) {
TEST_F(ProxyServiceMojoTest, Error) {
net::ProxyInfo info;
net::TestCompletionCallback callback;
- net::RecordingBoundTestNetLog test_net_log;
+ net::NetLogWithSource net_log_with_source =
+ net::NetLogWithSource::Make(net::NetLogSourceType::NONE);
std::unique_ptr<net::ProxyResolutionRequest> request;
EXPECT_EQ(net::ERR_IO_PENDING,
proxy_resolution_service_->ResolveProxy(
GURL("http://foo"), std::string(), net::NetworkIsolationKey(),
- &info, callback.callback(), &request, test_net_log.bound()));
+ &info, callback.callback(), &request, net_log_with_source));
// PAC file fetcher should have a fetch triggered by the first
// |ResolveProxy()| request.
@@ -207,9 +210,9 @@ TEST_F(ProxyServiceMojoTest, Error) {
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ("DIRECT", info.ToPacString());
EXPECT_EQ(0u, mock_host_resolver_.num_resolve());
-
- CheckCapturedNetLogEntries(test_net_log.GetEntries());
- CheckCapturedNetLogEntries(net_log_.GetEntries());
+ CheckCapturedNetLogEntries(
+ net_log_observer_.GetEntriesForSource(net_log_with_source.source()));
+ CheckCapturedNetLogEntries(net_log_observer_.GetEntries());
}
TEST_F(ProxyServiceMojoTest, ErrorOnInitialization) {
@@ -234,7 +237,7 @@ TEST_F(ProxyServiceMojoTest, ErrorOnInitialization) {
EXPECT_EQ("DIRECT", info.ToPacString());
EXPECT_EQ(0u, mock_host_resolver_.num_resolve());
- CheckCapturedNetLogEntries(net_log_.GetEntries());
+ CheckCapturedNetLogEntries(net_log_observer_.GetEntries());
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/BUILD.gn b/chromium/services/network/public/cpp/BUILD.gn
index ff1427034dd..33c082b1df7 100644
--- a/chromium/services/network/public/cpp/BUILD.gn
+++ b/chromium/services/network/public/cpp/BUILD.gn
@@ -9,7 +9,10 @@ import("//testing/libfuzzer/fuzzer_test.gni")
buildflag_header("buildflags") {
header = "network_service_buildflags.h"
- flags = [ "IS_CT_SUPPORTED=$is_ct_supported" ]
+ flags = [
+ "IS_CT_SUPPORTED=$is_ct_supported",
+ "IS_P2P_ENABLED=$is_p2p_enabled",
+ ]
}
component("crash_keys") {
@@ -221,6 +224,23 @@ component("network_param_mojom_support") {
defines = [ "IS_NETWORK_CPP_NETWORK_PARAM_IMPL" ]
}
+component("proxy_config_mojom_support") {
+ sources = [
+ "mutable_network_traffic_annotation_tag_mojom_traits.h",
+ "mutable_partial_network_traffic_annotation_tag_mojom_traits.h",
+ "proxy_config_mojom_traits.cc",
+ "proxy_config_mojom_traits.h",
+ "proxy_config_with_annotation_mojom_traits.cc",
+ "proxy_config_with_annotation_mojom_traits.h",
+ ]
+ deps = [
+ "//mojo/public/mojom/base",
+ "//net",
+ "//services/network/public/mojom:mojom_proxy_config_shared",
+ ]
+ defines = [ "IS_NETWORK_CPP_PROXY_CONFIG_IMPL" ]
+}
+
# This component is separate from cpp_base as it is a dependency of
# //services/network/public/mojom:url_loader_base.
component("cross_origin_embedder_policy") {
@@ -277,8 +297,6 @@ component("cpp_base") {
"isolation_info_mojom_traits.h",
"load_timing_info_mojom_traits.cc",
"load_timing_info_mojom_traits.h",
- "mutable_network_traffic_annotation_tag_mojom_traits.h",
- "mutable_partial_network_traffic_annotation_tag_mojom_traits.h",
"network_interface_mojom_traits.cc",
"network_interface_mojom_traits.h",
"network_ipc_param_traits.cc",
@@ -289,13 +307,6 @@ component("cpp_base") {
"optional_trust_token_params.h",
"origin_policy.cc",
"origin_policy.h",
- "p2p_param_traits.cc",
- "p2p_param_traits.h",
- "p2p_socket_type.h",
- "proxy_config_mojom_traits.cc",
- "proxy_config_mojom_traits.h",
- "proxy_config_with_annotation_mojom_traits.cc",
- "proxy_config_with_annotation_mojom_traits.h",
"resource_request.cc",
"resource_request.h",
"resource_request_body.cc",
@@ -321,9 +332,9 @@ component("cpp_base") {
":cross_origin_embedder_policy",
":ip_address_mojom_support",
":network_param_mojom_support",
+ ":proxy_config_mojom_support",
":schemeful_site_mojom_support",
"//services/network/public/mojom:url_loader_base",
- "//third_party/webrtc_overrides:webrtc_component",
"//url/ipc:url_ipc",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
@@ -338,6 +349,16 @@ component("cpp_base") {
]
defines = [ "IS_NETWORK_CPP_BASE_IMPL" ]
+ if (is_p2p_enabled) {
+ sources += [
+ "p2p_param_traits.cc",
+ "p2p_param_traits.h",
+ "p2p_socket_type.h",
+ ]
+
+ public_deps += [ "//third_party/webrtc_overrides:webrtc_component" ]
+ }
+
# Since URLLoader is typedmapped in mojo and the class also uses the mojo
# interfaces a circular dependency exists. Allow this and ignore windows
# errors from it.
diff --git a/chromium/services/network/public/cpp/OWNERS b/chromium/services/network/public/cpp/OWNERS
index 8150a25f3c5..c1e3e3e6c99 100644
--- a/chromium/services/network/public/cpp/OWNERS
+++ b/chromium/services/network/public/cpp/OWNERS
@@ -14,3 +14,6 @@ per-file cross_origin_opener_policy*=clamy@chromium.org
# Files and features related to component:Internals>Network>TrustTokens
per-file trust_token*=file://services/network/trust_tokens/OWNERS
+
+# Files related to Client Hints.
+per-file client_hints*=file://components/embedder_support/OWNERS
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
index 790d06e3023..e2a97bcee5d 100644
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
@@ -146,10 +146,10 @@ TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAdditionalCerts) {
config.additional_trust_anchors.push_back(
net::ImportCertFromFile(certs_dir, "root_ca_cert.pem"));
config.additional_trust_anchors.push_back(
- net::ImportCertFromFile(certs_dir, "aia-root.pem"));
+ net::ImportCertFromFile(certs_dir, "2048-rsa-root.pem"));
config.additional_untrusted_authorities.push_back(
- net::ImportCertFromFile(certs_dir, "aia-intermediate.der"));
+ net::ImportCertFromFile(certs_dir, "intermediate_ca_cert.pem"));
net::CertVerifier::Config out_config;
diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
index cb436569e1b..6e01f957ef9 100644
--- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/net_errors.h"
@@ -62,7 +63,7 @@ class CertVerifierRequestImpl : public mojom::CertVerifierRequest,
// Certificate being verified.
scoped_refptr<net::X509Certificate> cert_;
// Out parameter for the result.
- net::CertVerifyResult* cert_verify_result_;
+ raw_ptr<net::CertVerifyResult> cert_verify_result_;
// Callback to call once the result is available.
net::CompletionOnceCallback completion_callback_;
diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc
index ee0c33dce03..0c10eb50907 100644
--- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc
@@ -8,6 +8,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/ignore_result.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -93,7 +95,7 @@ class MojoCertVerifierTest : public PlatformTest {
}
private:
- MojoCertVerifierTest* test_;
+ raw_ptr<MojoCertVerifierTest> test_;
net::CertVerifier::Config config_;
mojo::Remote<mojom::URLLoaderFactoryConnector> reconnector_;
diff --git a/chromium/services/network/public/cpp/client_hints.cc b/chromium/services/network/public/cpp/client_hints.cc
index d4429c89fa2..37269bb3472 100644
--- a/chromium/services/network/public/cpp/client_hints.cc
+++ b/chromium/services/network/public/cpp/client_hints.cc
@@ -14,6 +14,8 @@
#include "base/strings/string_util.h"
#include "net/http/structured_headers.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+#include "url/origin.h"
namespace network {
@@ -49,6 +51,8 @@ ClientHintToNameMap MakeClientHintToNameMap() {
{network::mojom::WebClientHintsType::kResourceWidth, "sec-ch-width"},
{network::mojom::WebClientHintsType::kViewportWidth,
"sec-ch-viewport-width"},
+ {network::mojom::WebClientHintsType::kUAFullVersionList,
+ "sec-ch-ua-full-version-list"},
};
}
@@ -90,7 +94,7 @@ const DecodeMap& GetDecodeMap() {
absl::optional<std::vector<network::mojom::WebClientHintsType>>
ParseClientHintsHeader(const std::string& header) {
// Accept-CH is an sh-list of tokens; see:
- // https://httpwg.org/http-extensions/client-hints.html#rfc.section.3.1
+ // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-19#section-3.1
absl::optional<net::structured_headers::List> maybe_list =
net::structured_headers::ParseList(header);
if (!maybe_list.has_value())
@@ -119,13 +123,37 @@ ParseClientHintsHeader(const std::string& header) {
return absl::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();
+absl::optional<ClientHintToDelegatedThirdPartiesMap>
+ParseClientHintToDelegatedThirdPartiesHeader(const std::string& header) {
+ // Accept-CH is an sh-dictionary of tokens to origins; see:
+ // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-19#section-3.2
+ absl::optional<net::structured_headers::Dictionary> maybe_dictionary =
+ // We need to lower-case the string here or dictionary parsing refuses to
+ // see the keys.
+ net::structured_headers::ParseDictionary(base::ToLowerASCII(header));
+ if (!maybe_dictionary.has_value())
+ return absl::nullopt;
+
+ ClientHintToDelegatedThirdPartiesMap result;
- return base::Seconds(persist_duration_seconds);
+ // Now convert those to actual hint enums.
+ const DecodeMap& decode_map = GetDecodeMap();
+ for (const auto& dictionary_pair : maybe_dictionary.value()) {
+ std::vector<url::Origin> delegates;
+ for (const auto& member : dictionary_pair.second.member) {
+ if (!member.item.is_token())
+ continue;
+ const GURL maybe_gurl = GURL(member.item.GetString());
+ if (!maybe_gurl.is_valid())
+ continue;
+ delegates.push_back(url::Origin::Create(maybe_gurl));
+ }
+ const std::string& client_hint_string = dictionary_pair.first;
+ auto iter = decode_map.find(client_hint_string);
+ if (iter != decode_map.end())
+ result.insert(std::make_pair(iter->second, delegates));
+ } // for dictionary_pair
+ return absl::make_optional(std::move(result));
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/client_hints.h b/chromium/services/network/public/cpp/client_hints.h
index 1aab7a70d97..0d65cbb14e4 100644
--- a/chromium/services/network/public/cpp/client_hints.h
+++ b/chromium/services/network/public/cpp/client_hints.h
@@ -14,6 +14,10 @@
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+namespace url {
+class Origin;
+} // namespace url
+
namespace network {
using ClientHintToNameMap =
@@ -32,9 +36,17 @@ absl::optional<std::vector<network::mojom::WebClientHintsType>>
COMPONENT_EXPORT(NETWORK_CPP)
ParseClientHintsHeader(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);
+using ClientHintToDelegatedThirdPartiesMap =
+ base::flat_map<network::mojom::WebClientHintsType,
+ std::vector<url::Origin>>;
+
+// Tries to parse an Accept-CH header w/ third-party delegation ability (i.e. a
+// named meta tag). Returns absl::nullopt if parsing failed and the header
+// should be ignored; otherwise returns a (possibly empty) map of hints to
+// delegated third-parties.
+absl::optional<ClientHintToDelegatedThirdPartiesMap> COMPONENT_EXPORT(
+ NETWORK_CPP)
+ ParseClientHintToDelegatedThirdPartiesHeader(const std::string& header);
} // namespace network
diff --git a/chromium/services/network/public/cpp/client_hints_unittest.cc b/chromium/services/network/public/cpp/client_hints_unittest.cc
index c007922529b..1e603acccbc 100644
--- a/chromium/services/network/public/cpp/client_hints_unittest.cc
+++ b/chromium/services/network/public/cpp/client_hints_unittest.cc
@@ -8,12 +8,14 @@
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
using testing::UnorderedElementsAre;
namespace network {
-TEST(ClientHintsTest, ParseAcceptCH) {
+TEST(ClientHintsTest, ParseClientHintsHeader) {
absl::optional<std::vector<network::mojom::WebClientHintsType>> result;
// Empty is OK.
@@ -49,10 +51,6 @@ TEST(ClientHintsTest, ParseAcceptCH) {
UnorderedElementsAre(
network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
network::mojom::WebClientHintsType::kRtt_DEPRECATED));
-}
-
-TEST(ClientHintsTest, ParseAcceptCHCaseInsensitive) {
- absl::optional<std::vector<network::mojom::WebClientHintsType>> result;
// Matching is case-insensitive.
result = ParseClientHintsHeader("Device-meMory, Rtt ");
@@ -63,12 +61,100 @@ TEST(ClientHintsTest, ParseAcceptCHCaseInsensitive) {
network::mojom::WebClientHintsType::kRtt_DEPRECATED));
}
-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::Seconds(1000), ParseAcceptCHLifetime("1000"));
+TEST(ClientHintsTest, ParseClientHintToDelegatedThirdPartiesHeader) {
+ absl::optional<ClientHintToDelegatedThirdPartiesMap> result;
+
+ // Empty is OK.
+ result = ParseClientHintToDelegatedThirdPartiesHeader(" ");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_TRUE(result.value().empty());
+
+ // Normal case.
+ result = ParseClientHintToDelegatedThirdPartiesHeader("device-memory, rtt ");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(
+ result.value(),
+ UnorderedElementsAre(
+ std::make_pair(
+ network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
+ (std::vector<url::Origin>){}),
+ std::make_pair(network::mojom::WebClientHintsType::kRtt_DEPRECATED,
+ (std::vector<url::Origin>){})));
+
+ // Must be a list of tokens, not other things.
+ result = ParseClientHintToDelegatedThirdPartiesHeader(
+ "\"device-memory\", \"rtt\"");
+ EXPECT_FALSE(result.has_value());
+
+ // Parameters to the tokens are ignored, as encourageed by structured headers
+ // spec.
+ result = ParseClientHintToDelegatedThirdPartiesHeader(
+ "device-memory;resolution=GIB, rtt");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(
+ result.value(),
+ UnorderedElementsAre(
+ std::make_pair(
+ network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
+ (std::vector<url::Origin>){}),
+ std::make_pair(network::mojom::WebClientHintsType::kRtt_DEPRECATED,
+ (std::vector<url::Origin>){})));
+
+ // Unknown tokens are fine, since this meant to be extensible.
+ result = ParseClientHintToDelegatedThirdPartiesHeader(
+ "device-memory, rtt , nosuchtokenwhywhywhy");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(
+ result.value(),
+ UnorderedElementsAre(
+ std::make_pair(
+ network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
+ (std::vector<url::Origin>){}),
+ std::make_pair(network::mojom::WebClientHintsType::kRtt_DEPRECATED,
+ (std::vector<url::Origin>){})));
+
+ // Matching is case-insensitive.
+ result = ParseClientHintToDelegatedThirdPartiesHeader("Device-meMory, Rtt ");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(
+ result.value(),
+ UnorderedElementsAre(
+ std::make_pair(
+ network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
+ (std::vector<url::Origin>){}),
+ std::make_pair(network::mojom::WebClientHintsType::kRtt_DEPRECATED,
+ (std::vector<url::Origin>){})));
+
+ // Matching can find a one or more origins.
+ result = ParseClientHintToDelegatedThirdPartiesHeader(
+ "device-memory=https://foo.bar, rtt=( https://foo.bar "
+ "https://baz.qux) ");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(
+ result.value(),
+ UnorderedElementsAre(
+ std::make_pair(
+ network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
+ (std::vector<url::Origin>){
+ url::Origin::Create(GURL("https://foo.bar"))}),
+ std::make_pair(network::mojom::WebClientHintsType::kRtt_DEPRECATED,
+ (std::vector<url::Origin>){
+ url::Origin::Create(GURL("https://foo.bar")),
+ url::Origin::Create(GURL("https://baz.qux"))})));
+
+ // Matching ignores invalid domains
+ result = ParseClientHintToDelegatedThirdPartiesHeader(
+ "device-memory=6, rtt=( https://foo.bar/wasd self ) ");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(
+ result.value(),
+ UnorderedElementsAre(
+ std::make_pair(
+ network::mojom::WebClientHintsType::kDeviceMemory_DEPRECATED,
+ (std::vector<url::Origin>){}),
+ std::make_pair(network::mojom::WebClientHintsType::kRtt_DEPRECATED,
+ (std::vector<url::Origin>){
+ url::Origin::Create(GURL("https://foo.bar"))})));
}
} // 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 9aa0502403b..051eb8f5e4e 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
@@ -194,8 +194,10 @@ void ReportViolation(CSPContext* context,
GURL blocked_url = (directive_name == CSPDirectiveName::FrameAncestors)
? GURL(ToString(*policy->self_origin))
: url;
+ std::string blocked_url_scheme = blocked_url.scheme();
auto safe_source_location =
source_location ? source_location->Clone() : mojom::SourceLocation::New();
+
context->SanitizeDataForUseInCspViolation(has_followed_redirect,
directive_name, &blocked_url,
safe_source_location.get());
@@ -218,6 +220,18 @@ void ReportViolation(CSPContext* context,
<< ToString(effective_directive_name) << "' is used as a fallback.";
}
+ // Wildcards match network schemes ('http', 'https', 'ws', 'wss'), and the
+ // scheme of the protected resource:
+ // https://w3c.github.io/webappsec-csp/#match-url-to-source-expression. Other
+ // schemes, including custom schemes, must be explicitly listed in a source
+ // list.
+ if (policy->directives[effective_directive_name]->allow_star) {
+ message << " Note that '*' matches only URLs with network schemes ('http', "
+ "'https', 'ws', 'wss'), or URLs whose scheme matches `self`'s "
+ "scheme. "
+ << blocked_url_scheme << ":' must be added explicitely.";
+ }
+
message << "\n";
context->ReportContentSecurityPolicyViolation(mojom::CSPViolation::New(
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 49db44c5b36..dc575e2f5f6 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
@@ -90,6 +90,9 @@ class CSPContextTest : public CSPContext {
public:
CSPContextTest() = default;
+ CSPContextTest(const CSPContextTest&) = delete;
+ CSPContextTest& operator=(const CSPContextTest&) = delete;
+
const std::vector<network::mojom::CSPViolationPtr>& violations() {
return violations_;
}
@@ -109,8 +112,6 @@ class CSPContextTest : public CSPContext {
}
std::vector<network::mojom::CSPViolationPtr> violations_;
std::vector<std::string> scheme_to_bypass_;
-
- DISALLOW_COPY_AND_ASSIGN(CSPContextTest);
};
mojom::ContentSecurityPolicyPtr EmptyCSP() {
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
index 47b42e93f68..9043c45f073 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
@@ -44,8 +44,9 @@ class CSPContextTest : public CSPContext {
network::mojom::SourceLocation* source_location) const override {
if (!sanitize_data_for_use_in_csp_violation_)
return;
- *blocked_url = blocked_url->GetOrigin();
- source_location->url = GURL(source_location->url).GetOrigin().spec();
+ *blocked_url = blocked_url->DeprecatedGetOriginAsURL();
+ source_location->url =
+ GURL(source_location->url).DeprecatedGetOriginAsURL().spec();
source_location->line = 0u;
source_location->column = 0u;
}
@@ -227,7 +228,8 @@ TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
policies, CSPDirectiveName::FrameSrc, blocked_url, original_url, false,
false, source_location, CSPContext::CHECK_ALL_CSP, false));
ASSERT_EQ(3u, context.violations().size());
- EXPECT_EQ(context.violations()[2]->blocked_url, blocked_url.GetOrigin());
+ EXPECT_EQ(context.violations()[2]->blocked_url,
+ blocked_url.DeprecatedGetOriginAsURL());
EXPECT_EQ(context.violations()[2]->source_location->url, "http://a.com/");
EXPECT_EQ(context.violations()[2]->source_location->line, 0u);
EXPECT_EQ(context.violations()[2]->source_location->column, 0u);
@@ -333,4 +335,24 @@ TEST(CSPContextTest, CheckCSPDisposition) {
EXPECT_EQ(console_message_a, context.violations()[0]->console_message);
}
+TEST(CSPContextTest, BlockedDespiteWildcard) {
+ CSPContextTest context;
+ auto policies = ParseContentSecurityPolicies(
+ "frame-src *", mojom::ContentSecurityPolicyType::kEnforce,
+ mojom::ContentSecurityPolicySource::kMeta,
+ GURL("https://www.example.org"));
+
+ EXPECT_FALSE(context.IsAllowedByCsp(policies, CSPDirectiveName::FrameSrc,
+ GURL("data:text/html,<html></html>"),
+ GURL(), false, false, SourceLocation(),
+ CSPContext::CHECK_ALL_CSP, false));
+ EXPECT_EQ(context.violations().size(), 1u);
+ EXPECT_EQ(context.violations()[0]->console_message,
+ "Refused to frame 'data:text/html,<html></html>' because it "
+ "violates the following Content Security Policy directive: "
+ "\"frame-src *\". Note that '*' matches only URLs with network "
+ "schemes ('http', 'https', 'ws', 'wss'), or URLs whose scheme "
+ "matches `self`'s scheme. data:' must be added explicitely.\n");
+}
+
} // namespace network
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 9f627061aea..56fad377a5d 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
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "services/network/public/cpp/content_security_policy/csp_source_list.h"
+#include "base/memory/raw_ptr.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
@@ -1061,7 +1062,7 @@ TEST(CSPSourceList, SubsumeListNoScheme) {
struct TestCase {
std::string required;
std::vector<std::string> response_csp;
- mojom::CSPSource* origin;
+ raw_ptr<mojom::CSPSource> origin;
bool expected;
} cases[] = {
{"http://a.com", {"a.com"}, origin_https.get(), true},
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 d9fdedbe4dd..d54625cc186 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -467,37 +467,46 @@ bool StructTraits<network::mojom::CookiePartitionKeyDataView,
net::CookiePartitionKey>::
Read(network::mojom::CookiePartitionKeyDataView partition_key,
net::CookiePartitionKey* out) {
+ if (partition_key.from_script()) {
+ *out = net::CookiePartitionKey::FromScript().value();
+ return true;
+ }
net::SchemefulSite site;
if (!partition_key.ReadSite(&site))
return false;
- *out = net::CookiePartitionKey::FromWire(site);
+
+ absl::optional<base::UnguessableToken> nonce;
+ if (!partition_key.ReadNonce(&nonce))
+ return false;
+ *out = net::CookiePartitionKey::FromWire(site, nonce);
return true;
}
-const std::vector<net::CookiePartitionKey> StructTraits<
- network::mojom::CookiePartitionKeychainDataView,
- net::CookiePartitionKeychain>::keys(const net::CookiePartitionKeychain&
- keychain) {
+const std::vector<net::CookiePartitionKey>
+StructTraits<network::mojom::CookiePartitionKeyCollectionDataView,
+ net::CookiePartitionKeyCollection>::
+ keys(const net::CookiePartitionKeyCollection& key_collection) {
std::vector<net::CookiePartitionKey> result;
- if (keychain.ContainsAllKeys() || keychain.IsEmpty())
+ if (key_collection.ContainsAllKeys() || key_collection.IsEmpty())
return result;
- result.insert(result.begin(), keychain.PartitionKeys().begin(),
- keychain.PartitionKeys().end());
+ result.insert(result.begin(), key_collection.PartitionKeys().begin(),
+ key_collection.PartitionKeys().end());
return result;
}
-bool StructTraits<network::mojom::CookiePartitionKeychainDataView,
- net::CookiePartitionKeychain>::
- Read(network::mojom::CookiePartitionKeychainDataView keychain,
- net::CookiePartitionKeychain* out) {
- if (keychain.contains_all_partitions()) {
- *out = net::CookiePartitionKeychain::ContainsAll();
+bool StructTraits<network::mojom::CookiePartitionKeyCollectionDataView,
+ net::CookiePartitionKeyCollection>::
+ Read(network::mojom::CookiePartitionKeyCollectionDataView
+ key_collection_data_view,
+ net::CookiePartitionKeyCollection* out) {
+ if (key_collection_data_view.contains_all_partitions()) {
+ *out = net::CookiePartitionKeyCollection::ContainsAll();
return true;
}
std::vector<net::CookiePartitionKey> keys;
- if (!keychain.ReadKeys(&keys))
+ if (!key_collection_data_view.ReadKeys(&keys))
return false;
- *out = net::CookiePartitionKeychain(keys);
+ *out = net::CookiePartitionKeyCollection(keys);
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 f273b1351ea..c2dc38731ee 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -15,7 +15,7 @@
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_options.h"
-#include "net/cookies/cookie_partition_keychain.h"
+#include "net/cookies/cookie_partition_key_collection.h"
#include "net/cookies/same_party_context.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -185,22 +185,32 @@ struct StructTraits<network::mojom::CookiePartitionKeyDataView,
static const net::SchemefulSite& site(const net::CookiePartitionKey& cpk) {
return cpk.site();
}
+ static bool from_script(const net::CookiePartitionKey& cpk) {
+ return cpk.from_script();
+ }
+
+ static const absl::optional<base::UnguessableToken>& nonce(
+ const net::CookiePartitionKey& cpk) {
+ return cpk.nonce();
+ }
+
static bool Read(network::mojom::CookiePartitionKeyDataView partition_key,
net::CookiePartitionKey* out);
};
template <>
-struct StructTraits<network::mojom::CookiePartitionKeychainDataView,
- net::CookiePartitionKeychain> {
+struct StructTraits<network::mojom::CookiePartitionKeyCollectionDataView,
+ net::CookiePartitionKeyCollection> {
static bool contains_all_partitions(
- const net::CookiePartitionKeychain& keychain) {
- return keychain.ContainsAllKeys();
+ const net::CookiePartitionKeyCollection& key_collection) {
+ return key_collection.ContainsAllKeys();
}
static const std::vector<net::CookiePartitionKey> keys(
- const net::CookiePartitionKeychain& keychain);
+ const net::CookiePartitionKeyCollection& key_collection);
- static bool Read(network::mojom::CookiePartitionKeychainDataView keychain,
- net::CookiePartitionKeychain* out);
+ static bool Read(network::mojom::CookiePartitionKeyCollectionDataView
+ key_collection_data_view,
+ net::CookiePartitionKeyCollection* out);
};
template <>
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 9cde9da38b1..650ff5cc738 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
@@ -385,29 +385,37 @@ TEST(CookieManagerTraitsTest, Roundtrips_PartitionKey) {
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
*original, copied));
EXPECT_EQ(original->PartitionKey(), copied.PartitionKey());
+ EXPECT_FALSE(copied.PartitionKey()->from_script());
+
+ original = net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), base::Time(),
+ true, false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_LOW, false, net::CookiePartitionKey::FromScript(),
+ net::CookieSourceScheme::kSecure, 8433);
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
+ *original, copied));
+ EXPECT_TRUE(copied.PartitionKey()->from_script());
}
-TEST(CookieManagerTraitsTest, Roundtrips_CookiePartitionKeychain) {
+TEST(CookieManagerTraitsTest, Roundtrips_CookiePartitionKeyCollection) {
{
- net::CookiePartitionKeychain original;
- net::CookiePartitionKeychain copied;
+ net::CookiePartitionKeyCollection original;
+ net::CookiePartitionKeyCollection copied;
- EXPECT_TRUE(
- mojo::test::SerializeAndDeserialize<mojom::CookiePartitionKeychain>(
- original, copied));
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
+ mojom::CookiePartitionKeyCollection>(original, copied));
EXPECT_FALSE(copied.ContainsAllKeys());
EXPECT_EQ(0u, copied.PartitionKeys().size());
}
{
- net::CookiePartitionKeychain original(
+ net::CookiePartitionKeyCollection original(
net::CookiePartitionKey::FromURLForTesting(
GURL("https://www.example.com")));
- net::CookiePartitionKeychain copied;
+ net::CookiePartitionKeyCollection copied;
- EXPECT_TRUE(
- mojo::test::SerializeAndDeserialize<mojom::CookiePartitionKeychain>(
- original, copied));
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
+ mojom::CookiePartitionKeyCollection>(original, copied));
EXPECT_FALSE(copied.ContainsAllKeys());
EXPECT_THAT(copied.PartitionKeys(),
testing::UnorderedElementsAre(
@@ -416,15 +424,14 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookiePartitionKeychain) {
}
{
- net::CookiePartitionKeychain original({
+ net::CookiePartitionKeyCollection original({
net::CookiePartitionKey::FromURLForTesting(GURL("https://a.foo.com")),
net::CookiePartitionKey::FromURLForTesting(GURL("https://b.bar.com")),
});
- net::CookiePartitionKeychain copied;
+ net::CookiePartitionKeyCollection copied;
- EXPECT_TRUE(
- mojo::test::SerializeAndDeserialize<mojom::CookiePartitionKeychain>(
- original, copied));
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
+ mojom::CookiePartitionKeyCollection>(original, copied));
EXPECT_FALSE(copied.ContainsAllKeys());
EXPECT_THAT(copied.PartitionKeys(),
testing::UnorderedElementsAre(
@@ -435,13 +442,12 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookiePartitionKeychain) {
}
{
- net::CookiePartitionKeychain original =
- net::CookiePartitionKeychain::ContainsAll();
- net::CookiePartitionKeychain copied;
+ net::CookiePartitionKeyCollection original =
+ net::CookiePartitionKeyCollection::ContainsAll();
+ net::CookiePartitionKeyCollection copied;
- EXPECT_TRUE(
- mojo::test::SerializeAndDeserialize<mojom::CookiePartitionKeychain>(
- original, copied));
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
+ mojom::CookiePartitionKeyCollection>(original, copied));
EXPECT_TRUE(copied.ContainsAllKeys());
}
}
diff --git a/chromium/services/network/public/cpp/corb/corb_impl.cc b/chromium/services/network/public/cpp/corb/corb_impl.cc
index 119d2af3be5..321e407108a 100644
--- a/chromium/services/network/public/cpp/corb/corb_impl.cc
+++ b/chromium/services/network/public/cpp/corb/corb_impl.cc
@@ -345,14 +345,6 @@ MimeType CrossOriginReadBlocking::GetCanonicalMimeType(
}
// 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
- // response from FTP servers.
- return url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme);
-}
-
-// 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
@@ -708,12 +700,6 @@ CrossOriginReadBlocking::CorbResponseAnalyzer::ShouldBlockBasedOnHeaders(
if (initiator.IsSameOriginWith(target_origin))
return Decision::kAllow;
- // Only block documents from HTTP(S) schemes. Checking the scheme of
- // |target_origin| ensures that we also protect content of blob: and
- // filesystem: URLs if their nested origins have a HTTP(S) scheme.
- if (!IsBlockableScheme(target_origin.GetURL()))
- return Decision::kAllow;
-
// Only apply CORB to `no-cors` requests.
//
// CORB doesn't need to block kNavigate requests because results of these are
diff --git a/chromium/services/network/public/cpp/corb/corb_impl.h b/chromium/services/network/public/cpp/corb/corb_impl.h
index df2c52a710c..ea518d26aca 100644
--- a/chromium/services/network/public/cpp/corb/corb_impl.h
+++ b/chromium/services/network/public/cpp/corb/corb_impl.h
@@ -314,11 +314,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
static MimeType GetCanonicalMimeType(base::StringPiece mime_type);
private:
- // Returns whether this scheme is a target of the cross-origin read blocking
- // (CORB) policy. This returns true only for http://* and https://* urls.
- static bool IsBlockableScheme(const GURL& frame_origin);
- FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, IsBlockableScheme);
-
static SniffingResult SniffForHTML(base::StringPiece data);
static SniffingResult SniffForXML(base::StringPiece data);
static SniffingResult SniffForJSON(base::StringPiece data);
diff --git a/chromium/services/network/public/cpp/corb/corb_impl_unittest.cc b/chromium/services/network/public/cpp/corb/corb_impl_unittest.cc
index 903c354d8bc..99faf46e1ae 100644
--- a/chromium/services/network/public/cpp/corb/corb_impl_unittest.cc
+++ b/chromium/services/network/public/cpp/corb/corb_impl_unittest.cc
@@ -325,7 +325,10 @@ const TestScenario kScenarios[] = {
kVerdictPacketForHeadersBasedVerdict, // verdict_packet
},
{
- "Allowed: Cross-site XHR to HTML over FTP",
+ // This case won't be reached in practice today, because CORB is only
+ // used by certain URLLoaderFactories (e.g. in the NetworkService, when
+ // handling http(s) URLs) and is not used for ftp://... URLs.
+ "Blocked: Cross-site XHR to HTML over FTP",
__LINE__,
"ftp://www.b.com/resource.html", // target_url
"http://www.a.com/", // initiator_origin
@@ -336,11 +339,14 @@ const TestScenario kScenarios[] = {
{"<html><head>this should sniff as HTML"}, // packets
false, // resource_is_sensitive
CrossOriginProtectionDecision::kAllow, // protection_decision
- Verdict::kAllow, // verdict
- kVerdictPacketForHeadersBasedVerdict, // verdict_packet
+ Verdict::kBlock, // verdict
+ 0, // verdict_packet
},
{
- "Allowed: Cross-site XHR to HTML from file://",
+ // This case won't be reached in practice today, because CORB is only
+ // used by certain URLLoaderFactories (e.g. in the NetworkService, when
+ // handling http(s) URLs) and is not used for file://... URLs.
+ "Blocked: Cross-site XHR to HTML from file://",
__LINE__,
"file:///foo/resource.html", // target_url
"http://www.a.com/", // initiator_origin
@@ -351,8 +357,8 @@ const TestScenario kScenarios[] = {
{"<html><head>this should sniff as HTML"}, // packets
false, // resource_is_sensitive
CrossOriginProtectionDecision::kAllow, // protection_decision
- Verdict::kAllow, // verdict
- kVerdictPacketForHeadersBasedVerdict, // verdict_packet
+ Verdict::kBlock, // verdict
+ 0, // verdict_packet
},
{
// Blocked, because the unit test doesn't make a call to
@@ -2239,22 +2245,6 @@ INSTANTIATE_TEST_SUITE_P(All,
// isolation.
// =============================================================================
-TEST(CrossOriginReadBlockingTest, IsBlockableScheme) {
- GURL data_url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA==");
- GURL ftp_url("ftp://google.com");
- GURL mailto_url("mailto:google@google.com");
- GURL about_url("about:chrome");
- GURL http_url("http://google.com");
- GURL https_url("https://google.com");
-
- EXPECT_FALSE(CrossOriginReadBlocking::IsBlockableScheme(data_url));
- EXPECT_FALSE(CrossOriginReadBlocking::IsBlockableScheme(ftp_url));
- EXPECT_FALSE(CrossOriginReadBlocking::IsBlockableScheme(mailto_url));
- EXPECT_FALSE(CrossOriginReadBlocking::IsBlockableScheme(about_url));
- EXPECT_TRUE(CrossOriginReadBlocking::IsBlockableScheme(http_url));
- EXPECT_TRUE(CrossOriginReadBlocking::IsBlockableScheme(https_url));
-}
-
TEST(CrossOriginReadBlockingTest, SniffForHTML) {
using CORB = CrossOriginReadBlocking;
diff --git a/chromium/services/network/public/cpp/cors/cors.cc b/chromium/services/network/public/cpp/cors/cors.cc
index f8075a8a20e..af768ddd8c3 100644
--- a/chromium/services/network/public/cpp/cors/cors.cc
+++ b/chromium/services/network/public/cpp/cors/cors.cc
@@ -16,6 +16,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "net/base/mime_util.h"
+#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
@@ -129,18 +130,18 @@ namespace cors {
namespace header_names {
-constexpr char kAccessControlAllowCredentials[] =
+const char kAccessControlAllowCredentials[] =
"Access-Control-Allow-Credentials";
-constexpr char kAccessControlAllowExternal[] = "Access-Control-Allow-External";
-constexpr char kAccessControlAllowHeaders[] = "Access-Control-Allow-Headers";
-constexpr char kAccessControlAllowMethods[] = "Access-Control-Allow-Methods";
-constexpr char kAccessControlAllowOrigin[] = "Access-Control-Allow-Origin";
-constexpr char kAccessControlMaxAge[] = "Access-Control-Max-Age";
-constexpr char kAccessControlRequestExternal[] =
- "Access-Control-Request-External";
-constexpr char kAccessControlRequestHeaders[] =
- "Access-Control-Request-Headers";
-constexpr char kAccessControlRequestMethod[] = "Access-Control-Request-Method";
+const char kAccessControlAllowHeaders[] = "Access-Control-Allow-Headers";
+const char kAccessControlAllowMethods[] = "Access-Control-Allow-Methods";
+const char kAccessControlAllowOrigin[] = "Access-Control-Allow-Origin";
+const char kAccessControlAllowPrivateNetwork[] =
+ "Access-Control-Allow-Private-Network";
+const char kAccessControlMaxAge[] = "Access-Control-Max-Age";
+const char kAccessControlRequestHeaders[] = "Access-Control-Request-Headers";
+const char kAccessControlRequestMethod[] = "Access-Control-Request-Method";
+const char kAccessControlRequestPrivateNetwork[] =
+ "Access-Control-Request-Private-Network";
} // namespace header_names
@@ -364,7 +365,17 @@ bool IsCorsSafelistedHeader(const std::string& name, const std::string& value) {
"sec-ch-dpr",
"sec-ch-width",
"sec-ch-viewport-width",
+
+ // Simple range values are safelisted.
+ // https://fetch.spec.whatwg.org/#simple-range-header-value
+ "range",
+
+ // The `Sec-CH-UA-Full-Version-List` provide server information about the
+ // full version for each brand in its brands list.
+ // https://wicg.github.io/ua-client-hints/#sec-ch-ua-full-version-list
+ "sec-ch-ua-full-version-list",
});
+
if (!base::Contains(safe_names, lower_name))
return false;
@@ -397,6 +408,27 @@ bool IsCorsSafelistedHeader(const std::string& name, const std::string& value) {
if (lower_name == "content-type")
return IsCorsSafelistedLowerCaseContentType(lower_value);
+ if (lower_name == "range") {
+ // A 'simple' range value is of the following form: 'bytes=\d+-(\d+)?'.
+ // We can use the regular range header parser with the following caveats:
+ // - No space characters or trailing commas
+ // - Only one range is provided
+ // - No suffix (bytes=-x) ranges
+
+ if (std::any_of(lower_value.begin(), lower_value.end(), [](char c) {
+ return net::HttpUtil::IsLWS(c) || c == ',';
+ })) {
+ return false;
+ }
+
+ std::vector<net::HttpByteRange> ranges;
+ if (!net::HttpUtil::ParseRangeHeader(lower_value, &ranges))
+ return false;
+ if (ranges.size() != 1 || ranges[0].IsSuffixByteRange())
+ return false;
+ return true;
+ }
+
return true;
}
diff --git a/chromium/services/network/public/cpp/cors/cors.h b/chromium/services/network/public/cpp/cors/cors.h
index 435c599436e..50e488beef8 100644
--- a/chromium/services/network/public/cpp/cors/cors.h
+++ b/chromium/services/network/public/cpp/cors/cors.h
@@ -28,6 +28,7 @@ namespace header_names {
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlAllowCredentials[];
+// TODO(https://crbug.com/1263483): Remove this.
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlAllowExternal[];
COMPONENT_EXPORT(NETWORK_CPP)
@@ -37,13 +38,18 @@ extern const char kAccessControlAllowMethods[];
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlAllowOrigin[];
COMPONENT_EXPORT(NETWORK_CPP)
+extern const char kAccessControlAllowPrivateNetwork[];
+COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlMaxAge[];
+// TODO(https://crbug.com/1263483): Remove this.
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlRequestExternal[];
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlRequestHeaders[];
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kAccessControlRequestMethod[];
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const char kAccessControlRequestPrivateNetwork[];
} // namespace header_names
diff --git a/chromium/services/network/public/cpp/cors/cors_unittest.cc b/chromium/services/network/public/cpp/cors/cors_unittest.cc
index 252a8117861..5f02e34193e 100644
--- a/chromium/services/network/public/cpp/cors/cors_unittest.cc
+++ b/chromium/services/network/public/cpp/cors/cors_unittest.cc
@@ -504,6 +504,41 @@ TEST_F(CorsTest, CorsUnsafeRequestHeaderNames) {
List({"content-type", "hoge"}));
}
+TEST_F(CorsTest, CheckCorsRangeSafelist) {
+ // Missing values
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", ""));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "500"));
+
+ // Case
+ EXPECT_TRUE(IsCorsSafelistedHeader("range", "bytes=100-200"));
+ EXPECT_TRUE(IsCorsSafelistedHeader("Range", "bytes=100-200"));
+ EXPECT_TRUE(IsCorsSafelistedHeader("RANGE", "bytes=100-200"));
+ EXPECT_TRUE(IsCorsSafelistedHeader("range", "BYTES=100-200"));
+
+ // Valid values
+ EXPECT_TRUE(IsCorsSafelistedHeader("range", "bytes=100-"));
+
+ // Multiple ranges
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=100-200,300-400"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=100-200,400"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=100-200-400"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=100-200,400-"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=-50,100-"));
+
+ // Invalid ranges
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=200-100"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=-200--100"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=-50-50"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=-200"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=100"));
+
+ // Invalid charset.
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes = 100-200"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes =100-200"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", "bytes=,100-200"));
+ EXPECT_FALSE(IsCorsSafelistedHeader("range", ",bytes=,100-200"));
+}
+
TEST_F(CorsTest, NoCorsSafelistedHeaderName) {
EXPECT_TRUE(IsNoCorsSafelistedHeaderName("accept"));
EXPECT_TRUE(IsNoCorsSafelistedHeaderName("AcCePT"));
diff --git a/chromium/services/network/public/cpp/cors/origin_access_entry.cc b/chromium/services/network/public/cpp/cors/origin_access_entry.cc
index 667fe2619b1..03628a5afaa 100644
--- a/chromium/services/network/public/cpp/cors/origin_access_entry.cc
+++ b/chromium/services/network/public/cpp/cors/origin_access_entry.cc
@@ -29,6 +29,19 @@ bool IsSubdomainOfHost(const std::string& subdomain, const std::string& host) {
return true;
}
+bool IsPublicSuffixSubdomainOfHost(const std::string& subdomain,
+ const std::string& host) {
+ size_t public_suffix_length =
+ net::registry_controlled_domains::PermissiveGetHostRegistryLength(
+ subdomain,
+ net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ return public_suffix_length != std::string::npos &&
+ public_suffix_length != 0 &&
+ IsSubdomainOfHost(
+ subdomain.substr(subdomain.length() - public_suffix_length), host);
+}
+
} // namespace
OriginAccessEntry::OriginAccessEntry(
@@ -56,14 +69,14 @@ OriginAccessEntry::OriginAccessEntry(
net::registry_controlled_domains::PermissiveGetHostRegistryLength(
host_, net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- if (public_suffix_length == 0)
+ if (public_suffix_length == 0 || public_suffix_length == std::string::npos)
public_suffix_length = host_.length();
if (host_.length() <= public_suffix_length + 1) {
host_is_public_suffix_ = true;
} else if (domain_match_mode_ ==
- mojom::CorsDomainMatchMode::kAllowRegistrableDomains &&
- public_suffix_length) {
+ mojom::CorsDomainMatchMode::kAllowRegistrableDomains) {
+ DCHECK(public_suffix_length);
// The "2" in the next line is 1 for the '.', plus a 1-char minimum label
// length.
const size_t dot =
@@ -133,6 +146,10 @@ OriginAccessEntry::MatchResult OriginAccessEntry::MatchesDomain(
if (host_is_public_suffix_)
return kMatchesOriginButIsPublicSuffix;
+ // Determine whether host_ matches domain's public suffix.
+ if (IsPublicSuffixSubdomainOfHost(domain, host_))
+ return kMatchesOriginButIsPublicSuffix;
+
return kMatchesOrigin;
}
diff --git a/chromium/services/network/public/cpp/cors/origin_access_entry.h b/chromium/services/network/public/cpp/cors/origin_access_entry.h
index 04c1e913e6a..82b3da7f988 100644
--- a/chromium/services/network/public/cpp/cors/origin_access_entry.h
+++ b/chromium/services/network/public/cpp/cors/origin_access_entry.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "services/network/public/mojom/cors.mojom-shared.h"
#include "services/network/public/mojom/cors_origin_pattern.mojom-shared.h"
@@ -25,9 +24,9 @@ class CorsOriginPattern;
namespace cors {
-// A class to hold a protocol and domain pair and to provide methods to
-// determine if a given origin or domain matches to the pair. The class can have
-// a setting to control if the matching methods accept a partial match.
+// A class to hold a protocol and domain and port triple and to provide methods
+// to determine if a given origin or domain matches. The class can have a
+// setting to control if the matching methods accept a partial match.
class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessEntry final {
public:
enum MatchResult {
@@ -51,6 +50,10 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessEntry final {
const mojom::CorsPortMatchMode port_match_mode,
const mojom::CorsOriginAccessMatchPriority priority =
mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
+
+ OriginAccessEntry(const OriginAccessEntry&) = delete;
+ OriginAccessEntry& operator=(const OriginAccessEntry&) = delete;
+
OriginAccessEntry(OriginAccessEntry&& from);
// MatchesOrigin requires a protocol match (e.g. 'http' != 'https'), and a
@@ -78,8 +81,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessEntry final {
std::string registrable_domain_;
bool host_is_public_suffix_;
-
- DISALLOW_COPY_AND_ASSIGN(OriginAccessEntry);
};
} // namespace cors
diff --git a/chromium/services/network/public/cpp/cors/origin_access_entry_unittest.cc b/chromium/services/network/public/cpp/cors/origin_access_entry_unittest.cc
index 5782f38d91d..b9c4b98b33a 100644
--- a/chromium/services/network/public/cpp/cors/origin_access_entry_unittest.cc
+++ b/chromium/services/network/public/cpp/cors/origin_access_entry_unittest.cc
@@ -146,6 +146,32 @@ TEST(OriginAccessEntryTest, AllowRegistrableDomainsTest) {
{"http", "", "http://beispiel.de/", OriginAccessEntry::kMatchesOrigin},
{"https", "", "http://beispiel.de/",
OriginAccessEntry::kDoesNotMatchOrigin},
+
+ // Table of examples from the HTML spec. (Except those based on
+ // IP-address, which we don't support.)
+ // https://html.spec.whatwg.org/multipage/origin.html#dom-document-domain
+ {"http", "0.0.0.0", "http://0.0.0.0", OriginAccessEntry::kMatchesOrigin},
+ {"http", "example.com", "http://example.com",
+ OriginAccessEntry::kMatchesOrigin},
+ {"http", "example.com", "http://example.com.",
+ OriginAccessEntry::kDoesNotMatchOrigin},
+ {"http", "example.com.", "http://example.com",
+ OriginAccessEntry::kDoesNotMatchOrigin},
+ {"http", "example.com", "http://www.example.com",
+ OriginAccessEntry::kMatchesOrigin},
+ {"http", "com", "http://example.com",
+ OriginAccessEntry::kMatchesOriginButIsPublicSuffix},
+ {"http", "example", "http://example", OriginAccessEntry::kMatchesOrigin},
+ {"http", "compute.amazonaws.com", "http://example.compute.amazonaws.com",
+ OriginAccessEntry::kMatchesOriginButIsPublicSuffix},
+ {"http", "example.compute.amazonaws.com",
+ "http://www.example.compute.amazonaws.com",
+ OriginAccessEntry::kMatchesOriginButIsPublicSuffix},
+ {"http", "amazonaws.com", "http://www.example.compute.amazonaws.com",
+ OriginAccessEntry::kMatchesOriginButIsPublicSuffix},
+ {"http", "amazonaws.com", "http://test.amazonaws.com",
+ OriginAccessEntry::kMatchesOrigin},
+
};
for (const auto& test : inputs) {
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 8591e978de6..7a29e765cc8 100644
--- a/chromium/services/network/public/cpp/cors/origin_access_list.h
+++ b/chromium/services/network/public/cpp/cors/origin_access_list.h
@@ -11,7 +11,6 @@
#include "base/component_export.h"
#include "base/containers/flat_map.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "services/network/public/cpp/cors/origin_access_entry.h"
#include "services/network/public/mojom/cors_origin_pattern.mojom-shared.h"
diff --git a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc
index e8439fc5163..424bdf24870 100644
--- a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc
+++ b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h
index d7fdd4bba34..bc09d66645a 100644
--- a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h
+++ b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_PUBLIC_CPP_CROSS_THREAD_PENDING_SHARED_URL_LOADER_FACTORY_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc
index a3a647f627a..e4277d8e8d4 100644
--- a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc
+++ b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc
@@ -10,8 +10,8 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
diff --git a/chromium/services/network/public/cpp/devtools_observer_util.cc b/chromium/services/network/public/cpp/devtools_observer_util.cc
index 6886f6323bf..c51e6d8fbc3 100644
--- a/chromium/services/network/public/cpp/devtools_observer_util.cc
+++ b/chromium/services/network/public/cpp/devtools_observer_util.cc
@@ -16,7 +16,8 @@ mojom::URLResponseHeadDevToolsInfoPtr ExtractDevToolsInfo(
head.cert_status, head.encoded_data_length, head.was_in_prefetch_cache,
head.was_fetched_via_service_worker, head.cache_storage_cache_name,
head.alpn_negotiated_protocol, head.was_fetched_via_spdy,
- head.service_worker_response_source, head.ssl_info, head.remote_endpoint);
+ head.service_worker_response_source, head.ssl_info, head.remote_endpoint,
+ head.emitted_extra_info);
}
mojom::URLRequestDevToolsInfoPtr ExtractDevToolsInfo(
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 31267c6745f..3bb1ebe17b7 100644
--- a/chromium/services/network/public/cpp/empty_url_loader_client.h
+++ b/chromium/services/network/public/cpp/empty_url_loader_client.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/callback_forward.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chromium/services/network/public/cpp/features.cc b/chromium/services/network/public/cpp/features.cc
index d109cac66b5..4aaf592cb9d 100644
--- a/chromium/services/network/public/cpp/features.cc
+++ b/chromium/services/network/public/cpp/features.cc
@@ -81,19 +81,12 @@ const base::Feature kProactivelyThrottleLowPriorityRequests{
// Enables Cross-Origin-Embedder-Policy: credentialless.
// https://github.com/mikewest/credentiallessness
+// TODO(https://crbug.com/1175099): Remove one week after M96: 2021-11-25
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginEmbedderPolicyCredentialless{
"CrossOriginEmbedderPolicyCredentialless",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Enables Cross-Origin-Embedder-Policy credentialless origin trial. It will be
-// used as a kill switch during the experiment.
-// Intent-to-experiment:
-// https://groups.google.com/a/chromium.org/g/blink-dev/c/Sdc0G1bvKr0/m/YHR8RuWyAAAJ
-const base::Feature kCrossOriginEmbedderPolicyCredentiallessOriginTrial{
- "CrossOriginEmbedderPolicyCredentiallessOriginTrial",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables Cross-Origin Opener Policy (COOP).
// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
// https://html.spec.whatwg.org/#cross-origin-opener-policy
@@ -223,12 +216,15 @@ constexpr base::FeatureParam<int> kLoaderChunkSize{
// static
uint32_t GetDataPipeDefaultAllocationSize(DataPipeAllocationSize option) {
- if (option == DataPipeAllocationSize::kDefaultSizeOnly)
- return kDataPipeDefaultAllocationSize;
// For low-memory devices, always use the (smaller) default buffer size.
if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512)
return kDataPipeDefaultAllocationSize;
- return base::saturated_cast<uint32_t>(kDataPipeAllocationSize.Get());
+ switch (option) {
+ case DataPipeAllocationSize::kDefaultSizeOnly:
+ return kDataPipeDefaultAllocationSize;
+ case DataPipeAllocationSize::kLargerSizeIfPossible:
+ return base::saturated_cast<uint32_t>(kDataPipeAllocationSize.Get());
+ }
}
// static
@@ -236,10 +232,35 @@ uint32_t GetLoaderChunkSize() {
return base::saturated_cast<uint32_t>(kLoaderChunkSize.Get());
}
-// Enable recording UMAs for network activities which can wake-up radio on
-// Android.
-const base::Feature kRecordRadioWakeupTrigger{
- "RecordRadioWakeupTrigger", base::FEATURE_DISABLED_BY_DEFAULT};
+// Check disk cache to see if the queued requests (especially those don't need
+// validation) have already been cached. If yes, start them as they may not
+// contend for network.
+const base::Feature kCheckCacheForQueuedRequests{
+ "CheckCacheForQueuedRequests", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// The time interval before checking the cache for queued request.
+constexpr base::FeatureParam<base::TimeDelta> kQueuedRequestsCacheCheckInterval{
+ &kCheckCacheForQueuedRequests, "queued_requests_cache_check_interval",
+ base::Milliseconds(100)};
+
+// Cache check is only valid for requests queued for long than this threshold.
+constexpr base::FeatureParam<base::TimeDelta>
+ kQueuedRequestsCacheCheckTimeThreshold{
+ &kCheckCacheForQueuedRequests,
+ "queued_requests_cache_check_time_threshold", base::Milliseconds(100)};
+
+// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name
+const base::Feature kCorsNonWildcardRequestHeadersSupport{
+ "CorsNonWildcardRequestHeadersSupport", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Whether the sync client optimization is used for communication between the
+// CorsURLLoader and URLLoader.
+const base::Feature kURLLoaderSyncClient{"URLLoaderSyncClient",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Optimize the implementation of calling URLLoaderFactory::UpdateLoadInfo().
+const base::Feature kOptimizeUpdateLoadInfo{"OptimizeUpdateLoadInfo",
+ base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/features.gni b/chromium/services/network/public/cpp/features.gni
index 18fef9132d7..a05bca40428 100644
--- a/chromium/services/network/public/cpp/features.gni
+++ b/chromium/services/network/public/cpp/features.gni
@@ -8,4 +8,10 @@ declare_args() {
# Certificate transparency is not supported on iOS.
# TODO(mmenke): It's actually not supported on Android, either.
is_ct_supported = !is_ios
+
+ # Controls whether P2P is exposed by the network service.
+ # Optional to reduce avoid having Chrome on iOS depends on
+ # WebRTC and related third-party libraries (libvpx, libaom,
+ # ...).
+ is_p2p_enabled = true
}
diff --git a/chromium/services/network/public/cpp/features.h b/chromium/services/network/public/cpp/features.h
index 01492ca6c44..36fc346532a 100644
--- a/chromium/services/network/public/cpp/features.h
+++ b/chromium/services/network/public/cpp/features.h
@@ -35,8 +35,6 @@ extern const base::Feature kProactivelyThrottleLowPriorityRequests;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginEmbedderPolicyCredentialless;
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kCrossOriginEmbedderPolicyCredentiallessOriginTrial;
-COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginOpenerPolicy;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginOpenerPolicyByDefault;
@@ -92,7 +90,24 @@ COMPONENT_EXPORT(NETWORK_CPP)
extern uint32_t GetLoaderChunkSize();
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kRecordRadioWakeupTrigger;
+extern const base::Feature kCheckCacheForQueuedRequests;
+
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::FeatureParam<base::TimeDelta>
+ kQueuedRequestsCacheCheckInterval;
+
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::FeatureParam<base::TimeDelta>
+ kQueuedRequestsCacheCheckTimeThreshold;
+
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kCorsNonWildcardRequestHeadersSupport;
+
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kURLLoaderSyncClient;
+
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kOptimizeUpdateLoadInfo;
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/ip_address_space_util.cc b/chromium/services/network/public/cpp/ip_address_space_util.cc
index a7cfbcc1222..c504326ce08 100644
--- a/chromium/services/network/public/cpp/ip_address_space_util.cc
+++ b/chromium/services/network/public/cpp/ip_address_space_util.cc
@@ -14,6 +14,7 @@
#include "base/strings/string_split.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/transport_info.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/parsed_headers.mojom.h"
@@ -250,8 +251,6 @@ const AddressSpaceMap& NonPublicAddressSpaceMap() {
return *kMap;
}
-} // namespace
-
IPAddressSpace IPEndPointToIPAddressSpace(const IPEndPoint& endpoint) {
if (!endpoint.address().IsValid()) {
return IPAddressSpace::kUnknown;
@@ -267,6 +266,17 @@ IPAddressSpace IPEndPointToIPAddressSpace(const IPEndPoint& endpoint) {
.value_or(IPAddressSpace::kPublic);
}
+} // namespace
+
+IPAddressSpace TransportInfoToIPAddressSpace(const net::TransportInfo& info) {
+ switch (info.type) {
+ case net::TransportType::kDirect:
+ return IPEndPointToIPAddressSpace(info.endpoint);
+ case net::TransportType::kProxied:
+ return mojom::IPAddressSpace::kUnknown;
+ }
+}
+
namespace {
// For comparison purposes, we treat kUnknown the same as kPublic.
diff --git a/chromium/services/network/public/cpp/ip_address_space_util.h b/chromium/services/network/public/cpp/ip_address_space_util.h
index d0a9236a92e..f16eb955e80 100644
--- a/chromium/services/network/public/cpp/ip_address_space_util.h
+++ b/chromium/services/network/public/cpp/ip_address_space_util.h
@@ -16,25 +16,33 @@ class GURL;
namespace net {
class IPEndPoint;
+struct TransportInfo;
} // namespace net
namespace network {
-// Returns the IPAddressSpace to which `endpoint` belongs.
+// Returns the `IPAddressSpace` to which the endpoint of `transport` belongs.
//
-// Returns `kUnknown` for invalid IP addresses. Otherwise, takes into account
-// the `--ip-address-space-overrides` command-line switch.
+// When the transport is a proxied connection, returns `kUnknown`. See
+// https://github.com/WICG/private-network-access/issues/62 for more details on
+// the reasoning there.
//
-// `endpoint`'s port is only used for matching to command-line overrides. It is
-// ignored otherwise. In particular, if no overrides are specified on the
+// When the transport is a direct connection, returns the IP address space of
+// `info.endpoint`. This returns `kUnknown` for invalid IP addresses. Otherwise,
+// takes into account the `--ip-address-space-overrides` command-line switch. If
+// no override applies, then follows this algorithm:
+// https://wicg.github.io/private-network-access/#determine-the-ip-address-space
+//
+// `info.endpoint`'s port is only used for matching to command-line overrides.
+// It is ignored otherwise. In particular, if no overrides are specified on the
// command-line, then this function ignores the port entirely.
//
// WARNING: This can only be used as-is for subresource requests loaded over the
// network. Special URL schemes and resource headers must also be taken into
// account at higher layers.
mojom::IPAddressSpace COMPONENT_EXPORT(NETWORK_CPP)
- IPEndPointToIPAddressSpace(const net::IPEndPoint& endpoint);
+ TransportInfoToIPAddressSpace(const net::TransportInfo& info);
// Returns whether `lhs` is less public than `rhs`.
//
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
index e4fedd25b20..11b349df94a 100644
--- a/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
+++ b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/transport_info.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,6 +23,8 @@ using mojom::URLResponseHead;
using net::IPAddress;
using net::IPAddressBytes;
using net::IPEndPoint;
+using net::TransportInfo;
+using net::TransportType;
IPAddress PublicIPv4Address() {
return IPAddress(64, 233, 160, 0);
@@ -31,6 +34,24 @@ IPAddress PrivateIPv4Address() {
return IPAddress(192, 168, 1, 1);
}
+TransportInfo DirectTransport(const IPEndPoint& endpoint) {
+ TransportInfo result;
+ result.type = TransportType::kDirect;
+ result.endpoint = endpoint;
+ return result;
+}
+
+TransportInfo ProxiedTransport(const IPEndPoint& endpoint) {
+ TransportInfo result;
+ result.type = TransportType::kProxied;
+ result.endpoint = endpoint;
+ return result;
+}
+
+IPAddressSpace IPEndPointToIPAddressSpace(const IPEndPoint& endpoint) {
+ return TransportInfoToIPAddressSpace(DirectTransport(endpoint));
+}
+
// Helper for tests that do not care about command-line overrides.
IPAddressSpace IPAddressToIPAddressSpace(const IPAddress& address) {
return IPEndPointToIPAddressSpace(IPEndPoint(address, 80));
@@ -355,6 +376,22 @@ TEST(IPAddressSpaceTest, IPEndPointToAddressSpaceOverrideV6) {
IPAddressSpace::kPrivate);
}
+TEST(IPAddressSpaceTest, TransportInfoToIPAddressSpaceProxiedIsUnknown) {
+ EXPECT_EQ(TransportInfoToIPAddressSpace(
+ ProxiedTransport(IPEndPoint(IPAddress(1, 2, 3, 4), 80))),
+ IPAddressSpace::kUnknown);
+}
+
+TEST(IPAddressSpaceTest, TransportInfoToIPAddressSpaceProxiedIgnoresOverrides) {
+ auto& command_line = *base::CommandLine::ForCurrentProcess();
+ command_line.AppendSwitchASCII(switches::kIpAddressSpaceOverrides,
+ "127.0.0.1:80=public");
+
+ EXPECT_EQ(TransportInfoToIPAddressSpace(
+ ProxiedTransport(IPEndPoint(IPAddress(127, 0, 0, 1), 80))),
+ IPAddressSpace::kUnknown);
+}
+
// Verifies that IPv4-mapped IPv6 addresses are not overridden as though they
// were the mapped IPv4 address instead.
TEST(IPAddressSpaceTest, IPEndPointToAddressSpaceOverrideIPv4MappedIPv6) {
diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy.cc b/chromium/services/network/public/cpp/is_potentially_trustworthy.cc
index 1d333c1f036..48a3edf1a20 100644
--- a/chromium/services/network/public/cpp/is_potentially_trustworthy.cc
+++ b/chromium/services/network/public/cpp/is_potentially_trustworthy.cc
@@ -115,6 +115,11 @@ bool IsValidWildcardPattern(const std::string& hostname_pattern) {
// If there is no registrar portion, the pattern is considered invalid.
if (registry_length == 0)
return false;
+ // If the registrar portion contains a wildcard, the pattern is considered
+ // invalid.
+ if (hostname_pattern.find('*', hostname_pattern.size() - registry_length) !=
+ std::string::npos)
+ return false;
// If there is no component before the registrar portion, or if the component
// immediately preceding the registrar portion contains a wildcard, the
// pattern is not considered valid.
diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy.h b/chromium/services/network/public/cpp/is_potentially_trustworthy.h
index 7e5c31dd02c..3fbfb05eede 100644
--- a/chromium/services/network/public/cpp/is_potentially_trustworthy.h
+++ b/chromium/services/network/public/cpp/is_potentially_trustworthy.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
@@ -64,6 +63,9 @@ class COMPONENT_EXPORT(NETWORK_CPP) SecureOriginAllowlist {
public:
static SecureOriginAllowlist& GetInstance();
+ SecureOriginAllowlist(const SecureOriginAllowlist&) = delete;
+ SecureOriginAllowlist& operator=(const SecureOriginAllowlist&) = delete;
+
// Returns true if |origin| has a match in the secure origin allowlist.
bool IsOriginAllowlisted(const url::Origin& origin);
@@ -111,8 +113,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) SecureOriginAllowlist {
bool has_cmdline_been_parsed_ GUARDED_BY(lock_) = false;
std::vector<std::string> auxiliary_allowlist_ GUARDED_BY(lock_);
-
- DISALLOW_COPY_AND_ASSIGN(SecureOriginAllowlist);
};
} // namespace network
diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
index 0db2a2d0839..3cc44916e7f 100644
--- a/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
+++ b/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -86,6 +86,7 @@ TEST_F(SecureOriginAllowlistTest, HostnamePatterns) {
{"http://*.foo.com", "http://bar.foo.com", false},
{"*://foo.com", "http://foo.com", false},
// Wildcards must be beyond eTLD+1.
+ {"foo.*", "http://foo.com", false},
{"*.co.uk", "http://foo.co.uk", false},
{"*.co.uk", "http://co.uk", false},
{"*.baz", "http://foo.baz", false},
@@ -117,6 +118,7 @@ TEST_F(SecureOriginAllowlistTest, HostnamePatterns) {
{"10.*.30.40", "http://10.20.30.40", true},
{"*.*.30.40", "http://10.20.30.40", true},
{"10.20.*.40", "http://10.20.30.40", false},
+ {"10.20.30.*", "http://10.20.30.40", false},
// Adjacent wildcards are not allowed.
{"**.40", "http://10.20.30.40", false},
{"10.**.40", "http://10.20.30.40", false},
@@ -126,9 +128,6 @@ TEST_F(SecureOriginAllowlistTest, HostnamePatterns) {
// test cases.
{"*.2.3.4.5", "http://2.3.4.5", false},
{"*.1.2.3.4.5", "http://2.3.4.5", false},
- // These are likely bugs.
- {"10.20.30.*", "http://10.20.30.40", true},
- {"foo.*", "http://foo.com", true},
// *'s don't work as part of a component in IPv4 addresses - they must be
// an entire component.
{"10*.20.30.40", "http://10.20.30.40", false},
diff --git a/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h b/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h
index 35482ed59dc..3fe361814d2 100644
--- a/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h
+++ b/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h
@@ -5,8 +5,9 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_TAG_MOJOM_TRAITS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_TAG_MOJOM_TRAITS_H_
+#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom.h"
+#include "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom-shared.h"
namespace mojo {
diff --git a/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc
index bea82b571a9..67ba5b97274 100644
--- a/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc
@@ -4,7 +4,6 @@
#include "services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h"
-#include "base/macros.h"
#include "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h b/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h
index 89d3e64af05..0bfd66f47f1 100644
--- a/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h
+++ b/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h
@@ -5,8 +5,9 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_MUTABLE_PARTIAL_NETWORK_TRAFFIC_ANNOTATION_TAG_MOJOM_TRAITS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_MUTABLE_PARTIAL_NETWORK_TRAFFIC_ANNOTATION_TAG_MOJOM_TRAITS_H_
+#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/network/public/mojom/mutable_partial_network_traffic_annotation_tag.mojom.h"
+#include "services/network/public/mojom/mutable_partial_network_traffic_annotation_tag.mojom-shared.h"
namespace mojo {
diff --git a/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc
index a404fbcae20..b7a2269a906 100644
--- a/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc
@@ -5,7 +5,6 @@
#include "services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h"
#include "base/check_op.h"
-#include "base/macros.h"
#include "services/network/public/mojom/mutable_partial_network_traffic_annotation_tag.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/services/network/public/cpp/net_adapters.h b/chromium/services/network/public/cpp/net_adapters.h
index cb19f83e865..678f843937d 100644
--- a/chromium/services/network/public/cpp/net_adapters.h
+++ b/chromium/services/network/public/cpp/net_adapters.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/io_buffer.h"
@@ -29,6 +28,9 @@ namespace network {
class COMPONENT_EXPORT(NETWORK_CPP) NetToMojoPendingBuffer
: public base::RefCountedThreadSafe<NetToMojoPendingBuffer> {
public:
+ NetToMojoPendingBuffer(const NetToMojoPendingBuffer&) = delete;
+ NetToMojoPendingBuffer& operator=(const NetToMojoPendingBuffer&) = delete;
+
// Begins a two-phase write to the data pipe.
//
// On success, MOJO_RESULT_OK will be returned. The ownership of the given
@@ -53,8 +55,11 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetToMojoPendingBuffer
void* buffer);
~NetToMojoPendingBuffer();
mojo::ScopedDataPipeProducerHandle handle_;
+
+ // `buffer_` is not a raw_ptr<...> for performance reasons: pointee is never
+ // protected by BackupRefPtr, because the pointer comes either from using
+ // `mmap`, MapViewOfFile or base::AllocPages directly.
void* buffer_;
- DISALLOW_COPY_AND_ASSIGN(NetToMojoPendingBuffer);
};
// Net side of a Net -> Mojo copy. The data will be read from the network and
@@ -66,16 +71,20 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetToMojoIOBuffer
// will be offset by that many bytes.
NetToMojoIOBuffer(NetToMojoPendingBuffer* pending_buffer, int offset = 0);
+ NetToMojoIOBuffer(const NetToMojoIOBuffer&) = delete;
+ NetToMojoIOBuffer& operator=(const NetToMojoIOBuffer&) = delete;
+
private:
~NetToMojoIOBuffer() override;
scoped_refptr<NetToMojoPendingBuffer> pending_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(NetToMojoIOBuffer);
};
class COMPONENT_EXPORT(NETWORK_CPP) MojoToNetPendingBuffer
: public base::RefCountedThreadSafe<MojoToNetPendingBuffer> {
public:
+ MojoToNetPendingBuffer(const MojoToNetPendingBuffer&) = delete;
+ MojoToNetPendingBuffer& operator=(const MojoToNetPendingBuffer&) = delete;
+
// Starts reading from Mojo.
//
// On success, MOJO_RESULT_OK will be returned. The ownership of the given
@@ -112,9 +121,11 @@ class COMPONENT_EXPORT(NETWORK_CPP) MojoToNetPendingBuffer
~MojoToNetPendingBuffer();
mojo::ScopedDataPipeConsumerHandle handle_;
- const void* buffer_;
- DISALLOW_COPY_AND_ASSIGN(MojoToNetPendingBuffer);
+ // `buffer_` is not a raw_ptr<...> for performance reasons: pointee is never
+ // protected by BackupRefPtr, because the pointer comes either from using
+ // `mmap`, MapViewOfFile or base::AllocPages directly.
+ const void* buffer_;
};
// Net side of a Mojo -> Net copy. The data will already be in the
diff --git a/chromium/services/network/public/cpp/network_connection_tracker.cc b/chromium/services/network/public/cpp/network_connection_tracker.cc
index d0d319b917c..d3e95409d75 100644
--- a/chromium/services/network/public/cpp/network_connection_tracker.cc
+++ b/chromium/services/network/public/cpp/network_connection_tracker.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/task_runner.h"
+#include "base/task/task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/network_change_manager.mojom.h"
diff --git a/chromium/services/network/public/cpp/network_connection_tracker.h b/chromium/services/network/public/cpp/network_connection_tracker.h
index 864a03fb718..b9174efccb3 100644
--- a/chromium/services/network/public/cpp/network_connection_tracker.h
+++ b/chromium/services/network/public/cpp/network_connection_tracker.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/observer_list_threadsafe.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
@@ -59,6 +58,9 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetworkConnectionTracker
// before the network service.
explicit NetworkConnectionTracker(BindingCallback callback);
+ NetworkConnectionTracker(const NetworkConnectionTracker&) = delete;
+ NetworkConnectionTracker& operator=(const NetworkConnectionTracker&) = delete;
+
~NetworkConnectionTracker() override;
// If connection type can be retrieved synchronously, returns true and |type|
@@ -153,8 +155,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetworkConnectionTracker
// Only the initialization and re-initialization of |this| are required to
// be bound to the same sequence.
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(NetworkConnectionTracker);
};
} // namespace network
diff --git a/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc b/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc
index 1bed9bc3368..330dcfe8f52 100644
--- a/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc
+++ b/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc
@@ -8,7 +8,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
+#include "base/ignore_result.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
@@ -95,7 +96,7 @@ class TestNetworkConnectionObserver
}
size_t num_notifications_;
- NetworkConnectionTracker* tracker_;
+ raw_ptr<NetworkConnectionTracker> tracker_;
// May be null.
std::unique_ptr<base::RunLoop> run_loop_;
network::mojom::ConnectionType expected_connection_type_;
@@ -111,6 +112,11 @@ class TestLeakyNetworkConnectionObserver
tracker->AddLeakyNetworkConnectionObserver(this);
}
+ TestLeakyNetworkConnectionObserver(
+ const TestLeakyNetworkConnectionObserver&) = delete;
+ TestLeakyNetworkConnectionObserver& operator=(
+ const TestLeakyNetworkConnectionObserver&) = delete;
+
// NetworkConnectionObserver implementation:
void OnConnectionChanged(network::mojom::ConnectionType type) override {
connection_type_ = type;
@@ -129,8 +135,6 @@ class TestLeakyNetworkConnectionObserver
private:
std::unique_ptr<base::RunLoop> run_loop_;
network::mojom::ConnectionType connection_type_;
-
- DISALLOW_COPY_AND_ASSIGN(TestLeakyNetworkConnectionObserver);
};
// A helper class to call NetworkConnectionTracker::GetConnectionType().
@@ -172,7 +176,7 @@ class ConnectionTypeGetter {
}
base::RunLoop run_loop_;
- NetworkConnectionTracker* tracker_;
+ raw_ptr<NetworkConnectionTracker> tracker_;
network::mojom::ConnectionType connection_type_;
THREAD_CHECKER(thread_checker_);
};
diff --git a/chromium/services/network/public/cpp/network_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/network_mojom_traits_unittest.cc
index 1aee1d9fc56..917ad5ae9f4 100644
--- a/chromium/services/network/public/cpp/network_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/network_mojom_traits_unittest.cc
@@ -17,6 +17,10 @@ namespace {
class NetworkStructTraitsTest : public testing::Test,
public mojom::TraitsTestService {
+ public:
+ NetworkStructTraitsTest(const NetworkStructTraitsTest&) = delete;
+ NetworkStructTraitsTest& operator=(const NetworkStructTraitsTest&) = delete;
+
protected:
NetworkStructTraitsTest() = default;
@@ -36,7 +40,6 @@ class NetworkStructTraitsTest : public testing::Test,
base::test::SingleThreadTaskEnvironment task_environment_;
mojo::ReceiverSet<TraitsTestService> traits_test_receivers_;
- DISALLOW_COPY_AND_ASSIGN(NetworkStructTraitsTest);
};
} // namespace
diff --git a/chromium/services/network/public/cpp/network_quality_tracker.cc b/chromium/services/network/public/cpp/network_quality_tracker.cc
index efe35a7d3d4..9584aca0c40 100644
--- a/chromium/services/network/public/cpp/network_quality_tracker.cc
+++ b/chromium/services/network/public/cpp/network_quality_tracker.cc
@@ -119,9 +119,9 @@ void NetworkQualityTracker::OnNetworkQualityChanged(
return;
// If the RTT values are unavailable, set them to value 0.
- if (http_rtt < base::TimeDelta())
+ if (http_rtt.is_negative())
http_rtt = base::TimeDelta();
- if (transport_rtt < base::TimeDelta())
+ if (transport_rtt.is_negative())
transport_rtt = base::TimeDelta();
// If the bandwidth value is unavailable, set it to the maximum possible
diff --git a/chromium/services/network/public/cpp/network_quality_tracker.h b/chromium/services/network/public/cpp/network_quality_tracker.h
index 74128dd88fb..340559b7f62 100644
--- a/chromium/services/network/public/cpp/network_quality_tracker.h
+++ b/chromium/services/network/public/cpp/network_quality_tracker.h
@@ -7,7 +7,6 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -26,6 +25,11 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetworkQualityTracker
public:
class COMPONENT_EXPORT(NETWORK_CPP) EffectiveConnectionTypeObserver {
public:
+ EffectiveConnectionTypeObserver(const EffectiveConnectionTypeObserver&) =
+ delete;
+ EffectiveConnectionTypeObserver& operator=(
+ const EffectiveConnectionTypeObserver&) = delete;
+
// Called when there is a change in the effective connection type. The
// |observer| is notified of the current effective connection type on the
// same thread on which it was added.
@@ -35,9 +39,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetworkQualityTracker
protected:
EffectiveConnectionTypeObserver() {}
virtual ~EffectiveConnectionTypeObserver() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(EffectiveConnectionTypeObserver);
};
// Observes changes in the HTTP RTT, transport RTT or downstream throughput
@@ -72,6 +73,9 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetworkQualityTracker
explicit NetworkQualityTracker(
base::RepeatingCallback<network::mojom::NetworkService*()> callback);
+ NetworkQualityTracker(const NetworkQualityTracker&) = delete;
+ NetworkQualityTracker& operator=(const NetworkQualityTracker&) = delete;
+
~NetworkQualityTracker() override;
// Returns the current estimate of the effective connection type.
@@ -182,8 +186,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) NetworkQualityTracker
receiver_{this};
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(NetworkQualityTracker);
};
} // namespace network
diff --git a/chromium/services/network/public/cpp/network_quality_tracker_unittest.cc b/chromium/services/network/public/cpp/network_quality_tracker_unittest.cc
index a7044769cf6..8bdb3ead83b 100644
--- a/chromium/services/network/public/cpp/network_quality_tracker_unittest.cc
+++ b/chromium/services/network/public/cpp/network_quality_tracker_unittest.cc
@@ -7,7 +7,7 @@
#include <limits>
#include "base/bind.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
@@ -81,7 +81,7 @@ class TestEffectiveConnectionTypeObserver
private:
size_t num_notifications_;
- NetworkQualityTracker* tracker_;
+ raw_ptr<NetworkQualityTracker> tracker_;
// May be null.
std::unique_ptr<base::RunLoop> run_loop_;
net::EffectiveConnectionType expected_effective_connection_type_;
@@ -160,7 +160,7 @@ class TestRTTAndThroughputEstimatesObserver
private:
size_t num_notifications_;
- NetworkQualityTracker* tracker_;
+ raw_ptr<NetworkQualityTracker> tracker_;
// May be null.
std::unique_ptr<base::RunLoop> run_loop_;
base::TimeDelta http_rtt_;
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 6c6566c963c..b35d4335bdb 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
@@ -4,6 +4,7 @@
#include "services/network/public/cpp/optional_trust_token_params.h"
+#include "base/ignore_result.h"
#include "base/test/gtest_util.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
diff --git a/chromium/services/network/public/cpp/origin_agent_cluster_parser.cc b/chromium/services/network/public/cpp/origin_agent_cluster_parser.cc
index af23159a5c2..9676ad5c508 100644
--- a/chromium/services/network/public/cpp/origin_agent_cluster_parser.cc
+++ b/chromium/services/network/public/cpp/origin_agent_cluster_parser.cc
@@ -7,9 +7,14 @@
namespace network {
-bool ParseOriginAgentCluster(const std::string& header_value) {
+mojom::OriginAgentClusterValue ParseOriginAgentCluster(
+ const std::string& header_value) {
const auto item = net::structured_headers::ParseItem(header_value);
- return item && item->item.is_boolean() && item->item.GetBoolean();
+ if (!item || !item->item.is_boolean())
+ return mojom::OriginAgentClusterValue::kAbsent;
+ if (item->item.GetBoolean())
+ return mojom::OriginAgentClusterValue::kTrue;
+ return mojom::OriginAgentClusterValue::kFalse;
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/origin_agent_cluster_parser.h b/chromium/services/network/public/cpp/origin_agent_cluster_parser.h
index 04610c5fff0..8dd4d339df6 100644
--- a/chromium/services/network/public/cpp/origin_agent_cluster_parser.h
+++ b/chromium/services/network/public/cpp/origin_agent_cluster_parser.h
@@ -7,6 +7,7 @@
#include <string>
#include "base/component_export.h"
+#include "services/network/public/mojom/parsed_headers.mojom.h"
namespace network {
@@ -16,7 +17,7 @@ namespace network {
// See the comment in network::PopulateParsedHeaders for restrictions on this
// function.
COMPONENT_EXPORT(NETWORK_CPP)
-bool ParseOriginAgentCluster(const std::string&);
+mojom::OriginAgentClusterValue ParseOriginAgentCluster(const std::string&);
} // namespace network
diff --git a/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc b/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc
index 11b2c3194c4..55f62e1f887 100644
--- a/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc
+++ b/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc
@@ -12,20 +12,28 @@
namespace network {
TEST(OriginAgentClusterHeaderTest, Parse) {
- EXPECT_EQ(ParseOriginAgentCluster(""), false);
-
- EXPECT_EQ(ParseOriginAgentCluster("?1"), true);
- EXPECT_EQ(ParseOriginAgentCluster("?0"), false);
-
- EXPECT_EQ(ParseOriginAgentCluster("?1;param"), true);
- EXPECT_EQ(ParseOriginAgentCluster("?1;param=value"), true);
- EXPECT_EQ(ParseOriginAgentCluster("?1;param=value;param2=value2"), true);
-
- EXPECT_EQ(ParseOriginAgentCluster("true"), false);
- EXPECT_EQ(ParseOriginAgentCluster("\"?1\""), false);
- EXPECT_EQ(ParseOriginAgentCluster("1"), false);
- EXPECT_EQ(ParseOriginAgentCluster("?2"), false);
- EXPECT_EQ(ParseOriginAgentCluster("(?1)"), false);
+ using mojom::OriginAgentClusterValue;
+
+ EXPECT_EQ(ParseOriginAgentCluster(""), OriginAgentClusterValue::kAbsent);
+
+ EXPECT_EQ(ParseOriginAgentCluster("?1"), OriginAgentClusterValue::kTrue);
+ EXPECT_EQ(ParseOriginAgentCluster("?0"), OriginAgentClusterValue::kFalse);
+
+ EXPECT_EQ(ParseOriginAgentCluster("?1;param"),
+ OriginAgentClusterValue::kTrue);
+ EXPECT_EQ(ParseOriginAgentCluster("?1;param=value"),
+ OriginAgentClusterValue::kTrue);
+ EXPECT_EQ(ParseOriginAgentCluster("?1;param=value;param2=value2"),
+ OriginAgentClusterValue::kTrue);
+ EXPECT_EQ(ParseOriginAgentCluster("?0;param=value"),
+ OriginAgentClusterValue::kFalse);
+
+ EXPECT_EQ(ParseOriginAgentCluster("true"), OriginAgentClusterValue::kAbsent);
+ EXPECT_EQ(ParseOriginAgentCluster("\"?1\""),
+ OriginAgentClusterValue::kAbsent);
+ EXPECT_EQ(ParseOriginAgentCluster("1"), OriginAgentClusterValue::kAbsent);
+ EXPECT_EQ(ParseOriginAgentCluster("?2"), OriginAgentClusterValue::kAbsent);
+ EXPECT_EQ(ParseOriginAgentCluster("(?1)"), OriginAgentClusterValue::kAbsent);
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/parsed_headers.cc b/chromium/services/network/public/cpp/parsed_headers.cc
index 9ff7a481fe3..b9ea67f7a76 100644
--- a/chromium/services/network/public/cpp/parsed_headers.cc
+++ b/chromium/services/network/public/cpp/parsed_headers.cc
@@ -39,22 +39,14 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders(
ParseCrossOriginOpenerPolicy(*headers);
std::string origin_agent_cluster;
- if (headers->GetNormalizedHeader("Origin-Agent-Cluster",
- &origin_agent_cluster)) {
- parsed_headers->origin_agent_cluster =
- ParseOriginAgentCluster(origin_agent_cluster);
- }
+ headers->GetNormalizedHeader("Origin-Agent-Cluster", &origin_agent_cluster);
+ parsed_headers->origin_agent_cluster =
+ ParseOriginAgentCluster(origin_agent_cluster);
std::string accept_ch;
if (headers->GetNormalizedHeader("Accept-CH", &accept_ch))
parsed_headers->accept_ch = ParseClientHintsHeader(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);
- }
-
std::string critical_ch;
if (headers->GetNormalizedHeader("Critical-CH", &critical_ch))
parsed_headers->critical_ch = ParseClientHintsHeader(critical_ch);
diff --git a/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc b/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc
index 43dc9c896ea..06d8f04cd4d 100644
--- a/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc
@@ -6,7 +6,6 @@
#include "net/base/proxy_string_util.h"
#include "url/gurl.h"
-#include "url/mojom/url_gurl_mojom_traits.h"
namespace mojo {
diff --git a/chromium/services/network/public/cpp/proxy_config_mojom_traits.h b/chromium/services/network/public/cpp/proxy_config_mojom_traits.h
index c3211065e82..e355c5b5c20 100644
--- a/chromium/services/network/public/cpp/proxy_config_mojom_traits.h
+++ b/chromium/services/network/public/cpp/proxy_config_mojom_traits.h
@@ -5,9 +5,13 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_PROXY_CONFIG_MOJOM_TRAITS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_PROXY_CONFIG_MOJOM_TRAITS_H_
+#include <string>
+#include <vector>
+
#include "base/component_export.h"
-#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
#include "mojo/public/cpp/base/big_string_mojom_traits.h"
+#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/proxy_resolution/proxy_bypass_rules.h"
#include "net/proxy_resolution/proxy_config.h"
#include "net/proxy_resolution/proxy_config_with_annotation.h"
@@ -19,7 +23,7 @@
namespace mojo {
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+struct COMPONENT_EXPORT(NETWORK_CPP_PROXY_CONFIG)
StructTraits<network::mojom::ProxyBypassRulesDataView,
net::ProxyBypassRules> {
public:
@@ -29,7 +33,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
};
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+struct COMPONENT_EXPORT(NETWORK_CPP_PROXY_CONFIG)
StructTraits<network::mojom::ProxyListDataView, net::ProxyList> {
public:
static std::vector<std::string> proxies(const net::ProxyList& r);
@@ -38,7 +42,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
};
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+struct COMPONENT_EXPORT(NETWORK_CPP_PROXY_CONFIG)
EnumTraits<network::mojom::ProxyRulesType,
net::ProxyConfig::ProxyRules::Type> {
public:
@@ -49,7 +53,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
};
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+struct COMPONENT_EXPORT(NETWORK_CPP_PROXY_CONFIG)
StructTraits<network::mojom::ProxyRulesDataView,
net::ProxyConfig::ProxyRules> {
public:
@@ -89,9 +93,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
net::ProxyConfig::ProxyRules* out_proxy_rules);
};
-
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+struct COMPONENT_EXPORT(NETWORK_CPP_PROXY_CONFIG)
StructTraits<network::mojom::ProxyConfigDataView, net::ProxyConfig> {
public:
static bool auto_detect(const net::ProxyConfig& r) { return r.auto_detect(); }
diff --git a/chromium/services/network/public/cpp/proxy_config_with_annotation_mojom_traits.h b/chromium/services/network/public/cpp/proxy_config_with_annotation_mojom_traits.h
index a2972373500..fcaaa3db98c 100644
--- a/chromium/services/network/public/cpp/proxy_config_with_annotation_mojom_traits.h
+++ b/chromium/services/network/public/cpp/proxy_config_with_annotation_mojom_traits.h
@@ -6,7 +6,9 @@
#define SERVICES_NETWORK_PUBLIC_CPP_PROXY_CONFIG_WITH_ANNOTATION_MOJOM_TRAITS_H_
#include "base/component_export.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/proxy_resolution/proxy_config_with_annotation.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h"
#include "services/network/public/cpp/proxy_config_mojom_traits.h"
#include "services/network/public/mojom/proxy_config_with_annotation.mojom-shared.h"
@@ -16,7 +18,7 @@
namespace mojo {
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+struct COMPONENT_EXPORT(NETWORK_CPP_PROXY_CONFIG)
StructTraits<network::mojom::ProxyConfigWithAnnotationDataView,
net::ProxyConfigWithAnnotation> {
public:
diff --git a/chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.cc b/chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.cc
new file mode 100644
index 00000000000..d43e38e1680
--- /dev/null
+++ b/chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.cc
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/reporting_api_endpoint_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<network::mojom::ReportingApiEndpointDataView,
+ net::ReportingEndpoint>::
+ Read(network::mojom::ReportingApiEndpointDataView data,
+ net::ReportingEndpoint* out) {
+ if (!data.ReadUrl(&out->info.url))
+ return false;
+ if (!data.ReadOrigin(&out->group_key.origin))
+ return false;
+ if (!data.ReadGroupName(&out->group_key.group_name))
+ return false;
+ if (!data.ReadNetworkIsolationKey(&out->group_key.network_isolation_key))
+ return false;
+ if (!data.ReadReportingSource(&out->group_key.reporting_source))
+ return false;
+
+ out->stats.attempted_uploads = data.attempted_uploads();
+ out->stats.successful_uploads = data.successful_uploads();
+ out->stats.attempted_reports = data.attempted_reports();
+ out->stats.successful_reports = data.successful_reports();
+ out->info.priority = data.priority();
+ out->info.weight = data.weight();
+ return true;
+}
+
+} // namespace mojo \ No newline at end of file
diff --git a/chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.h b/chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.h
new file mode 100644
index 00000000000..53f5ab0694b
--- /dev/null
+++ b/chromium/services/network/public/cpp/reporting_api_endpoint_mojom_traits.h
@@ -0,0 +1,73 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_REPORTING_API_ENDPOINT_MOJOM_TRAITS_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_REPORTING_API_ENDPOINT_MOJOM_TRAITS_H_
+
+#include "base/values.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "net/base/network_isolation_key.h"
+#include "net/reporting/reporting_endpoint.h"
+#include "services/network/public/cpp/network_isolation_key_mojom_traits.h"
+#include "services/network/public/mojom/reporting_service.mojom-shared.h"
+#include "url/mojom/url_gurl_mojom_traits.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<network::mojom::ReportingApiEndpointDataView,
+ net::ReportingEndpoint> {
+ static const GURL& url(const net::ReportingEndpoint& endpoint) {
+ return endpoint.info.url;
+ }
+
+ static int32_t attempted_uploads(const net::ReportingEndpoint& endpoint) {
+ return endpoint.stats.attempted_uploads;
+ }
+
+ static int32_t successful_uploads(const net::ReportingEndpoint& endpoint) {
+ return endpoint.stats.successful_uploads;
+ }
+
+ static int32_t attempted_reports(const net::ReportingEndpoint& endpoint) {
+ return endpoint.stats.attempted_reports;
+ }
+
+ static int32_t successful_reports(const net::ReportingEndpoint& endpoint) {
+ return endpoint.stats.successful_reports;
+ }
+
+ static int32_t priority(const net::ReportingEndpoint& endpoint) {
+ return endpoint.info.priority;
+ }
+
+ static int32_t weight(const net::ReportingEndpoint& endpoint) {
+ return endpoint.info.weight;
+ }
+
+ static const url::Origin& origin(const net::ReportingEndpoint& endpoint) {
+ return endpoint.group_key.origin;
+ }
+
+ static const std::string& group_name(const net::ReportingEndpoint& endpoint) {
+ return endpoint.group_key.group_name;
+ }
+
+ static const net::NetworkIsolationKey network_isolation_key(
+ const net::ReportingEndpoint& endpoint) {
+ return endpoint.group_key.network_isolation_key;
+ }
+
+ static const absl::optional<base::UnguessableToken>& reporting_source(
+ const net::ReportingEndpoint& endpoint) {
+ return endpoint.group_key.reporting_source;
+ }
+
+ static bool Read(network::mojom::ReportingApiEndpointDataView data,
+ net::ReportingEndpoint* out);
+};
+
+} // namespace mojo
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_REPORTING_API_ENDPOINT_MOJOM_TRAITS_H_
diff --git a/chromium/services/network/public/cpp/reporting_api_report_mojom_traits.h b/chromium/services/network/public/cpp/reporting_api_report_mojom_traits.h
index cfcd323af3a..7564a5e6d31 100644
--- a/chromium/services/network/public/cpp/reporting_api_report_mojom_traits.h
+++ b/chromium/services/network/public/cpp/reporting_api_report_mojom_traits.h
@@ -11,7 +11,7 @@
#include "mojo/public/cpp/base/values_mojom_traits.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/reporting/reporting_report.h"
-#include "services/network/public/mojom/reporting_report.mojom-shared.h"
+#include "services/network/public/mojom/reporting_service.mojom-shared.h"
#include "url/mojom/url_gurl_mojom_traits.h"
namespace mojo {
diff --git a/chromium/services/network/public/cpp/request_destination.cc b/chromium/services/network/public/cpp/request_destination.cc
index c61db5ed468..a7328528962 100644
--- a/chromium/services/network/public/cpp/request_destination.cc
+++ b/chromium/services/network/public/cpp/request_destination.cc
@@ -55,9 +55,18 @@ const char* RequestDestinationToString(
return "worker";
case network::mojom::RequestDestination::kXslt:
return "xslt";
+ case network::mojom::RequestDestination::kFencedframe:
+ return "fencedframe";
}
NOTREACHED();
return "empty";
}
+bool IsRequestDestinationEmbeddedFrame(
+ network::mojom::RequestDestination dest) {
+ return dest == network::mojom::RequestDestination::kFrame ||
+ dest == network::mojom::RequestDestination::kIframe ||
+ dest == network::mojom::RequestDestination::kFencedframe;
+}
+
} // namespace network
diff --git a/chromium/services/network/public/cpp/request_destination.h b/chromium/services/network/public/cpp/request_destination.h
index 095e166666f..4d85c06b52a 100644
--- a/chromium/services/network/public/cpp/request_destination.h
+++ b/chromium/services/network/public/cpp/request_destination.h
@@ -15,6 +15,10 @@ namespace network {
COMPONENT_EXPORT(NETWORK_CPP)
const char* RequestDestinationToString(network::mojom::RequestDestination dest);
+// Returns whether the destination is a frame embedded in the document.
+COMPONENT_EXPORT(NETWORK_CPP)
+bool IsRequestDestinationEmbeddedFrame(network::mojom::RequestDestination dest);
+
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_REQUEST_DESTINATION_H_
diff --git a/chromium/services/network/public/cpp/resource_request.cc b/chromium/services/network/public/cpp/resource_request.cc
index a24972bd0d0..f14c99863eb 100644
--- a/chromium/services/network/public/cpp/resource_request.cc
+++ b/chromium/services/network/public/cpp/resource_request.cc
@@ -8,6 +8,7 @@
#include "base/strings/string_number_conversions.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
+#include "net/log/net_log_source.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/url_request.mojom.h"
@@ -79,6 +80,13 @@ bool OptionalWebBundleTokenParamsEqualsForTesting( // IN-TEST
(lhs && rhs && lhs->EqualsForTesting(*rhs)); // IN-TEST
}
+bool OptionalNetLogInfoEqualsForTesting(
+ const absl::optional<net::NetLogSource>& lhs,
+ const absl::optional<net::NetLogSource>& rhs) {
+ bool equal_members = lhs && rhs && lhs.value() == rhs.value();
+ return (!lhs && !rhs) || equal_members;
+}
+
base::debug::CrashKeyString* GetRequestUrlCrashKey() {
static auto* crash_key = base::debug::AllocateCrashKeyString(
"request_url", base::debug::CrashKeySize::Size256);
@@ -188,10 +196,6 @@ ResourceRequest::WebBundleTokenParams::CloneHandle() const {
return new_remote;
}
-ResourceRequest::NetLogParams::NetLogParams() = default;
-ResourceRequest::NetLogParams::NetLogParams(uint32_t id) : source_id(id) {}
-ResourceRequest::NetLogParams::~NetLogParams() = default;
-
ResourceRequest::ResourceRequest() = default;
ResourceRequest::ResourceRequest(const ResourceRequest& request) = default;
ResourceRequest::~ResourceRequest() = default;
@@ -212,7 +216,6 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
resource_type == request.resource_type &&
priority == request.priority &&
devtools_stack_id == request.devtools_stack_id &&
- should_reset_appcache == request.should_reset_appcache &&
is_external_request == request.is_external_request &&
cors_preflight_policy == request.cors_preflight_policy &&
originated_from_service_worker ==
@@ -254,6 +257,10 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
trust_token_params == request.trust_token_params &&
OptionalWebBundleTokenParamsEqualsForTesting( // IN-TEST
web_bundle_token_params, request.web_bundle_token_params) &&
+ OptionalNetLogInfoEqualsForTesting(net_log_create_info,
+ request.net_log_create_info) &&
+ OptionalNetLogInfoEqualsForTesting(net_log_reference_info,
+ request.net_log_reference_info) &&
target_ip_address_space == request.target_ip_address_space;
}
diff --git a/chromium/services/network/public/cpp/resource_request.h b/chromium/services/network/public/cpp/resource_request.h
index 2857fb52a54..7c835d24442 100644
--- a/chromium/services/network/public/cpp/resource_request.h
+++ b/chromium/services/network/public/cpp/resource_request.h
@@ -18,6 +18,7 @@
#include "net/cookies/site_for_cookies.h"
#include "net/filter/source_stream.h"
#include "net/http/http_request_headers.h"
+#include "net/log/net_log_source.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"
@@ -101,16 +102,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
int32_t render_process_id = -1;
};
- // Typemapped to network.mojom.NetLogParams, see comments there for
- // details of each field.
- struct COMPONENT_EXPORT(NETWORK_CPP_BASE) NetLogParams {
- NetLogParams();
- explicit NetLogParams(uint32_t id);
- ~NetLogParams();
-
- uint32_t source_id;
- };
-
ResourceRequest();
ResourceRequest(const ResourceRequest& request);
~ResourceRequest();
@@ -134,6 +125,10 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
// once Chrome Platform Apps are gone.
absl::optional<url::Origin> isolated_world_origin;
+ // The chain of URLs seen during navigation redirects. This should only
+ // contain values if the mode is `RedirectMode::kNavigate`.
+ std::vector<GURL> navigation_redirect_chain;
+
GURL referrer;
net::ReferrerPolicy referrer_policy = net::ReferrerPolicy::NEVER_CLEAR;
net::HttpRequestHeaders headers;
@@ -141,7 +136,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
int load_flags = 0;
int resource_type = 0;
net::RequestPriority priority = net::IDLE;
- bool should_reset_appcache = false;
bool is_external_request = false;
mojom::CorsPreflightPolicy cors_preflight_policy =
mojom::CorsPreflightPolicy::kConsiderPreflight;
@@ -153,6 +147,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
mojom::RedirectMode redirect_mode = mojom::RedirectMode::kFollow;
std::string fetch_integrity;
mojom::RequestDestination destination = mojom::RequestDestination::kEmpty;
+ mojom::RequestDestination original_destination =
+ mojom::RequestDestination::kEmpty;
scoped_refptr<ResourceRequestBody> request_body;
bool keepalive = false;
bool has_user_gesture = false;
@@ -186,7 +182,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
// decoding any non-listed stream types.
absl::optional<std::vector<net::SourceStream::SourceType>>
devtools_accepted_stream_types;
- absl::optional<NetLogParams> net_log_params;
+ absl::optional<net::NetLogSource> net_log_create_info;
+ absl::optional<net::NetLogSource> net_log_reference_info;
mojom::IPAddressSpace target_ip_address_space =
mojom::IPAddressSpace::kUnknown;
};
diff --git a/chromium/services/network/public/cpp/resource_request_body.h b/chromium/services/network/public/cpp/resource_request_body.h
index 4c0e150a1f5..e8aabfe1f69 100644
--- a/chromium/services/network/public/cpp/resource_request_body.h
+++ b/chromium/services/network/public/cpp/resource_request_body.h
@@ -12,7 +12,6 @@
#include "base/component_export.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/data_element.h"
@@ -35,6 +34,9 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
ResourceRequestBody();
+ ResourceRequestBody(const ResourceRequestBody&) = delete;
+ ResourceRequestBody& operator=(const ResourceRequestBody&) = delete;
+
// Creates ResourceRequestBody that holds a copy of |bytes|.
static scoped_refptr<ResourceRequestBody> CreateFromBytes(const char* bytes,
size_t length);
@@ -112,8 +114,6 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
bool contains_sensitive_info_;
bool allow_http1_for_streaming_upload_ = true;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceRequestBody);
};
} // namespace network
diff --git a/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h b/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h
index 34f9b48f7e9..70f58ea6eac 100644
--- a/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h
+++ b/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_PUBLIC_CPP_SELF_DELETING_URL_LOADER_FACTORY_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -20,6 +19,11 @@ namespace network {
// which should be owned by the set of its receivers.
class COMPONENT_EXPORT(NETWORK_CPP) SelfDeletingURLLoaderFactory
: public mojom::URLLoaderFactory {
+ public:
+ SelfDeletingURLLoaderFactory(const SelfDeletingURLLoaderFactory&) = delete;
+ SelfDeletingURLLoaderFactory& operator=(const SelfDeletingURLLoaderFactory&) =
+ delete;
+
protected:
// Constructs SelfDeletingURLLoaderFactory object that will self-delete
// once all receivers disconnect (including |factory_receiver| below as well
@@ -51,8 +55,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) SelfDeletingURLLoaderFactory
void OnDisconnect();
mojo::ReceiverSet<mojom::URLLoaderFactory> receivers_;
-
- DISALLOW_COPY_AND_ASSIGN(SelfDeletingURLLoaderFactory);
};
} // namespace network
diff --git a/chromium/services/network/public/cpp/server/http_connection.h b/chromium/services/network/public/cpp/server/http_connection.h
index 0ce8aacd0db..589cc91979a 100644
--- a/chromium/services/network/public/cpp/server/http_connection.h
+++ b/chromium/services/network/public/cpp/server/http_connection.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
diff --git a/chromium/services/network/public/cpp/server/http_server.cc b/chromium/services/network/public/cpp/server/http_server.cc
index e022e32d8a5..5a548bc56aa 100644
--- a/chromium/services/network/public/cpp/server/http_server.cc
+++ b/chromium/services/network/public/cpp/server/http_server.cc
@@ -10,9 +10,9 @@
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -277,7 +277,8 @@ void HttpServer::HandleReadResult(HttpConnection* connection, MojoResult rv) {
Close(connection->id());
return;
}
- delegate_->OnWebSocketMessage(connection->id(), std::move(message));
+ if (result == WebSocket::FRAME_OK_FINAL)
+ delegate_->OnWebSocketMessage(connection->id(), std::move(message));
if (HasClosedConnection(connection)) {
return;
}
diff --git a/chromium/services/network/public/cpp/server/http_server.h b/chromium/services/network/public/cpp/server/http_server.h
index 967cf8ddbd4..46ac7194ac2 100644
--- a/chromium/services/network/public/cpp/server/http_server.h
+++ b/chromium/services/network/public/cpp/server/http_server.h
@@ -13,7 +13,7 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -143,7 +143,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) HttpServer {
bool HasClosedConnection(HttpConnection* connection);
const mojo::Remote<mojom::TCPServerSocket> server_socket_;
- HttpServer::Delegate* const delegate_;
+ const raw_ptr<HttpServer::Delegate> delegate_;
int last_id_;
std::map<int, std::unique_ptr<HttpConnection>> id_to_connection_;
diff --git a/chromium/services/network/public/cpp/server/http_server_unittest.cc b/chromium/services/network/public/cpp/server/http_server_unittest.cc
index 783be348cc8..8cca7451b86 100644
--- a/chromium/services/network/public/cpp/server/http_server_unittest.cc
+++ b/chromium/services/network/public/cpp/server/http_server_unittest.cc
@@ -322,32 +322,52 @@ class WebSocketTest : public HttpServerTest {
};
class WebSocketAcceptingTest : public WebSocketTest {
+ public:
void OnWebSocketRequest(int connection_id,
const HttpServerRequestInfo& info) override {
HttpServerTest::OnHttpRequest(connection_id, info);
server_->AcceptWebSocket(connection_id, info, TRAFFIC_ANNOTATION_FOR_TESTS);
}
+
+ void OnWebSocketMessage(int connection_id, std::string data) override {
+ message_ = data;
+ if (run_loop_) {
+ run_loop_->Quit();
+ }
+ }
+
+ const std::string& GetMessage() {
+ run_loop_ = std::make_unique<base::RunLoop>();
+ run_loop_->Run();
+ run_loop_.reset();
+ return message_;
+ }
+
+ private:
+ std::string message_;
+ std::unique_ptr<base::RunLoop> run_loop_;
};
-constexpr uint8_t kFinalBit = 0x80;
-constexpr uint8_t kMaskBit = 0x80;
-constexpr size_t kMaskingKeyWidthInBytes = 4;
-
-std::string EncodeControlFrame(std::string message,
- net::WebSocketFrameHeader::OpCodeEnum op_code,
- int mask) {
- const char mask_key_bit = mask ? kMaskBit : 0;
- std::string encoded_frame = {
- static_cast<char>(kFinalBit | op_code),
- static_cast<char>(mask_key_bit | message.length())};
- if (mask != 0) {
- const std::string kMaskBytes(reinterpret_cast<char*>(&mask), 4);
- encoded_frame += kMaskBytes;
- for (size_t i = 0; i < message.length(); ++i) // Mask the payload.
- message[i] = message[i] ^ kMaskBytes[i % kMaskingKeyWidthInBytes];
+std::string EncodeFrame(std::string message,
+ net::WebSocketFrameHeader::OpCodeEnum op_code,
+ bool mask,
+ bool finish) {
+ net::WebSocketFrameHeader header(op_code);
+ header.final = finish;
+ header.masked = mask;
+ header.payload_length = message.size();
+ const int header_size = GetWebSocketFrameHeaderSize(header);
+ std::string frame_header;
+ frame_header.resize(header_size);
+ if (mask) {
+ net::WebSocketMaskingKey masking_key = net::GenerateWebSocketMaskingKey();
+ WriteWebSocketFrameHeader(header, &masking_key, &frame_header[0],
+ header_size);
+ MaskWebSocketFramePayload(masking_key, 0, &message[0], message.size());
+ } else {
+ WriteWebSocketFrameHeader(header, nullptr, &frame_header[0], header_size);
}
- encoded_frame += message;
- return encoded_frame;
+ return frame_header + message;
}
TEST_F(HttpServerTest, SetNonexistingConnectionBuffer) {
@@ -562,16 +582,17 @@ TEST_F(WebSocketAcceptingTest, SendPingFrameWithNoMessage) {
"Sec-WebSocket-Key: key\r\n\r\n");
RunUntilRequestsReceived(1);
ASSERT_TRUE(client.ReadResponse(&response));
- const std::string kMessage = "";
- constexpr int kMask = 654321;
- const std::string kPingFrame = EncodeControlFrame(
- kMessage, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePing, kMask);
- const std::string kPongFrame = EncodeControlFrame(
- kMessage, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong, 0);
- client.Send(kPingFrame);
+ const std::string message = "";
+ const std::string ping_frame =
+ EncodeFrame(message, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePing,
+ /* mask= */ true, /* finish= */ true);
+ const std::string pong_frame =
+ EncodeFrame(message, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong,
+ /* mask= */ false, /* finish= */ true);
+ client.Send(ping_frame);
response.clear();
- ASSERT_TRUE(client.Read(&response, kPongFrame.length()));
- EXPECT_EQ(response, kPongFrame);
+ ASSERT_TRUE(client.Read(&response, pong_frame.length()));
+ EXPECT_EQ(response, pong_frame);
}
TEST_F(WebSocketAcceptingTest, SendPingFrameWithMessage) {
@@ -586,16 +607,17 @@ TEST_F(WebSocketAcceptingTest, SendPingFrameWithMessage) {
"Sec-WebSocket-Key: key\r\n\r\n");
RunUntilRequestsReceived(1);
ASSERT_TRUE(client.ReadResponse(&response));
- const std::string kMessage = "hello";
- constexpr int kMask = 654321;
- const std::string kPingFrame = EncodeControlFrame(
- kMessage, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePing, kMask);
- const std::string kPongFrame = EncodeControlFrame(
- kMessage, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong, 0);
- client.Send(kPingFrame);
+ const std::string message = "hello";
+ const std::string ping_frame =
+ EncodeFrame(message, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePing,
+ /* mask= */ true, /* finish= */ true);
+ const std::string pong_frame =
+ EncodeFrame(message, net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong,
+ /* mask= */ false, /* finish= */ true);
+ client.Send(ping_frame);
response.clear();
- ASSERT_TRUE(client.Read(&response, kPongFrame.length()));
- EXPECT_EQ(response, kPongFrame);
+ ASSERT_TRUE(client.Read(&response, pong_frame.length()));
+ EXPECT_EQ(response, pong_frame);
}
TEST_F(WebSocketAcceptingTest, SendPongFrame) {
@@ -610,34 +632,49 @@ TEST_F(WebSocketAcceptingTest, SendPongFrame) {
"Sec-WebSocket-Key: key\r\n\r\n");
RunUntilRequestsReceived(1);
ASSERT_TRUE(client.ReadResponse(&response));
- constexpr int kMask = 654321;
- const std::string kPingFrame = EncodeControlFrame(
- "", net::WebSocketFrameHeader::OpCodeEnum::kOpCodePing, kMask);
- const std::string kPongFrameSend = EncodeControlFrame(
- "", net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong, kMask);
- const std::string kPongFrameReceive = EncodeControlFrame(
- "", net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong, 0);
- client.Send(kPongFrameSend);
- client.Send(kPingFrame);
+ const std::string ping_frame = EncodeFrame(
+ /* message= */ "", net::WebSocketFrameHeader::OpCodeEnum::kOpCodePing,
+ /* mask= */ true, /* finish= */ true);
+ const std::string pong_frame_send = EncodeFrame(
+ /* message= */ "", net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong,
+ /* mask= */ true, /* finish= */ true);
+ const std::string pong_frame_receive = EncodeFrame(
+ /* message= */ "", net::WebSocketFrameHeader::OpCodeEnum::kOpCodePong,
+ /* mask= */ false, /* finish= */ true);
+ client.Send(pong_frame_send);
+ client.Send(ping_frame);
response.clear();
- ASSERT_TRUE(client.Read(&response, kPongFrameReceive.length()));
- EXPECT_EQ(response, kPongFrameReceive);
+ ASSERT_TRUE(client.Read(&response, pong_frame_receive.length()));
+ EXPECT_EQ(response, pong_frame_receive);
}
-TEST_F(HttpServerTest, RequestWithTooLargeBody) {
+TEST_F(WebSocketAcceptingTest, SendLongTextFrame) {
TestHttpClient client;
CreateConnection(&client);
+ std::string response;
client.Send(
"GET /test HTTP/1.1\r\n"
- "Content-Length: 1073741824\r\n\r\n");
- std::string response;
+ "Upgrade: WebSocket\r\n"
+ "Connection: SomethingElse, Upgrade\r\n"
+ "Sec-WebSocket-Version: 8\r\n"
+ "Sec-WebSocket-Key: key\r\n\r\n");
+ RunUntilRequestsReceived(1);
ASSERT_TRUE(client.ReadResponse(&response));
- EXPECT_EQ(
- "HTTP/1.1 500 Internal Server Error\r\n"
- "Content-Length:53\r\n"
- "Content-Type:text/html\r\n\r\n"
- "request content-length too big or unknown: 1073741824",
- response);
+ constexpr int kFrameSize = 100000;
+ const std::string text_frame(kFrameSize, 'a');
+ const std::string continuation_frame(kFrameSize, 'b');
+ const std::string text_encoded_frame = EncodeFrame(
+ text_frame, net::WebSocketFrameHeader::OpCodeEnum::kOpCodeText,
+ /* mask= */ true,
+ /* finish= */ false);
+ const std::string continuation_encoded_frame =
+ EncodeFrame(continuation_frame,
+ net::WebSocketFrameHeader::OpCodeEnum::kOpCodeContinuation,
+ /* mask= */ true, /* finish= */ true);
+ client.Send(text_encoded_frame);
+ client.Send(continuation_encoded_frame);
+ std::string received_message = GetMessage();
+ EXPECT_EQ(received_message, text_frame + continuation_frame);
}
TEST_F(HttpServerTest, Send200) {
diff --git a/chromium/services/network/public/cpp/server/web_socket.cc b/chromium/services/network/public/cpp/server/web_socket.cc
index 8be24f0866d..2c0086872ce 100644
--- a/chromium/services/network/public/cpp/server/web_socket.cc
+++ b/chromium/services/network/public/cpp/server/web_socket.cc
@@ -118,15 +118,13 @@ WebSocket::ParseResult WebSocket::Read(std::string* message) {
// can't proceed without an |encoder_|.
return FRAME_ERROR;
}
- ParseResult result = FRAME_OK_MIDDLE;
const std::string& read_buf = connection_->read_buf();
base::StringPiece frame(read_buf);
- while (result == FRAME_OK_MIDDLE) {
- int bytes_consumed = 0;
- result = encoder_->DecodeFrame(frame, &bytes_consumed, message);
- frame = frame.substr(bytes_consumed);
- }
- connection_->read_buf().erase(0, frame.data() - read_buf.data());
+ int bytes_consumed = 0;
+ const ParseResult result =
+ encoder_->DecodeFrame(frame, &bytes_consumed, message);
+ frame = frame.substr(bytes_consumed);
+ connection_->read_buf().erase(0, bytes_consumed);
if (result == FRAME_CLOSE)
closed_ = true;
if (result == FRAME_PING) {
diff --git a/chromium/services/network/public/cpp/server/web_socket.h b/chromium/services/network/public/cpp/server/web_socket.h
index e5c1912a6ce..79998cb3c22 100644
--- a/chromium/services/network/public/cpp/server/web_socket.h
+++ b/chromium/services/network/public/cpp/server/web_socket.h
@@ -8,7 +8,7 @@
#include <memory>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/strings/string_piece.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/websockets/websocket_frame.h"
@@ -56,8 +56,8 @@ class WebSocket final {
const std::string& message,
const net::NetworkTrafficAnnotationTag traffic_annotation);
- HttpServer* const server_;
- HttpConnection* const connection_;
+ const raw_ptr<HttpServer> server_;
+ const raw_ptr<HttpConnection> connection_;
std::unique_ptr<WebSocketEncoder> encoder_;
bool closed_;
std::unique_ptr<net::NetworkTrafficAnnotationTag> traffic_annotation_ =
diff --git a/chromium/services/network/public/cpp/server/web_socket_encoder.cc b/chromium/services/network/public/cpp/server/web_socket_encoder.cc
index 809eb6733e3..dfe31eba6f3 100644
--- a/chromium/services/network/public/cpp/server/web_socket_encoder.cc
+++ b/chromium/services/network/public/cpp/server/web_socket_encoder.cc
@@ -316,8 +316,10 @@ WebSocket::ParseResult WebSocketEncoder::DecodeFrame(
result = WebSocket::FRAME_ERROR;
}
}
- if (result != WebSocket::FRAME_OK_MIDDLE)
+ if (result != WebSocket::FRAME_OK_MIDDLE &&
+ result != WebSocket::FRAME_INCOMPLETE) {
continuation_message_frames_.clear();
+ }
return result;
}
diff --git a/chromium/services/network/public/cpp/server/web_socket_encoder.h b/chromium/services/network/public/cpp/server/web_socket_encoder.h
index f07def424ca..026e73404f7 100644
--- a/chromium/services/network/public/cpp/server/web_socket_encoder.h
+++ b/chromium/services/network/public/cpp/server/web_socket_encoder.h
@@ -10,7 +10,6 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/websockets/websocket_deflater.h"
#include "net/websockets/websocket_inflater.h"
diff --git a/chromium/services/network/public/cpp/shared_url_loader_factory.h b/chromium/services/network/public/cpp/shared_url_loader_factory.h
index 033fb15c160..0806db8947b 100644
--- a/chromium/services/network/public/cpp/shared_url_loader_factory.h
+++ b/chromium/services/network/public/cpp/shared_url_loader_factory.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
diff --git a/chromium/services/network/public/cpp/simple_url_loader.cc b/chromium/services/network/public/cpp/simple_url_loader.cc
index 6464a8658af..9c49ef60380 100644
--- a/chromium/services/network/public/cpp/simple_url_loader.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader.cc
@@ -15,13 +15,13 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -564,7 +564,7 @@ class BodyReader {
mojo::ScopedDataPipeConsumerHandle body_data_pipe_;
std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
- Delegate* const delegate_;
+ const raw_ptr<Delegate> delegate_;
const int64_t max_body_size_;
int64_t total_bytes_read_ = 0;
@@ -629,7 +629,7 @@ class BodyHandler {
}
private:
- SimpleURLLoaderImpl* const simple_url_loader_;
+ const raw_ptr<SimpleURLLoaderImpl> simple_url_loader_;
bool const want_download_progress_;
};
@@ -1162,7 +1162,7 @@ class DownloadAsStreamBodyHandler : public BodyHandler,
body_reader_->Resume();
}
- SimpleURLLoaderStreamConsumer* stream_consumer_;
+ raw_ptr<SimpleURLLoaderStreamConsumer> stream_consumer_;
std::unique_ptr<BodyReader> body_reader_;
diff --git a/chromium/services/network/public/cpp/simple_url_loader_stream_consumer.h b/chromium/services/network/public/cpp/simple_url_loader_stream_consumer.h
index 1a4cbc115b8..89e1bd13c77 100644
--- a/chromium/services/network/public/cpp/simple_url_loader_stream_consumer.h
+++ b/chromium/services/network/public/cpp/simple_url_loader_stream_consumer.h
@@ -7,7 +7,6 @@
#include "base/callback_forward.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/strings/string_piece.h"
namespace network {
@@ -19,6 +18,10 @@ namespace network {
// will be called during SimpleURLLoader destruction.
class COMPONENT_EXPORT(NETWORK_CPP) SimpleURLLoaderStreamConsumer {
public:
+ SimpleURLLoaderStreamConsumer(const SimpleURLLoaderStreamConsumer&) = delete;
+ SimpleURLLoaderStreamConsumer& operator=(
+ const SimpleURLLoaderStreamConsumer&) = delete;
+
// Called as body data is received.
//
// More data will not be read until |resume| is called. It's safe to call
@@ -61,9 +64,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) SimpleURLLoaderStreamConsumer {
protected:
SimpleURLLoaderStreamConsumer() {}
virtual ~SimpleURLLoaderStreamConsumer() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SimpleURLLoaderStreamConsumer);
};
} // namespace network
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 cc67adf60fc..f7478943a34 100644
--- a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -18,16 +18,16 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/test/test_timeouts.h"
@@ -2231,7 +2231,7 @@ class MockURLLoader : public network::mojom::URLLoader {
read_run_loop_->Quit();
}
- base::test::TaskEnvironment* task_environment_;
+ raw_ptr<base::test::TaskEnvironment> task_environment_;
std::unique_ptr<net::URLRequest> url_request_;
mojo::Receiver<network::mojom::URLLoader> receiver_;
@@ -2329,7 +2329,7 @@ class MockURLLoaderFactory : public network::mojom::URLLoaderFactory {
const std::list<GURL>& requested_urls() const { return requested_urls_; }
private:
- base::test::TaskEnvironment* task_environment_;
+ raw_ptr<base::test::TaskEnvironment> task_environment_;
std::list<std::unique_ptr<MockURLLoader>> url_loaders_;
std::list<std::vector<TestLoaderEvent>> test_events_;
diff --git a/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc b/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
index ff83a66e75f..07ef0bf063b 100644
--- a/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
+++ b/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
@@ -5,6 +5,7 @@
#include "services/network/public/cpp/source_stream_to_data_pipe.h"
#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
#include "base/test/task_environment.h"
#include "net/filter/mock_source_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -112,7 +113,7 @@ class SourceStreamToDataPipeTest
void FinishedReading(int result) { callback_result_ = result; }
base::test::TaskEnvironment task_environment_;
- net::MockSourceStream* source_;
+ raw_ptr<net::MockSourceStream> source_;
std::unique_ptr<SourceStreamToDataPipe> adapter_;
mojo::ScopedDataPipeConsumerHandle consumer_end_;
absl::optional<int> callback_result_;
diff --git a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc
index e1b3e70e339..ab9382486e9 100644
--- a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc
+++ b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc
@@ -23,6 +23,7 @@ constexpr struct KnownLoadingMode {
{"default", mojom::LoadingMode::kDefault},
{"uncredentialed-prefetch", mojom::LoadingMode::kUncredentialedPrefetch},
{"uncredentialed-prerender", mojom::LoadingMode::kUncredentialedPrerender},
+ {"fenced-frame", mojom::LoadingMode::kFencedFrame},
};
} // namespace
diff --git a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc
index 87628c3093a..7120fc4cd7d 100644
--- a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc
+++ b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc
@@ -29,6 +29,9 @@ TEST(SupportsLoadingModeParserTest, Valid) {
EXPECT_THAT(ParseSupportsLoadingMode("uncredentialed-prefetch"),
SupportedModesAre(mojom::LoadingMode::kDefault,
mojom::LoadingMode::kUncredentialedPrefetch));
+ EXPECT_THAT(ParseSupportsLoadingMode("fenced-frame"),
+ SupportedModesAre(mojom::LoadingMode::kDefault,
+ mojom::LoadingMode::kFencedFrame));
EXPECT_THAT(ParseSupportsLoadingMode(
"uncredentialed-prefetch, uncredentialed-prefetch"),
SupportedModesAre(mojom::LoadingMode::kDefault,
@@ -53,6 +56,8 @@ TEST(SupportsLoadingModeParserTest, IgnoresUnknown) {
SupportedModesAre(mojom::LoadingMode::kDefault));
EXPECT_THAT(ParseSupportsLoadingMode("(uncredentialed-prefetch default)"),
SupportedModesAre(mojom::LoadingMode::kDefault));
+ EXPECT_THAT(ParseSupportsLoadingMode("uncredentialed-pre"),
+ SupportedModesAre(mojom::LoadingMode::kDefault));
}
TEST(SupportsLoadingModeParserTest, InvalidHttpStructuredHeaderList) {
@@ -80,6 +85,11 @@ TEST(SupportsLoadingModeParserTest, ValidFromResponseHeaders) {
mojom::LoadingMode::kUncredentialedPrefetch));
EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\n"
+ "supports-loading-mode: fenced-frame\n")),
+ SupportedModesAre(mojom::LoadingMode::kDefault,
+ mojom::LoadingMode::kFencedFrame));
+ EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate(
+ "HTTP/1.1 200 OK\n"
"Supports-Loading-Mode: default,\n"
" uncredentialed-prerender")),
SupportedModesAre(mojom::LoadingMode::kDefault,
diff --git a/chromium/services/network/public/cpp/url_loader_completion_status.h b/chromium/services/network/public/cpp/url_loader_completion_status.h
index 9db1bba5a81..9b7ee8022f6 100644
--- a/chromium/services/network/public/cpp/url_loader_completion_status.h
+++ b/chromium/services/network/public/cpp/url_loader_completion_status.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "net/base/proxy_server.h"
#include "net/dns/public/resolve_error_info.h"
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.cc b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
index 6bd39133e2d..9fefb0ca05e 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
@@ -9,10 +9,13 @@
#include "base/debug/dump_without_crashing.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
+#include "base/time/time.h"
#include "mojo/public/cpp/base/file_mojom_traits.h"
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "net/log/net_log_source.h"
+#include "net/log/net_log_source_type.h"
#include "services/network/public/cpp/crash_keys.h"
#include "services/network/public/cpp/http_request_headers_mojom_traits.h"
#include "services/network/public/cpp/isolation_info_mojom_traits.h"
@@ -115,11 +118,19 @@ bool StructTraits<network::mojom::WebBundleTokenParamsDataView,
return true;
}
-bool StructTraits<network::mojom::NetLogParamsDataView,
- network::ResourceRequest::NetLogParams>::
- Read(network::mojom::NetLogParamsDataView data,
- network::ResourceRequest::NetLogParams* out) {
- out->source_id = data.source_id();
+bool StructTraits<network::mojom::NetLogSourceDataView, net::NetLogSource>::
+ Read(network::mojom::NetLogSourceDataView data, net::NetLogSource* out) {
+ if (data.source_type() >=
+ static_cast<uint32_t>(net::NetLogSourceType::COUNT)) {
+ return false;
+ }
+ base::TimeTicks start_time;
+ if (!data.ReadStartTime(&start_time)) {
+ return false;
+ }
+ *out =
+ net::NetLogSource(static_cast<net::NetLogSourceType>(data.source_type()),
+ data.source_id(), start_time);
return true;
}
@@ -168,7 +179,9 @@ bool StructTraits<
!data.ReadWebBundleTokenParams(&out->web_bundle_token_params) ||
!data.ReadDevtoolsAcceptedStreamTypes(
&out->devtools_accepted_stream_types) ||
- !data.ReadNetLogParams(&out->net_log_params)) {
+ !data.ReadNetLogCreateInfo(&out->net_log_create_info) ||
+ !data.ReadNetLogReferenceInfo(&out->net_log_reference_info) ||
+ !data.ReadNavigationRedirectChain(&out->navigation_redirect_chain)) {
// Note that data.ReadTrustTokenParams is temporarily handled below.
return false;
}
@@ -185,7 +198,6 @@ bool StructTraits<
data.update_first_party_url_on_redirect();
out->load_flags = data.load_flags();
out->resource_type = data.resource_type();
- out->should_reset_appcache = data.should_reset_appcache();
out->is_external_request = data.is_external_request();
out->originated_from_service_worker = data.originated_from_service_worker();
out->skip_service_worker = data.skip_service_worker();
@@ -206,6 +218,7 @@ bool StructTraits<
out->is_fetch_like_api = data.is_fetch_like_api();
out->is_favicon = data.is_favicon();
out->obey_origin_policy = data.obey_origin_policy();
+ out->original_destination = data.original_destination();
out->target_ip_address_space = data.target_ip_address_space();
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 86e6558f3eb..53b1cd261ec 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.h
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.h
@@ -141,15 +141,19 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
- StructTraits<network::mojom::NetLogParamsDataView,
- network::ResourceRequest::NetLogParams> {
- static uint32_t source_id(
- const network::ResourceRequest::NetLogParams& params) {
- return params.source_id;
+ StructTraits<network::mojom::NetLogSourceDataView, net::NetLogSource> {
+ static uint32_t source_id(const net::NetLogSource& params) {
+ return params.id;
+ }
+ static uint32_t source_type(const net::NetLogSource& params) {
+ return static_cast<uint32_t>(params.type);
+ }
+ static base::TimeTicks start_time(const net::NetLogSource& params) {
+ return params.start_time;
}
- static bool Read(network::mojom::NetLogParamsDataView data,
- network::ResourceRequest::NetLogParams* out);
+ static bool Read(network::mojom::NetLogSourceDataView data,
+ net::NetLogSource* out);
};
template <>
@@ -173,6 +177,10 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
const network::ResourceRequest& request) {
return request.request_initiator;
}
+ static const std::vector<GURL> navigation_redirect_chain(
+ const network::ResourceRequest& request) {
+ return request.navigation_redirect_chain;
+ }
static const absl::optional<url::Origin>& isolated_world_origin(
const network::ResourceRequest& request) {
return request.isolated_world_origin;
@@ -202,9 +210,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
const network::ResourceRequest& request) {
return request.priority;
}
- static bool should_reset_appcache(const network::ResourceRequest& request) {
- return request.should_reset_appcache;
- }
static bool is_external_request(const network::ResourceRequest& request) {
return request.is_external_request;
}
@@ -313,6 +318,10 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
static bool obey_origin_policy(const network::ResourceRequest& request) {
return request.obey_origin_policy;
}
+ static network::mojom::RequestDestination original_destination(
+ const network::ResourceRequest& request) {
+ return request.original_destination;
+ }
static const absl::optional<std::vector<net::SourceStream::SourceType>>&
devtools_accepted_stream_types(const network::ResourceRequest& request) {
return request.devtools_accepted_stream_types;
@@ -333,9 +342,13 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
web_bundle_token_params(const network::ResourceRequest& request) {
return request.web_bundle_token_params;
}
- static const absl::optional<network::ResourceRequest::NetLogParams>&
- net_log_params(const network::ResourceRequest& request) {
- return request.net_log_params;
+ static const absl::optional<net::NetLogSource>& net_log_create_info(
+ const network::ResourceRequest& request) {
+ return request.net_log_create_info;
+ }
+ static const absl::optional<net::NetLogSource>& net_log_reference_info(
+ const network::ResourceRequest& request) {
+ return request.net_log_reference_info;
}
static network::mojom::IPAddressSpace target_ip_address_space(
const network::ResourceRequest& request) {
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 15aceadea15..111956b1a29 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
@@ -10,6 +10,9 @@
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/isolation_info.h"
#include "net/filter/source_stream.h"
+#include "net/log/net_log.h"
+#include "net/log/net_log_source.h"
+#include "net/log/net_log_source_type.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"
@@ -67,7 +70,6 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) {
original.load_flags = 3;
original.resource_type = 2;
original.priority = net::IDLE;
- original.should_reset_appcache = true;
original.is_external_request = false;
original.cors_preflight_policy =
mojom::CorsPreflightPolicy::kConsiderPreflight;
@@ -93,8 +95,10 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) {
absl::make_optional(ResourceRequest::WebBundleTokenParams(
GURL("https://bundle.test/"), base::UnguessableToken::Create(),
mojo::PendingRemote<network::mojom::WebBundleHandle>()));
- original.net_log_params =
- absl::make_optional(ResourceRequest::NetLogParams());
+ original.net_log_create_info = absl::make_optional(net::NetLogSource(
+ net::NetLogSourceType::URL_REQUEST, net::NetLog::Get()->NextID()));
+ original.net_log_reference_info = absl::make_optional(net::NetLogSource(
+ net::NetLogSourceType::URL_REQUEST, net::NetLog::Get()->NextID()));
original.devtools_accepted_stream_types =
std::vector<net::SourceStream::SourceType>(
{net::SourceStream::SourceType::TYPE_BROTLI,
diff --git a/chromium/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h b/chromium/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h
index 9d2f0018eb1..a06e48b6dff 100644
--- a/chromium/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h
+++ b/chromium/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -52,7 +53,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) WeakWrapperSharedURLLoaderFactory
base::OnceCallback<mojom::URLLoaderFactory*()> make_factory_ptr_;
// Not owned.
- mojom::URLLoaderFactory* factory_ptr_ = nullptr;
+ raw_ptr<mojom::URLLoaderFactory> factory_ptr_ = nullptr;
};
} // namespace network
diff --git a/chromium/services/network/public/mojom/BUILD.gn b/chromium/services/network/public/mojom/BUILD.gn
index f7bd3d84693..0e735dda0f9 100644
--- a/chromium/services/network/public/mojom/BUILD.gn
+++ b/chromium/services/network/public/mojom/BUILD.gn
@@ -154,10 +154,10 @@ mojom("mojom_network_isolation_key") {
}
# As with |mojom_ip_address|, this is a separate target to avoid a circular
-# dependency, which comes from the fact that proxy_resolver_win service will use
-# this interfaces, and the network service will use the proxy_resolver_win
-# service. This is separate from other targets because only this needs to be
-# included in proxy_resolver_win builds.
+# dependency, which comes from the fact that proxy_resolver_win uses this
+# interface, and the network service uses the proxy_resolver_win service. This
+# is separate from other targets because only this needs to be included in
+# proxy_resolver_win builds.
mojom("mojom_proxy_config") {
generate_java = true
sources = [
@@ -178,7 +178,10 @@ mojom("mojom_proxy_config") {
},
]
traits_headers = [ "//services/network/public/cpp/mutable_network_traffic_annotation_tag_mojom_traits.h" ]
- traits_public_deps = [ "//net/traffic_annotation" ]
+ traits_public_deps = [
+ "//net/traffic_annotation",
+ "//services/network/public/cpp:proxy_config_mojom_support",
+ ]
},
]
@@ -191,7 +194,10 @@ mojom("mojom_proxy_config") {
},
]
traits_headers = [ "//services/network/public/cpp/mutable_partial_network_traffic_annotation_tag_mojom_traits.h" ]
- traits_public_deps = [ "//net/traffic_annotation" ]
+ traits_public_deps = [
+ "//net/traffic_annotation",
+ "//services/network/public/cpp:proxy_config_mojom_support",
+ ]
},
{
types = [
@@ -218,7 +224,10 @@ mojom("mojom_proxy_config") {
]
traits_headers =
[ "//services/network/public/cpp/proxy_config_mojom_traits.h" ]
- traits_public_deps = [ "//net" ]
+ traits_public_deps = [
+ "//net",
+ "//services/network/public/cpp:proxy_config_mojom_support",
+ ]
},
{
types = [
@@ -228,7 +237,10 @@ mojom("mojom_proxy_config") {
},
]
traits_headers = [ "//services/network/public/cpp/proxy_config_with_annotation_mojom_traits.h" ]
- traits_public_deps = [ "//net" ]
+ traits_public_deps = [
+ "//net",
+ "//services/network/public/cpp:proxy_config_mojom_support",
+ ]
},
]
@@ -295,6 +307,10 @@ mojom("url_loader_base") {
"//url/mojom:url_mojom_origin",
]
+ if (is_win) {
+ public_deps += [ "//services/proxy_resolver_win/public/mojom" ]
+ }
+
enabled_features = []
if (is_android || is_chromeos_ash) {
enabled_features += [ "network_change_notifier_in_browser" ]
@@ -363,8 +379,8 @@ mojom("url_loader_base") {
cpp = "::network::ResourceRequest::WebBundleTokenParams"
},
{
- mojom = "network.mojom.NetLogParams"
- cpp = "::network::ResourceRequest::NetLogParams"
+ mojom = "network.mojom.NetLogSource"
+ cpp = "::net::NetLogSource"
},
{
mojom = "network.mojom.URLRequest"
@@ -455,38 +471,44 @@ mojom("url_loader_base") {
[ "//services/network/public/cpp/network_interface_mojom_traits.h" ]
traits_public_deps = [ "//net" ]
},
- {
- types = [
- {
- mojom = "network.mojom.P2PPacketInfo"
- cpp = "::network::P2PPacketInfo"
- },
- {
- mojom = "network.mojom.P2PSendPacketMetrics"
- cpp = "::network::P2PSendPacketMetrics"
- },
- {
- mojom = "network.mojom.P2PPortRange"
- cpp = "::network::P2PPortRange"
- },
- {
- mojom = "network.mojom.P2PHostAndIPEndPoint"
- cpp = "::network::P2PHostAndIPEndPoint"
- },
- {
- mojom = "network.mojom.P2PSocketOption"
- cpp = "::network::P2PSocketOption"
- },
- {
- mojom = "network.mojom.P2PSocketType"
- cpp = "::network::P2PSocketType"
- },
- ]
- traits_headers = [ "//services/network/public/cpp/p2p_param_traits.h" ]
- traits_public_deps = [ "//third_party/webrtc_overrides:webrtc_component" ]
- },
]
+ if (is_p2p_enabled) {
+ shared_typemaps += [
+ {
+ types = [
+ {
+ mojom = "network.mojom.P2PPacketInfo"
+ cpp = "::network::P2PPacketInfo"
+ },
+ {
+ mojom = "network.mojom.P2PSendPacketMetrics"
+ cpp = "::network::P2PSendPacketMetrics"
+ },
+ {
+ mojom = "network.mojom.P2PPortRange"
+ cpp = "::network::P2PPortRange"
+ },
+ {
+ mojom = "network.mojom.P2PHostAndIPEndPoint"
+ cpp = "::network::P2PHostAndIPEndPoint"
+ },
+ {
+ mojom = "network.mojom.P2PSocketOption"
+ cpp = "::network::P2PSocketOption"
+ },
+ {
+ mojom = "network.mojom.P2PSocketType"
+ cpp = "::network::P2PSocketType"
+ },
+ ]
+ traits_headers = [ "//services/network/public/cpp/p2p_param_traits.h" ]
+ traits_public_deps =
+ [ "//third_party/webrtc_overrides:webrtc_component" ]
+ },
+ ]
+ }
+
cpp_typemaps = [
{
types = [
@@ -787,8 +809,8 @@ mojom("cookies_mojom") {
cpp = "::net::CookieOptions"
},
{
- mojom = "network.mojom.CookiePartitionKeychain"
- cpp = "::net::CookiePartitionKeychain"
+ mojom = "network.mojom.CookiePartitionKeyCollection"
+ cpp = "::net::CookiePartitionKeyCollection"
},
{
mojom = "network.mojom.CanonicalCookie"
@@ -868,11 +890,9 @@ mojom("mojom") {
"network_quality_estimator_manager.mojom",
"network_service.mojom",
"network_service_test.mojom",
- "p2p.mojom",
- "p2p_trusted.mojom",
"proxy_lookup_client.mojom",
"proxy_resolving_socket.mojom",
- "reporting_report.mojom",
+ "reporting_service.mojom",
"ssl_config.mojom",
"supports_loading_mode.mojom",
"tcp_socket.mojom",
@@ -891,11 +911,16 @@ mojom("mojom") {
":url_loader_base",
":websocket_mojom",
"//mojo/public/mojom/base",
+ "//sandbox/policy/mojom",
"//services/proxy_resolver/public/mojom",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
]
+ if (is_win) {
+ public_deps += [ "//services/proxy_resolver_win/public/mojom" ]
+ }
+
enabled_features = []
# TODO(crbug/598073): When moving the service implementation to
@@ -907,6 +932,14 @@ mojom("mojom") {
sources += [ "ct_log_info.mojom" ]
}
+ if (is_p2p_enabled) {
+ enabled_features += [ "is_p2p_enabled" ]
+ sources += [
+ "p2p.mojom",
+ "p2p_trusted.mojom",
+ ]
+ }
+
has_dchecks = is_debug || dcheck_always_on
if (has_dchecks && is_win) {
enabled_features += [ "win_permissions_validation" ]
@@ -916,7 +949,9 @@ 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"
- enabled_features += [ "enable_reporting" ]
+ if (enable_reporting) {
+ enabled_features += [ "enable_reporting" ]
+ }
}
# This is only needed on desktop linux, but the defines make this difficult
@@ -1055,6 +1090,19 @@ mojom("mojom") {
]
traits_public_deps = [ "//net" ]
},
+ {
+ types = [
+ {
+ mojom = "network.mojom.ReportingApiEndpoint"
+ cpp = "::net::ReportingEndpoint"
+ },
+ ]
+ traits_headers = [
+ "//services/network/public/cpp/reporting_api_endpoint_mojom_traits.h",
+ ]
+ traits_sources = [ "//services/network/public/cpp/reporting_api_endpoint_mojom_traits.cc" ]
+ traits_public_deps = [ "//net" ]
+ },
]
}
diff --git a/chromium/services/network/public/mojom/cookie_manager.mojom b/chromium/services/network/public/mojom/cookie_manager.mojom
index 841e5e595c6..e08f8ce1109 100644
--- a/chromium/services/network/public/mojom/cookie_manager.mojom
+++ b/chromium/services/network/public/mojom/cookie_manager.mojom
@@ -6,6 +6,7 @@ module network.mojom;
import "components/content_settings/core/common/content_settings.mojom";
import "mojo/public/mojom/base/time.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/network/public/mojom/schemeful_site.mojom";
import "url/mojom/url.mojom";
@@ -151,9 +152,16 @@ struct CookieOptions {
struct CookiePartitionKey {
SchemefulSite site;
+
+ // Indicates the CookiePartitionKey is a placeholder indicating that the
+ // cookie should be partitioned, but it was created in the renderer so we
+ // don't know what its partition key is yet.
+ bool from_script = false;
+
+ mojo_base.mojom.UnguessableToken? nonce;
};
-struct CookiePartitionKeychain {
+struct CookiePartitionKeyCollection {
bool contains_all_partitions = false;
array<CookiePartitionKey> keys;
};
@@ -351,7 +359,7 @@ interface CookieManager {
// Get all cookies for the specified URL and cookie options.
// Will also return any partitioned cookies whose partition key are in
- // |cookie_partition_keychain|.
+ // |cookie_partition_key_collection|.
// Returned cookie list is sorted first by path length (longest first)
// and second by creation time. If the |return_excluded_cookies| option is set
// in the options, |excluded_cookies| with be a list of cookies that were
@@ -359,7 +367,7 @@ interface CookieManager {
// default, that option is not set and |excluded_cookies| is an empty list.
GetCookieList(url.mojom.Url url,
CookieOptions cookie_options,
- CookiePartitionKeychain cookie_partition_keychain)
+ CookiePartitionKeyCollection cookie_partition_key_collection)
=> (array<CookieWithAccessResult> cookies,
array<CookieWithAccessResult> excluded_cookies);
diff --git a/chromium/services/network/public/mojom/cors.mojom b/chromium/services/network/public/mojom/cors.mojom
index 3f3c8678ae7..8601f4db826 100644
--- a/chromium/services/network/public/mojom/cors.mojom
+++ b/chromium/services/network/public/mojom/cors.mojom
@@ -20,6 +20,10 @@ enum CorsPreflightPolicy {
enum CorsError {
// Access control
kDisallowedByMode,
+
+ // This value is only used in warnings reported to DevTools. It indicates that
+ // the preflight request failed due to a non-CORS net error (for example,
+ // `net::ERR_EMPTY_RESPONSE`).
kInvalidResponse,
// Not allowed wildcard origin was found in Access-Control-Allow-Origin
@@ -76,14 +80,19 @@ enum CorsError {
// response header.
kPreflightInvalidAllowCredentials,
- // "Access-Control-Allow-External:"
- // ( https://wicg.github.io/cors-rfc1918/#headers ) specific error
- // conditions:
+ // The Access-Control-Allow-Private-Network header was missing from the
+ // response to a preflight request with the
+ // Access-Control-Request-Private-Network header set.
+ //
+ // Spec: https://wicg.github.io/private-network-access/#headers
+ kPreflightMissingAllowPrivateNetwork,
+
+ // The Access-Control-Allow-Private-Network header on a preflight response
+ // had a invalid value. This error is only raised when the preflight request
+ // had the Access-Control-Request-Private-Network header set.
//
- // TODO(https://crbug.com/1252295): Rename these to reflect the evolution of
- // the spec. See https://wicg.github.io/private-network-access/#headers.
- kPreflightMissingAllowExternal,
- kPreflightInvalidAllowExternal,
+ // Spec: https://wicg.github.io/private-network-access/#headers
+ kPreflightInvalidAllowPrivateNetwork,
// Failed to parse Access-Control-Allow-Methods response header field in
// CORS-preflight response.
@@ -130,7 +139,12 @@ struct CorsErrorStatus {
// The target IP address space set on the URL request.
// See `ResourceRequest::target_ip_address_space`.
- // Set if (but not only if) `cors_error == kInvalidPrivateNetworkAccess`.
+ // Set if (but not only if) `cors_error` is one of:
+ //
+ // - `kInvalidPrivateNetworkAccess`
+ // - `kPreflightMissingAllowPrivateNetwork`
+ // - `kPreflightInvalidAllowPrivateNetwork`
+ //
IPAddressSpace target_address_space = IPAddressSpace.kUnknown;
// The address space of the requested resource.
diff --git a/chromium/services/network/public/mojom/ct_log_info.mojom b/chromium/services/network/public/mojom/ct_log_info.mojom
index db0c2d4b03a..9572c63c3c9 100644
--- a/chromium/services/network/public/mojom/ct_log_info.mojom
+++ b/chromium/services/network/public/mojom/ct_log_info.mojom
@@ -6,6 +6,14 @@ module network.mojom;
import "mojo/public/mojom/base/time.mojom";
+// Structure used to hold information about previous operators for a log.
+struct PreviousOperatorEntry {
+ // Name of the operator.
+ string name;
+ // Time when operator stopped operating this log.
+ mojo_base.mojom.TimeDelta end_time;
+};
+
// A single Certificate Transparency Log configuration.
struct CTLogInfo {
// The DER-encoded SubjectPublicKeyInfo of the log.
@@ -25,4 +33,10 @@ struct CTLogInfo {
// is used to determine the "once or currently qualified" status of the log.
// If the log is currently qualified, this will not be set.
mojo_base.mojom.TimeDelta? disqualified_at;
+
+ // Current operator for this log.
+ string current_operator;
+
+ // Information about previous operators for this log (if any).
+ array<PreviousOperatorEntry> previous_operators;
};
diff --git a/chromium/services/network/public/mojom/devtools_observer.mojom b/chromium/services/network/public/mojom/devtools_observer.mojom
index ce605932ce5..e1dbf518d1e 100644
--- a/chromium/services/network/public/mojom/devtools_observer.mojom
+++ b/chromium/services/network/public/mojom/devtools_observer.mojom
@@ -54,6 +54,7 @@ struct URLResponseHeadDevToolsInfo {
FetchResponseSource service_worker_response_source;
SSLInfo? ssl_info;
IPEndPoint remote_endpoint;
+ bool emitted_extra_info;
};
// Interface for devtools receiving information about individual request
@@ -126,11 +127,16 @@ interface DevToolsObserver {
// to share sensitive information with DevTools, and is handled in the browser
// process. Called even when |devtool_request_id| is not available to the
// URLLoader to ensure CORS issues are recorded even if DevTools is closed.
+ //
+ // |is_warning| being true indicates that the error was suppressed and treated
+ // as a simple warning, as opposed to having caused the request to fail.
OnCorsError(
string? devtool_request_id,
url.mojom.Origin? initiator_origin,
+ ClientSecurityState? client_security_state,
url.mojom.Url url,
- CorsErrorStatus status);
+ CorsErrorStatus status,
+ bool is_warning);
// Called when parsing the .wbn file has succeeded. The event
// contains the information about the web bundle contents.
diff --git a/chromium/services/network/public/mojom/fetch_api.mojom b/chromium/services/network/public/mojom/fetch_api.mojom
index 8acd3e7b268..447ed9f0bd0 100644
--- a/chromium/services/network/public/mojom/fetch_api.mojom
+++ b/chromium/services/network/public/mojom/fetch_api.mojom
@@ -54,6 +54,15 @@ enum RequestDestination {
kWebBundle = 19,
kWorker = 20,
kXslt = 21,
+ // kFencedframe represents a main resource request in a fenced frame. A
+ // <fencedframe> element uses this destination.
+ //
+ // e.g. <fencedframe src="example.com"></fencedframe>
+ //
+ // Fenced Frame is not standardized yet. See
+ // https://github.com/shivanigithub/fenced-frame for the explainer and
+ // crbug.com/1123606 for the implementation.
+ kFencedframe = 22,
};
// Corresponds to Fetch request's "redirect mode":
diff --git a/chromium/services/network/public/mojom/network_context.mojom b/chromium/services/network/public/mojom/network_context.mojom
index f3f625cc6d5..8cdb76c6eac 100644
--- a/chromium/services/network/public/mojom/network_context.mojom
+++ b/chromium/services/network/public/mojom/network_context.mojom
@@ -33,13 +33,11 @@ import "services/network/public/mojom/isolation_info.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/origin_policy_manager.mojom";
import "services/network/public/mojom/parsed_headers.mojom";
-import "services/network/public/mojom/p2p.mojom";
-import "services/network/public/mojom/p2p_trusted.mojom";
import "services/network/public/mojom/proxy_config.mojom";
import "services/network/public/mojom/proxy_config_with_annotation.mojom";
import "services/network/public/mojom/proxy_lookup_client.mojom";
import "services/network/public/mojom/proxy_resolving_socket.mojom";
-import "services/network/public/mojom/reporting_report.mojom";
+import "services/network/public/mojom/reporting_service.mojom";
import "services/network/public/mojom/restricted_cookie_manager.mojom";
import "services/network/public/mojom/site_for_cookies.mojom";
import "services/network/public/mojom/ssl_config.mojom";
@@ -59,6 +57,15 @@ import "url/mojom/url.mojom";
[EnableIf=is_chromeos_ash]
import "services/network/public/mojom/dhcp_wpad_url_client.mojom";
+[EnableIf=is_p2p_enabled]
+import "services/network/public/mojom/p2p.mojom";
+
+[EnableIf=is_p2p_enabled]
+import "services/network/public/mojom/p2p_trusted.mojom";
+
+[EnableIf=is_win]
+import "services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom";
+
const uint32 kWebSocketOptionNone = 0;
// Disallow the request from sending cookies. Disallow the response from writing
// cookies.
@@ -118,7 +125,7 @@ struct CertVerifierServiceRemoteParams {
// Client to update the custom proxy config.
interface CustomProxyConfigClient {
- OnCustomProxyConfigUpdated(CustomProxyConfig proxy_config);
+ OnCustomProxyConfigUpdated(CustomProxyConfig proxy_config) => ();
// Marks the custom proxies in |bad_proxies| as temporarily bad, so they are
// not layered onto the proxy resolution results for subsequent requests.
@@ -294,6 +301,13 @@ struct NetworkContextParams {
pending_remote<proxy_resolver.mojom.ProxyResolverFactory>?
proxy_resolver_factory;
+ // Handles all proxy resolution logic if the current proxy config comes from
+ // the operating system. Otherwise, or if this is not populated, proxy
+ // resolution is handled by Chrome as normal.
+ [EnableIf=is_win]
+ pending_remote<proxy_resolver_win.mojom.WindowsSystemProxyResolver>?
+ windows_system_proxy_resolver;
+
// Retrieves the PAC script URL set via DHCP from the browser process. Only
// used if |proxy_resolver_factory| is set. Note: optional because some tests
// build their own NetworkContextParams and don't need a DHCP WPAD client.
@@ -1232,6 +1246,7 @@ interface NetworkContext {
// |network_isolation_key| is the network cache shard to associate with the
// P2PSocketManager instance, and affects DNS cache shard used and proxy
// connection sharing.
+ [EnableIf=is_p2p_enabled]
CreateP2PSocketManager(
NetworkIsolationKey network_isolation_key,
pending_remote<P2PTrustedSocketManagerClient> client,
@@ -1346,6 +1361,11 @@ interface NetworkContext {
NetworkIsolationKey network_isolation_key,
AuthCredentials credentials) => ();
+ // Sets whether
+ // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name is
+ // supported in this network context.
+ SetCorsNonWildcardRequestHeadersSupport(bool value);
+
// Looks up credentials in the HttpAuthCache using the origin and path from
// |url|. Only supports basic auth scheme. Only looks up server (not proxy)
// auth credentials, and only those that are usable in the scope of
diff --git a/chromium/services/network/public/mojom/network_service.mojom b/chromium/services/network/public/mojom/network_service.mojom
index 59fbbde6ffc..8fab77504b1 100644
--- a/chromium/services/network/public/mojom/network_service.mojom
+++ b/chromium/services/network/public/mojom/network_service.mojom
@@ -9,10 +9,12 @@ import "mojo/public/mojom/base/file.mojom";
import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/memory_pressure_level.mojom";
import "mojo/public/mojom/base/read_only_buffer.mojom";
+import "mojo/public/mojom/base/read_only_file.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "mojo/public/mojom/base/values.mojom";
+import "sandbox/policy/mojom/sandbox.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/host_resolver.mojom";
import "services/network/public/mojom/http_raw_headers.mojom";
@@ -150,6 +152,9 @@ struct LoggingSettings {
//
// This is a trusted interface that only the browser process should have access
// to. It must not be sent to any untrusted process like a renderer process.
+// The network sandbox may be disabled (to kNoSandbox) by policy, and may not
+// be available on all platforms.
+[ServiceSandbox=sandbox.mojom.Sandbox.kNetwork]
interface NetworkService {
// Sets the parameters and initializes the service.
SetParams(NetworkServiceParams params);
@@ -364,14 +369,15 @@ interface NetworkService {
// environments.
BindTestInterface(pending_receiver<NetworkServiceTest> receiver);
- // Sets the First-Party Sets data. |raw_sets| is the JSON-encoded
- // string representation of a collection of set declarations according to the
- // format specified in this document:
- // https://github.com/privacycg/first-party-sets
- // Note that by setting the First-Party Sets, any previous notion of
- // First-Party Sets is cleared. On any kind of error, all First-Party Sets are
- // cleared (except for the manually-specified set, if one exists).
- SetFirstPartySets(string raw_sets);
+ // Sets the First-Party Sets data. |sets_file| is the file containing a
+ // collection of set declarations according to the format specified in this
+ // document: https://github.com/privacycg/first-party-sets. The collection may
+ // either be a single JSON array of such records, or a sequence of
+ // newline-delimited JSON objects (one per line). Note that by setting the
+ // First-Party Sets, any previous notion of First-Party Sets is cleared. On
+ // any kind of error, all First-Party Sets are cleared (except for the
+ // manually-specified set, if one exists).
+ SetFirstPartySets(mojo_base.mojom.ReadOnlyFile sets_file);
// Sets the First-Party Sets data that was persisted to compare it with the
// current First-Party Sets data set by `SetFirstPartySets()`, which is
@@ -391,7 +397,7 @@ interface NetworkService {
// when the raw headers represent untrustworthy input and the URLLoader used
// lives in a non-sandboxed process. It can also happen from some exotic
// URLLoader where parsing hasn't been implemented.
- // In particular, this is used for request served from AppCache, WebBundle,
+ // In particular, this is used for request served from WebBundle,
// Extensions, etc.
ParseHeaders(url.mojom.Url url, HttpResponseHeaders headers)
=> (ParsedHeaders parsed_headers);
diff --git a/chromium/services/network/public/mojom/network_service_test.mojom b/chromium/services/network/public/mojom/network_service_test.mojom
index f2dde438421..bdf7ccb1633 100644
--- a/chromium/services/network/public/mojom/network_service_test.mojom
+++ b/chromium/services/network/public/mojom/network_service_test.mojom
@@ -128,13 +128,4 @@ interface NetworkServiceTest {
// default.
[Sync]
SetSCTAuditingRetryDelay(mojo_base.mojom.TimeDelta? delay) => ();
-
- // Gets the current count of pending reports in the SCT auditing cache.
- [Sync]
- GetSCTAuditingPendingReportsCount() => (uint64 reports);
-
- // Runs the callback passed by the caller when an SCT auditing report
- // completes. This lets the caller wait on report completion by passing a
- // QuitClosure as the callback and running a RunLoop.
- SetSCTAuditingReportCompletionCallback() => ();
};
diff --git a/chromium/services/network/public/mojom/parsed_headers.mojom b/chromium/services/network/public/mojom/parsed_headers.mojom
index 7f0d84d5fb9..8ecea65982f 100644
--- a/chromium/services/network/public/mojom/parsed_headers.mojom
+++ b/chromium/services/network/public/mojom/parsed_headers.mojom
@@ -13,6 +13,12 @@ import "services/network/public/mojom/timing_allow_origin.mojom";
import "services/network/public/mojom/web_client_hints_types.mojom";
import "services/network/public/mojom/x_frame_options.mojom";
+enum OriginAgentClusterValue {
+ kAbsent, // No Origin-Agent-Cluster header specified.
+ kTrue, // Origin-Agent-Cluster: ?1.
+ kFalse // Origin-Agent-Cluster: ?0.
+};
+
// Holds the parsed representation of several security related HTTP headers.
// This struct should only be populated by network::PopulateParsedHeaders().
// ParsedHeaders are used only for navigational requests and for worker and
@@ -33,7 +39,7 @@ struct ParsedHeaders {
CrossOriginOpenerPolicy cross_origin_opener_policy;
// The parsed value of the Origin-Agent-Cluster header.
- bool origin_agent_cluster = false;
+ OriginAgentClusterValue origin_agent_cluster;
// The parsed Accept-CH from response headers.
//
@@ -44,9 +50,6 @@ struct ParsedHeaders {
// 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;
-
// The parsed Critical-CH response header.
//
// Should be parsed in the same way (i.e. same tokens and grammar) as the
diff --git a/chromium/services/network/public/mojom/proxy_config_with_annotation.mojom b/chromium/services/network/public/mojom/proxy_config_with_annotation.mojom
index 0b1054b810b..d08cda170b9 100644
--- a/chromium/services/network/public/mojom/proxy_config_with_annotation.mojom
+++ b/chromium/services/network/public/mojom/proxy_config_with_annotation.mojom
@@ -42,7 +42,7 @@ interface ProxyErrorClient {
// This only surfaces failures for an entire URL load, and not from
// individual proxy servers. For instance if a PAC script returned 4 proxy
// servers, and sending the request through the first three failed before
- // successfulyl sending through the fourth, this method is NOT called.
+ // successfully sending through the fourth, this method is NOT called.
//
// There is some ambiguity with how errors are classified as being a
// "proxy error". The current implementation includes a mix of
diff --git a/chromium/services/network/public/mojom/reporting_report.mojom b/chromium/services/network/public/mojom/reporting_report.mojom
deleted file mode 100644
index 4b218c587d7..00000000000
--- a/chromium/services/network/public/mojom/reporting_report.mojom
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module network.mojom;
-
-import "url/mojom/url.mojom";
-import "mojo/public/mojom/base/time.mojom";
-import "mojo/public/mojom/base/values.mojom";
-import "mojo/public/mojom/base/unguessable_token.mojom";
-
-
-// The status of a Reporting API report.
-enum ReportingApiReportStatus {
- kQueued,
- kPending,
- kDoomed,
- kSuccess,
-};
-
-// A Reporting API report.
-struct ReportingApiReport {
- mojo_base.mojom.UnguessableToken id;
- // The URL of the document that triggered the report.
- url.mojom.Url url;
- // The name of the endpoint group that should be used to deliver the report.
- string group;
- // The type of the report (specifies the set of data that is contained
- // in the report body).
- string type;
- // When the report was generated.
- mojo_base.mojom.TimeTicks timestamp;
- // How many uploads deep the related request was.
- int32 depth;
- // The number of delivery attempts made so far, not including an active
- // attempt.
- int32 attempts;
- // The body of the report.
- mojo_base.mojom.DictionaryValue body;
- // The status of the report.
- ReportingApiReportStatus status;
-};
-
-// Indirectly listens to changes in the Reporting Service via
-// ReportingCacheObserver as intermediate
-interface ReportingApiObserver {
- // Called whenever a report is added
- OnReportAdded(ReportingApiReport report);
- // Called whenever a report is updated (status change or attempts incremented)
- OnReportUpdated(ReportingApiReport report);
-}; \ No newline at end of file
diff --git a/chromium/services/network/public/mojom/reporting_service.mojom b/chromium/services/network/public/mojom/reporting_service.mojom
new file mode 100644
index 00000000000..06d12397fc2
--- /dev/null
+++ b/chromium/services/network/public/mojom/reporting_service.mojom
@@ -0,0 +1,86 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module network.mojom;
+
+import "url/mojom/url.mojom";
+import "url/mojom/origin.mojom";
+import "mojo/public/mojom/base/time.mojom";
+import "mojo/public/mojom/base/values.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
+import "services/network/public/mojom/network_isolation_key.mojom";
+
+// The status of a Reporting API report.
+enum ReportingApiReportStatus {
+ kQueued,
+ kPending,
+ kDoomed,
+ kSuccess,
+};
+
+// A Reporting API report.
+struct ReportingApiReport {
+ mojo_base.mojom.UnguessableToken id;
+ // The URL of the document that triggered the report.
+ url.mojom.Url url;
+ // The name of the endpoint group that should be used to deliver the report.
+ string group;
+ // The type of the report (specifies the set of data that is contained
+ // in the report body).
+ string type;
+ // When the report was generated.
+ mojo_base.mojom.TimeTicks timestamp;
+ // How many uploads deep the related request was.
+ int32 depth;
+ // The number of delivery attempts made so far, not including an active
+ // attempt.
+ int32 attempts;
+ // The body of the report.
+ mojo_base.mojom.DictionaryValue body;
+ // The status of the report.
+ ReportingApiReportStatus status;
+};
+
+struct ReportingApiEndpoint {
+ // The endpoint to which reports may be delivered.
+ url.mojom.Url url;
+ // The number of attempted uploads that were made for this endpoint.
+ int32 attempted_uploads;
+ // The number of uploads that have succeeded for this endpoint.
+ int32 successful_uploads;
+ // The number of individual reports that we've attempted to upload for this
+ // endpoint. (Failed uploads will cause a report to be counted multiple
+ // times, once for each attempt.)
+ int32 attempted_reports;
+ // The number of individual reports that were successfully uploaded for
+ // this endpoint.
+ int32 successful_reports;
+ // Priority when multiple endpoints are configured for an origin; endpoints
+ // with numerically lower priorities are used first.
+ int32 priority;
+ // Weight when multiple endpoints are configured for an origin with the same
+ // priority; among those with the same priority, each endpoint has a chance
+ // of being chosen that is proportional to its weight.
+ int32 weight;
+ // Origin that configured this endpoint group.
+ url.mojom.Origin origin;
+ // Name of the endpoint group (defaults to "default" during header parsing).
+ string group_name;
+ // The NetworkIsolationKey the group is scoped to. Needed to prevent leaking
+ // third party contexts across sites.
+ NetworkIsolationKey network_isolation_key;
+ // Source token for the document or worker which configured this endpoint.
+ mojo_base.mojom.UnguessableToken? reporting_source;
+};
+
+// Indirectly listens to changes in the Reporting Service via
+// ReportingCacheObserver as intermediate
+interface ReportingApiObserver {
+ // Called whenever a report is added
+ OnReportAdded(ReportingApiReport report);
+ // Called whenever a report is updated (status change or attempts incremented)
+ OnReportUpdated(ReportingApiReport report);
+ // Called on every update to the Reporting API endpoints
+ OnEndpointsUpdatedForOrigin(array<ReportingApiEndpoint> endpoints);
+}; \ No newline at end of file
diff --git a/chromium/services/network/public/mojom/ssl_config.mojom b/chromium/services/network/public/mojom/ssl_config.mojom
index 810a8137c0c..ebd823aee1d 100644
--- a/chromium/services/network/public/mojom/ssl_config.mojom
+++ b/chromium/services/network/public/mojom/ssl_config.mojom
@@ -20,13 +20,9 @@ struct SSLConfig {
bool sha1_local_anchors_enabled = false;
bool symantec_enforcement_disabled = false;
- // 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;
- // version_min_warn is the minimum protocol version that won't cause cert
- // errors (e.g., in Chrome we'll show a security interstitial for connections
- // using a version lower than version_min_warn).
- SSLVersion version_min_warn = kTLS12;
+ // SSL 2.0/3.0 and TLS 1.0/1.1 are not supported. Note these lines must be
+ // kept in sync with net/ssl/ssl_config.cc.
+ SSLVersion version_min = kTLS12;
SSLVersion version_max = kTLS13;
// Though cipher suites are sent in TLS as "uint8_t CipherSuite[2]", in
@@ -46,9 +42,6 @@ struct SSLConfig {
// If false, disables post-quantum key agreement in TLS connections.
bool cecpq2_enabled = true;
-
- // If false, disables 3DES cipher suites in TLS connections.
- bool triple_des_enabled = true;
};
// Receives SSL configuration updates.
diff --git a/chromium/services/network/public/mojom/supports_loading_mode.mojom b/chromium/services/network/public/mojom/supports_loading_mode.mojom
index 60357c6ed7f..3e02138bab2 100644
--- a/chromium/services/network/public/mojom/supports_loading_mode.mojom
+++ b/chromium/services/network/public/mojom/supports_loading_mode.mojom
@@ -20,6 +20,10 @@ enum LoadingMode {
// script before navigation. The document should, if necessary, personalize
// itself after loading when credentials become available, dynamically.
kUncredentialedPrerender,
+
+ // A mode to opt-in to being loaded in a fenced frame. The navigation in the
+ // root fenced frame node should not be successful if the mode is not present.
+ kFencedFrame,
};
// https://github.com/jeremyroman/alternate-loading-modes/blob/gh-pages/opt-in.md
diff --git a/chromium/services/network/public/mojom/tls_socket.mojom b/chromium/services/network/public/mojom/tls_socket.mojom
index 55db8a8e024..1356dbc6ee0 100644
--- a/chromium/services/network/public/mojom/tls_socket.mojom
+++ b/chromium/services/network/public/mojom/tls_socket.mojom
@@ -18,7 +18,7 @@ interface TLSClientSocket {
// Represents the options that consumers can specify when requesting a
// TLSClientSocket.
struct TLSClientSocketOptions {
- SSLVersion version_min = kTLS1;
+ SSLVersion version_min = kTLS12;
SSLVersion version_max = kTLS13;
// If true, the SSLInfo will be returned in the UpgradeToTLS callback on
diff --git a/chromium/services/network/public/mojom/url_loader_factory.mojom b/chromium/services/network/public/mojom/url_loader_factory.mojom
index 7b9b0302160..d66ef7589ce 100644
--- a/chromium/services/network/public/mojom/url_loader_factory.mojom
+++ b/chromium/services/network/public/mojom/url_loader_factory.mojom
@@ -57,15 +57,14 @@ const uint32 kURLLoadOptionBlockLocalRequest = 256;
// URLLoaderFactory is an interface for requesting URLs. It creates URLLoader
// instances. One URLLoader instance can load one URL.
interface URLLoaderFactory {
- // Creates a URLLoader and starts loading with the given |request|. |client|'s
+ // Creates a URLLoader and starts loading with the given `request`. `client`'s
// methods will be called when certain events related to that loading
// (e.g., response arrival) happen.
//
- // |request_id| is an arbitrary id for the request. The (routing_id,
- // request_id) pair must be unique over all calls to CreateLoaderAndStart()
- // on this factory.
+ // `request_id` is an arbitrary id for the request. `request_id` should be
+ // unique over all calls to CreateLoaderAndStart() on this factory, or 0.
//
- // |options| is a bitfield of the options defined above.
+ // `options` is a bitfield of the options defined above.
CreateLoaderAndStart(pending_receiver<URLLoader> loader,
int32 request_id,
uint32 options,
diff --git a/chromium/services/network/public/mojom/url_request.mojom b/chromium/services/network/public/mojom/url_request.mojom
index 6ad61365a1d..27477d595fd 100644
--- a/chromium/services/network/public/mojom/url_request.mojom
+++ b/chromium/services/network/public/mojom/url_request.mojom
@@ -99,13 +99,12 @@ struct WebBundleTokenParams {
};
// Options that may be set when URLRequests need to take over NetLog related
-// parameters from CorsURLLoader. The URLRequest will reuse these parameters
-// on logging. If set, contains parameters to construct a NetLogWithSource for
-// the request. If not set, URLRequest constructs a NetLogWitSource with
-// default parameters.
-struct NetLogParams {
- // The ID of NetLogSource.
+// parameters. The URLRequest will use these parameters on logging.
+// Typemapped to net::NetLogSource.
+struct NetLogSource {
+ uint32 source_type;
uint32 source_id;
+ mojo_base.mojom.TimeTicks start_time;
};
// Typemapped to network::ResourceRequest.
@@ -170,6 +169,15 @@ struct URLRequest {
// - URLLoaderFactoryParams::request_initiator_origin_lock
url.mojom.Origin? request_initiator;
+ // The chain of URLs seen during navigation redirects. This should only
+ // contain values if the mode is `RedirectMode::kNavigate`. This list
+ // will contain the initial network request URL, but not URLs from previous
+ // state in the DOM. For example, if a frame has URL A and sets its location
+ // to URL B, then the redirect chain will begin with URL B. The chain also
+ // includes the current request URL, however, it will not reflect any changes
+ // made by throttles.
+ array<url.mojom.Url> navigation_redirect_chain;
+
// If this is a subresource request initiated from an isolated world (e.g.
// from a content script of a Chrome Extension), then
// |isolated_world_origin| indicates the origin of the isolated world.
@@ -234,9 +242,6 @@ struct URLRequest {
// The priority of this request determined by Blink.
RequestPriority priority;
- // True if corresponding AppCache group should be reset.
- bool should_reset_appcache;
-
// https://wicg.github.io/cors-rfc1918/#external-request
// TODO(toyoshim): The browser should know better than renderers do.
// This is used to plumb Blink decided information for legacy code path, but
@@ -379,6 +384,10 @@ struct URLRequest {
// Spec: https://wicg.github.io/origin-policy/
bool obey_origin_policy;
+ // The original destination of a request that was passed through by a service
+ // worker.
+ RequestDestination original_destination;
+
// Params intended to be set by a trusted requestor which sends the request
// to a trusted URLLoaderFactory. Note that the main implementation of
// URLLoaderFactory is the one created in the network service via
@@ -431,15 +440,23 @@ struct URLRequest {
// decoding any non-listed stream types.
array<SourceType>? devtools_accepted_stream_types;
- // This field is set within the network service, more concretely by
- // CorsURLLoader, and solely used there unless the loader factory is
- // overridden. Setting this field by the process outside the network service
- // is currently not expected and is invalid.
- // If set correctly, it contains NetLog related parameters. This value is
- // filled and used when network service creates a new request for preflights
- // (which happens in CorsURLLoader). See the comment of NetLogParams for
- // details.
- NetLogParams? net_log_params;
+ // This field is filled and used when network service creates a new request
+ // for preflights (which happens in CorsURLLoader). So this field is set
+ // within the network service, more concretely by CorsURLLoader, and solely
+ // used there unless the loader factory is overridden. Setting this field by
+ // the process outside the network service is currently not expected and is
+ // invalid.
+ // If set, it contains NetLog related parameters to construct a NetLogSource
+ // for the request. If not set, URLRequest constructs a NetLogSource with
+ // default parameters.
+ NetLogSource? net_log_create_info;
+
+ // This field is filled and used within network service. Setting this field
+ // by the process outside the network service is currently not expected and
+ // is invalid.
+ // If set, it contains NetLog related parameters to identify the initiator
+ // of the request in NetLog.
+ NetLogSource? net_log_reference_info;
// The IP address space to which the target endpoint of this request should
// belong, or `kUnknown` if there is no such requirement.
diff --git a/chromium/services/network/public/mojom/url_response_head.mojom b/chromium/services/network/public/mojom/url_response_head.mojom
index cea1fb864ab..76a0a192fda 100644
--- a/chromium/services/network/public/mojom/url_response_head.mojom
+++ b/chromium/services/network/public/mojom/url_response_head.mojom
@@ -52,20 +52,16 @@ struct URLResponseHead {
// True if the request accessed the network in the process of retrieving data.
bool network_accessed = false;
- // The appcache this response was loaded from, or
- // kAppCacheNoCacheId (hard-coded as 0 because services/network
- // can't take a dependency on Blink).
- // TODO(rdsmith): Remove conceptual dependence on appcache.
- int64 appcache_id = 0;
-
- // The manifest url of the appcache this response was loaded from.
- // Note: this value is only populated for main resource requests.
- url.mojom.Url appcache_manifest_url;
-
// Detailed timing information used by the WebTiming, HAR and Developer
// Tools. Includes socket ID and socket reuse information.
LoadTimingInfo load_timing;
+ // Set to true if the request had devtools_request_id set and OnRawRequest
+ // and OnRawResponse are called on the corresponding DevToolsObserver. This
+ // allows Chrome DevTools Protocol clients to know whether they should wait
+ // for the signals from OnRawRequest and OnRawResponse for this request.
+ bool emitted_extra_info = false;
+
// True if the response was delivered using SPDY.
bool was_fetched_via_spdy = false;
diff --git a/chromium/services/network/public/mojom/web_bundle_handle.mojom b/chromium/services/network/public/mojom/web_bundle_handle.mojom
index f41031fae82..8250ac1c477 100644
--- a/chromium/services/network/public/mojom/web_bundle_handle.mojom
+++ b/chromium/services/network/public/mojom/web_bundle_handle.mojom
@@ -12,6 +12,7 @@ enum WebBundleErrorType {
kServingConstraintsNotMet,
kWebBundleFetchFailed,
kWebBundleRedirected,
+ kDeprecationWarning,
};
// A handle to a WebBundle instance in the Network Service. Created by a
diff --git a/chromium/services/network/public/mojom/web_client_hints_types.mojom b/chromium/services/network/public/mojom/web_client_hints_types.mojom
index 5a4a97b19cf..b311e5746a8 100644
--- a/chromium/services/network/public/mojom/web_client_hints_types.mojom
+++ b/chromium/services/network/public/mojom/web_client_hints_types.mojom
@@ -31,6 +31,8 @@ enum WebClientHintsType {
kUAPlatform = 10,
kUAModel = 11,
kUAMobile = 12,
+ // Sec-CH-UA-Full-Version is soon to be deprecated,
+ // prefer Sec-CH-UA-Full-Version-List instead.
kUAFullVersion = 13,
kUAPlatformVersion = 14,
kPrefersColorScheme = 15,
@@ -43,6 +45,8 @@ enum WebClientHintsType {
kDpr = 20, // The `sec-ch-` variant of kDpr_DEPRECATED
kResourceWidth = 21, // The `sec-ch-` variant of kResourceWidth_DEPRECATED
kViewportWidth = 22, // The `sec-ch-` variant of kViewportWidth_DEPRECATED
+ // A new client hint to deprecate `sec-ch-ua-full-version`
+ kUAFullVersionList = 23,
// Warning: Before adding a new client hint, read the warning at the top.
};
diff --git a/chromium/services/network/radio_monitor_android.cc b/chromium/services/network/radio_monitor_android.cc
index 9e3bb411afa..b303e2e3d17 100644
--- a/chromium/services/network/radio_monitor_android.cc
+++ b/chromium/services/network/radio_monitor_android.cc
@@ -5,65 +5,57 @@
#include "services/network/radio_monitor_android.h"
#include "base/metrics/histogram_functions.h"
-#include "services/network/public/cpp/features.h"
+#include "base/trace_event/trace_event.h"
+#include "net/android/radio_activity_tracker.h"
+#include "net/base/load_flags.h"
+#include "net/base/request_priority.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
namespace network {
-// static
-RadioMonitorAndroid& RadioMonitorAndroid::GetInstance() {
- static base::NoDestructor<RadioMonitorAndroid> s_instance;
- return *s_instance;
-}
-
-RadioMonitorAndroid::RadioMonitorAndroid() = default;
-
-void RadioMonitorAndroid::MaybeRecordURLLoaderAnnotationId(
+void MaybeRecordURLLoaderCreationForWakeupTrigger(
+ const ResourceRequest& request,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK(base::FeatureList::IsEnabled(features::kRecordRadioWakeupTrigger));
- if (!ShouldRecordRadioWakeupTrigger())
+ if (!net::android::RadioActivityTracker::GetInstance()
+ .ShouldRecordActivityForWakeupTrigger())
return;
- base::UmaHistogramSparse(kUmaNamePossibleWakeupTriggerURLLoader,
+ TRACE_EVENT_INSTANT1("loading", "RadioMonitorAndroid::URLLoaderWakeupRadio",
+ TRACE_EVENT_SCOPE_THREAD, "traffic_annotation",
+ traffic_annotation.unique_id_hash_code);
+
+ base::UmaHistogramEnumeration(
+ kUmaNamePossibleWakeupTriggerURLLoaderRequestDestination,
+ request.destination);
+ base::UmaHistogramEnumeration(
+ kUmaNamePossibleWakeupTriggerURLLoaderRequestPriority, request.priority,
+ static_cast<net::RequestPriority>(
+ net::RequestPrioritySize::NUM_PRIORITIES));
+ base::UmaHistogramBoolean(
+ kUmaNamePossibleWakeupTriggerURLLoaderRequestIsPrefetch,
+ request.load_flags & net::LOAD_PREFETCH);
+ base::UmaHistogramSparse(kUmaNamePossibleWakeupTriggerURLLoaderAnnotationId,
traffic_annotation.unique_id_hash_code);
}
-void RadioMonitorAndroid::MaybeRecordResolveHost(
+void MaybeRecordResolveHostForWakeupTrigger(
const mojom::ResolveHostParametersPtr& parameters) {
- DCHECK(base::FeatureList::IsEnabled(features::kRecordRadioWakeupTrigger));
- if (!ShouldRecordRadioWakeupTrigger())
+ if (!net::android::RadioActivityTracker::GetInstance()
+ .ShouldRecordActivityForWakeupTrigger())
return;
mojom::ResolveHostParameters::Purpose purpose =
parameters ? parameters->purpose
: mojom::ResolveHostParameters::Purpose::kUnspecified;
- base::UmaHistogramEnumeration(kUmaNamePossibleWakeupTriggerResolveHost,
- purpose);
-}
-bool RadioMonitorAndroid::IsRadioUtilsSupported() {
- return base::android::RadioUtils::IsSupported() ||
- radio_activity_override_for_testing_.has_value() ||
- radio_type_override_for_testing_.has_value();
-}
-
-bool RadioMonitorAndroid::ShouldRecordRadioWakeupTrigger() {
- if (!IsRadioUtilsSupported())
- return false;
-
- base::android::RadioConnectionType radio_type =
- radio_type_override_for_testing_.value_or(
- base::android::RadioUtils::GetConnectionType());
- if (radio_type != base::android::RadioConnectionType::kCell)
- return false;
+ TRACE_EVENT_INSTANT1("loading",
+ "RadioMonitorAndroid::HostResolverWakeupRadio",
+ TRACE_EVENT_SCOPE_THREAD, "purpose", purpose);
- absl::optional<base::android::RadioDataActivity> radio_activity =
- radio_activity_override_for_testing_.has_value()
- ? radio_activity_override_for_testing_
- : base::android::RadioUtils::GetCellDataActivity();
-
- return radio_activity.has_value() &&
- *radio_activity == base::android::RadioDataActivity::kDormant;
+ base::UmaHistogramEnumeration(kUmaNamePossibleWakeupTriggerResolveHost,
+ purpose);
}
} // namespace network
diff --git a/chromium/services/network/radio_monitor_android.h b/chromium/services/network/radio_monitor_android.h
index dcd7762edb3..bea3a77dec0 100644
--- a/chromium/services/network/radio_monitor_android.h
+++ b/chromium/services/network/radio_monitor_android.h
@@ -5,70 +5,39 @@
#ifndef SERVICES_NETWORK_RADIO_MONITOR_ANDROID_H_
#define SERVICES_NETWORK_RADIO_MONITOR_ANDROID_H_
-#include "base/android/radio_utils.h"
#include "base/component_export.h"
-#include "base/no_destructor.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/mojom/host_resolver.mojom-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-namespace network {
-
-constexpr char kUmaNamePossibleWakeupTriggerURLLoader[] =
- "Network.Radio.PossibleWakeupTrigger.URLLoaderAnnotationId";
-constexpr char kUmaNamePossibleWakeupTriggerResolveHost[] =
- "Network.Radio.PossibleWakeupTrigger.ResolveHostPurpose";
-
-// Checks radio states and records histograms when network activities may
-// trigger power-consuming radio state changes like wake-ups.
-class COMPONENT_EXPORT(NETWORK_SERVICE) RadioMonitorAndroid {
- public:
- static RadioMonitorAndroid& GetInstance();
-
- RadioMonitorAndroid(const RadioMonitorAndroid&) = delete;
- RadioMonitorAndroid& operator=(const RadioMonitorAndroid&) = delete;
- RadioMonitorAndroid(RadioMonitorAndroid&&) = delete;
- RadioMonitorAndroid& operator=(RadioMonitorAndroid&&) = delete;
-
- // Records a traffic annotation hash ID when a network request annotated with
- // `traffic_annotation` likely wake-ups radio.
- void MaybeRecordURLLoaderAnnotationId(
- const net::NetworkTrafficAnnotationTag& traffic_annotation);
+namespace net {
+struct NetworkTrafficAnnotationTag;
+} // namespace net
- // Records a host resolve request when the request likely wake-ups radio.
- void MaybeRecordResolveHost(
- const mojom::ResolveHostParametersPtr& parameters);
-
- // These override radio states for testing.
- void OverrideRadioActivityForTesting(
- absl::optional<base::android::RadioDataActivity> radio_activity) {
- radio_activity_override_for_testing_ = radio_activity;
- }
- void OverrideRadioTypeForTesting(
- absl::optional<base::android::RadioConnectionType> radio_type) {
- radio_type_override_for_testing_ = radio_type;
- }
-
- private:
- friend class base::NoDestructor<RadioMonitorAndroid>;
- RadioMonitorAndroid();
- ~RadioMonitorAndroid() = delete;
-
- // Returns true when RadioUtils is available or any radio states are
- // overridden for testing.
- bool IsRadioUtilsSupported();
+namespace network {
- // Returns true when radio data activity is dormant.
- // TODO(crbug.com/1232623): Consider optimizing this function. This function
- // uses Android's platform APIs which add non-negligible overheads.
- bool ShouldRecordRadioWakeupTrigger();
+struct ResourceRequest;
- // Radio state overrides for testing.
- absl::optional<base::android::RadioDataActivity>
- radio_activity_override_for_testing_;
- absl::optional<base::android::RadioConnectionType>
- radio_type_override_for_testing_;
-};
+constexpr char kUmaNamePossibleWakeupTriggerURLLoaderAnnotationId[] =
+ "Network.Radio.PossibleWakeupTrigger.URLLoaderAnnotationId2";
+constexpr char kUmaNamePossibleWakeupTriggerURLLoaderRequestDestination[] =
+ "Network.Radio.PossibleWakeupTrigger.URLLoaderRequestDestination";
+constexpr char kUmaNamePossibleWakeupTriggerURLLoaderRequestPriority[] =
+ "Network.Radio.PossibleWakeupTrigger.URLLoaderRequestPriority";
+constexpr char kUmaNamePossibleWakeupTriggerURLLoaderRequestIsPrefetch[] =
+ "Network.Radio.PossibleWakeupTrigger.URLLoaderRequestIsPrefetch";
+constexpr char kUmaNamePossibleWakeupTriggerResolveHost[] =
+ "Network.Radio.PossibleWakeupTrigger.ResolveHostPurpose2";
+
+// Records UMAs when a network request initiated by a URLLoader likely
+// wake-ups radio.
+COMPONENT_EXPORT(NETWORK_SERVICE)
+void MaybeRecordURLLoaderCreationForWakeupTrigger(
+ const ResourceRequest& request,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation);
+
+// Records a host resolve request when the request likely wake-ups radio.
+COMPONENT_EXPORT(NETWORK_SERVICE)
+void MaybeRecordResolveHostForWakeupTrigger(
+ const mojom::ResolveHostParametersPtr& parameters);
} // namespace network
diff --git a/chromium/services/network/resolve_host_request.h b/chromium/services/network/resolve_host_request.h
index 03695a4cfe3..45ef537eda7 100644
--- a/chromium/services/network/resolve_host_request.h
+++ b/chromium/services/network/resolve_host_request.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chromium/services/network/resource_scheduler/resource_scheduler.cc b/chromium/services/network/resource_scheduler/resource_scheduler.cc
index 4eef3f2ae60..c3d7e13c3ac 100644
--- a/chromium/services/network/resource_scheduler/resource_scheduler.cc
+++ b/chromium/services/network/resource_scheduler/resource_scheduler.cc
@@ -11,15 +11,15 @@
#include "base/bind.h"
#include "base/containers/contains.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/histogram_macros_local.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/supports_user_data.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/time/tick_clock.h"
@@ -73,6 +73,7 @@ enum class RequestStartTrigger {
LONG_QUEUED_REQUESTS_TIMER_FIRED,
EFFECTIVE_CONNECTION_TYPE_CHANGED,
PEER_TO_PEER_CONNECTIONS_COUNT_CHANGED,
+ FOUND_IN_CACHE,
};
const char* RequestStartTriggerString(RequestStartTrigger trigger) {
@@ -97,6 +98,8 @@ const char* RequestStartTriggerString(RequestStartTrigger trigger) {
return "EFFECTIVE_CONNECTION_TYPE_CHANGED";
case RequestStartTrigger::PEER_TO_PEER_CONNECTIONS_COUNT_CHANGED:
return "PEER_TO_PEER_CONNECTIONS_COUNT_CHANGED";
+ case RequestStartTrigger::FOUND_IN_CACHE:
+ return "FOUND_IN_CACHE";
}
}
@@ -254,7 +257,8 @@ class ResourceScheduler::ScheduledResourceRequestImpl
priority_(priority),
fifo_ordering_(0),
peak_delayable_requests_in_flight_(0u),
- host_port_pair_(net::HostPortPair::FromURL(request->url())) {
+ host_port_pair_(net::HostPortPair::FromURL(request->url())),
+ cache_checked_(false) {
DCHECK(!request_->GetUserData(kUserDataKey));
request_->SetUserData(kUserDataKey, std::make_unique<UnownedPointer>(this));
}
@@ -309,6 +313,10 @@ class ResourceScheduler::ScheduledResourceRequestImpl
ready_ = true;
}
+ void set_cache_checked() { cache_checked_ = true; }
+
+ bool cache_checked() const { return cache_checked_; }
+
void UpdateDelayableRequestsInFlight(size_t delayable_requests_in_flight) {
peak_delayable_requests_in_flight_ = std::max(
peak_delayable_requests_in_flight_, delayable_requests_in_flight);
@@ -344,12 +352,13 @@ class ResourceScheduler::ScheduledResourceRequestImpl
explicit UnownedPointer(ScheduledResourceRequestImpl* pointer)
: pointer_(pointer) {}
+ UnownedPointer(const UnownedPointer&) = delete;
+ UnownedPointer& operator=(const UnownedPointer&) = delete;
+
ScheduledResourceRequestImpl* get() const { return pointer_; }
private:
- ScheduledResourceRequestImpl* const pointer_;
-
- DISALLOW_COPY_AND_ASSIGN(UnownedPointer);
+ const raw_ptr<ScheduledResourceRequestImpl> pointer_;
};
static const void* const kUserDataKey;
@@ -358,12 +367,12 @@ class ResourceScheduler::ScheduledResourceRequestImpl
void WillStartRequest(bool* defer) override { deferred_ = *defer = !ready_; }
const ClientId client_id_;
- net::URLRequest* request_;
+ raw_ptr<net::URLRequest> request_;
bool ready_;
bool deferred_;
bool is_async_;
RequestAttributes attributes_;
- ResourceScheduler* scheduler_;
+ raw_ptr<ResourceScheduler> scheduler_;
RequestPriorityParams priority_;
uint32_t fifo_ordering_;
@@ -371,6 +380,7 @@ class ResourceScheduler::ScheduledResourceRequestImpl
size_t peak_delayable_requests_in_flight_;
// Cached to excessive recomputation in ReachedMaxRequestsPerHostPerClient().
const net::HostPortPair host_port_pair_;
+ bool cache_checked_;
base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequestImpl>
weak_ptr_factory_{this};
@@ -439,7 +449,8 @@ class ResourceScheduler::Client
}
}
- void ScheduleRequest(const net::URLRequest& url_request,
+ // Returns true if the request is started.
+ bool ScheduleRequest(const net::URLRequest& url_request,
ScheduledResourceRequestImpl* request) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
UpdateSignalQualityStatus();
@@ -448,9 +459,11 @@ class ResourceScheduler::Client
if (should_start == START_REQUEST) {
// New requests can be started synchronously without issue.
StartRequest(request, START_SYNC, RequestStartTrigger::NONE);
- } else {
- pending_requests_.Insert(request);
+ return true;
}
+
+ pending_requests_.Insert(request);
+ return false;
}
void RemoveRequest(ScheduledResourceRequestImpl* request) {
@@ -541,6 +554,78 @@ class ResourceScheduler::Client
RequestStartTrigger::LONG_QUEUED_REQUESTS_TIMER_FIRED);
}
+ void OnCacheCheckForQueuedRequestsTimerFired() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ for (RequestQueue::NetQueue::const_iterator it =
+ pending_requests_.GetNextHighestIterator();
+ it != pending_requests_.End(); ++it) {
+ if (!(*it)->cache_checked() &&
+ tick_clock_->NowTicks() - (*it)->url_request()->creation_time() >=
+ features::kQueuedRequestsCacheCheckTimeThreshold.Get()) {
+ CheckDiskCacheForPendingRequest(*it);
+ }
+ }
+ }
+
+ void CheckDiskCacheForPendingRequest(ScheduledResourceRequestImpl* request) {
+ request->set_cache_checked();
+ net::URLRequest* url_request = request->url_request();
+ net::HttpCache* http_cache =
+ url_request->context()->http_transaction_factory()->GetCache();
+ if (!http_cache)
+ return;
+
+ if (http_cache->mode() == net::HttpCache::Mode::DISABLE)
+ return;
+
+ if (url_request->method() != net::HttpRequestHeaders::kGetMethod)
+ return;
+
+ int load_flags = url_request->load_flags();
+ if (load_flags & net::LOAD_DISABLE_CACHE ||
+ load_flags & net::LOAD_BYPASS_CACHE ||
+ load_flags & net::LOAD_VALIDATE_CACHE) {
+ return;
+ }
+
+ net::Error result = http_cache->CheckResourceExistence(
+ url_request->url(), url_request->method(),
+ url_request->isolation_info().network_isolation_key(),
+ url_request->isolation_info().request_type() ==
+ net::IsolationInfo::RequestType::kSubFrame,
+ base::BindOnce(&Client::StartPendingRequestIfCached,
+ weak_ptr_factory_.GetWeakPtr(), url_request->url()));
+ if (result != net::OK)
+ return;
+
+ // It reaches here during iterating |pending_requests_|, and call
+ // StartPendingRequestIfCached() can change |pending_requests_|. So delay
+ // the run of StartPendingRequestIfCached() until after iterating
+ // |pending_requests_|.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&Client::StartPendingRequestIfCached,
+ weak_ptr_factory_.GetWeakPtr(),
+ url_request->url(), net::OK));
+ }
+
+ void StartPendingRequestIfCached(const GURL& url, net::Error result) {
+ if (result != net::OK)
+ return;
+
+ for (RequestQueue::NetQueue::const_iterator it =
+ pending_requests_.GetNextHighestIterator();
+ it != pending_requests_.End(); ++it) {
+ ScheduledResourceRequestImpl* request = *it;
+ if (request->url_request()->url() == url) {
+ // Iterator invalidation doesn't matter because we are not going to loop
+ // again.
+ pending_requests_.Erase(request);
+ StartRequest(request, START_ASYNC, RequestStartTrigger::FOUND_IN_CACHE);
+ return;
+ }
+ }
+ }
+
bool HasNoPendingRequests() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pending_requests_.IsEmpty();
@@ -1426,7 +1511,7 @@ class ResourceScheduler::Client
// Network quality estimator for network aware resource scheudling. This may
// be null.
- net::NetworkQualityEstimator* network_quality_estimator_;
+ raw_ptr<net::NetworkQualityEstimator> network_quality_estimator_;
// Resource scheduling params computed for the current network quality.
// These are recomputed every time an |OnNavigate| event is triggered.
@@ -1435,10 +1520,10 @@ class ResourceScheduler::Client
// A pointer to the resource scheduler which contains the resource scheduling
// configuration.
- ResourceScheduler* resource_scheduler_;
+ raw_ptr<ResourceScheduler> resource_scheduler_;
// Guaranteed to be non-null.
- const base::TickClock* tick_clock_;
+ raw_ptr<const base::TickClock> tick_clock_;
// Time when the last non-delayble request started in this client.
absl::optional<base::TimeTicks> last_non_delayable_request_start_;
@@ -1519,7 +1604,12 @@ ResourceScheduler::ScheduleRequest(int child_id,
}
Client* client = it->second.get();
- client->ScheduleRequest(*url_request, request.get());
+ if (!client->ScheduleRequest(*url_request, request.get())) {
+ if (base::FeatureList::IsEnabled(features::kCheckCacheForQueuedRequests)) {
+ // If the request is queued, start the cache check timer.
+ StartCacheCheckForQueuedRequestsTimer();
+ }
+ }
if (!IsLongQueuedRequestsDispatchTimerRunning())
StartLongQueuedRequestsDispatchTimerIfNeeded();
@@ -1662,6 +1752,21 @@ void ResourceScheduler::OnLongQueuedRequestsDispatchTimerFired() {
StartLongQueuedRequestsDispatchTimerIfNeeded();
}
+void ResourceScheduler::StartCacheCheckForQueuedRequestsTimer() {
+ if (check_cache_for_queued_request_timer_.IsRunning())
+ return;
+
+ check_cache_for_queued_request_timer_.Start(
+ FROM_HERE, features::kQueuedRequestsCacheCheckInterval.Get(), this,
+ &ResourceScheduler::OnCacheCheckForQueuedRequestsTimerFired);
+}
+
+void ResourceScheduler::OnCacheCheckForQueuedRequestsTimerFired() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ for (auto& client : client_map_)
+ client.second->OnCacheCheckForQueuedRequestsTimerFired();
+}
+
void ResourceScheduler::ReprioritizeRequest(net::URLRequest* request,
net::RequestPriority new_priority,
int new_intra_priority_value) {
@@ -1742,4 +1847,9 @@ void ResourceScheduler::DispatchLongQueuedRequestsForTesting() {
OnLongQueuedRequestsDispatchTimerFired();
}
+void ResourceScheduler::FireQueuedRequestsCacheCheckTimerForTesting() {
+ check_cache_for_queued_request_timer_.Stop();
+ OnCacheCheckForQueuedRequestsTimerFired();
+}
+
} // namespace network
diff --git a/chromium/services/network/resource_scheduler/resource_scheduler.h b/chromium/services/network/resource_scheduler/resource_scheduler.h
index f02286722e4..1b6740dadce 100644
--- a/chromium/services/network/resource_scheduler/resource_scheduler.h
+++ b/chromium/services/network/resource_scheduler/resource_scheduler.h
@@ -18,13 +18,14 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/feature_list.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/priority_queue.h"
#include "net/base/request_priority.h"
+#include "net/http/http_cache.h"
#include "net/nqe/effective_connection_type.h"
#include "services/network/resource_scheduler/resource_scheduler_params_manager.h"
@@ -84,6 +85,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ResourceScheduler {
};
explicit ResourceScheduler(const base::TickClock* tick_clock = nullptr);
+
+ ResourceScheduler(const ResourceScheduler&) = delete;
+ ResourceScheduler& operator=(const ResourceScheduler&) = delete;
+
virtual ~ResourceScheduler();
// Requests that this ResourceScheduler schedule, and eventually loads, the
@@ -147,6 +152,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ResourceScheduler {
// Dispatch requests that have been queued for too long to network.
void DispatchLongQueuedRequestsForTesting();
+ // Fire the timer to check cache for long queued requests.
+ void FireQueuedRequestsCacheCheckTimerForTesting();
+
private:
class Client;
class RequestQueue;
@@ -177,11 +185,17 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ResourceScheduler {
// pending requests that can be started.
void OnLongQueuedRequestsDispatchTimerFired();
+ // This timer regularly checks to see if there are any pending requests that
+ // have been queued long enough and have been cached. If yes, they can be
+ // started because they may not contend for network.
+ void StartCacheCheckForQueuedRequestsTimer();
+ void OnCacheCheckForQueuedRequestsTimerFired();
+
ClientMap client_map_;
RequestSet unowned_requests_;
// Guaranteed to be non-null.
- const base::TickClock* tick_clock_;
+ raw_ptr<const base::TickClock> tick_clock_;
// Timer to dispatch requests that may have been queued for too long.
base::OneShotTimer long_queued_requests_dispatch_timer_;
@@ -189,14 +203,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ResourceScheduler {
// Duration after which the timer to dispatch queued requests should fire.
const base::TimeDelta queued_requests_dispatch_periodicity_;
+ base::OneShotTimer check_cache_for_queued_request_timer_;
+
ResourceSchedulerParamsManager resource_scheduler_params_manager_;
// The TaskRunner to post tasks on. Can be overridden for tests.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(ResourceScheduler);
};
} // namespace network
diff --git a/chromium/services/network/resource_scheduler/resource_scheduler_client.h b/chromium/services/network/resource_scheduler/resource_scheduler_client.h
index e50e75d6774..81fc0333a22 100644
--- a/chromium/services/network/resource_scheduler/resource_scheduler_client.h
+++ b/chromium/services/network/resource_scheduler/resource_scheduler_client.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_NETWORK_RESOURCE_SCHEDULER_RESOURCE_SCHEDULER_CLIENT_H_
#define SERVICES_NETWORK_RESOURCE_SCHEDULER_RESOURCE_SCHEDULER_CLIENT_H_
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "net/base/request_priority.h"
#include "services/network/resource_scheduler/resource_scheduler.h"
@@ -32,6 +33,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ResourceSchedulerClient final
ResourceScheduler* resource_scheduler,
net::NetworkQualityEstimator* estimator);
+ ResourceSchedulerClient(const ResourceSchedulerClient&) = delete;
+ ResourceSchedulerClient& operator=(const ResourceSchedulerClient&) = delete;
+
std::unique_ptr<ResourceScheduler::ScheduledResourceRequest> ScheduleRequest(
bool is_async,
net::URLRequest* url_request);
@@ -45,9 +49,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ResourceSchedulerClient final
const int child_id_;
const int route_id_;
- ResourceScheduler* const resource_scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceSchedulerClient);
+ const raw_ptr<ResourceScheduler> resource_scheduler_;
};
} // namespace network
diff --git a/chromium/services/network/resource_scheduler/resource_scheduler_unittest.cc b/chromium/services/network/resource_scheduler/resource_scheduler_unittest.cc
index 469c76dd50c..c355ace118b 100644
--- a/chromium/services/network/resource_scheduler/resource_scheduler_unittest.cc
+++ b/chromium/services/network/resource_scheduler/resource_scheduler_unittest.cc
@@ -12,6 +12,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
@@ -25,8 +26,11 @@
#include "net/base/features.h"
#include "net/base/host_port_pair.h"
#include "net/base/isolation_info.h"
+#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/base/request_priority.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache_test_util.h"
#include "net/nqe/network_quality_estimator_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -127,12 +131,18 @@ class TestRequest {
virtual void Resume() { started_ = true; }
+ void SetMethod(const std::string& method) {
+ url_request_->set_method(method);
+ }
+
+ void SetLoadFlags(int flags) { url_request_->SetLoadFlags(flags); }
+
private:
bool started_;
std::unique_ptr<net::URLRequest> url_request_;
std::unique_ptr<ResourceScheduler::ScheduledResourceRequest>
scheduled_request_;
- ResourceScheduler* scheduler_;
+ raw_ptr<ResourceScheduler> scheduler_;
};
class CancelingTestRequest : public TestRequest {
@@ -513,6 +523,30 @@ class ResourceSchedulerTest : public testing::Test {
InitializeScheduler();
}
+ void CreateResourceEntryInCache(base::StringPiece url) {
+ auto* transaction_factory = context_->http_transaction_factory();
+ net::HttpCache* http_cache = transaction_factory->GetCache();
+ disk_cache::Backend* backend = nullptr;
+ net::TestCompletionCallback get_backend_callback;
+ int return_value =
+ http_cache->GetBackend(&backend, get_backend_callback.callback());
+ EXPECT_EQ(net::OK, get_backend_callback.GetResult(return_value));
+
+ net::HttpRequestInfo request_info;
+ request_info.url = GURL(url);
+ request_info.method = net::HttpRequestHeaders::kGetMethod;
+ request_info.network_isolation_key =
+ net::IsolationInfo().network_isolation_key();
+ request_info.is_subframe_document_resource = false;
+ std::string key = net::HttpCache::GenerateCacheKeyForTest(&request_info);
+
+ TestEntryResultCompletionCallback create_entry_callback;
+ disk_cache::EntryResult result = backend->OpenOrCreateEntry(
+ key, net::RequestPriority::LOWEST, create_entry_callback.callback());
+ EXPECT_EQ(net::OK,
+ create_entry_callback.GetResult(std::move(result)).net_error());
+ }
+
ResourceScheduler* scheduler() { return scheduler_.get(); }
base::test::TaskEnvironment task_environment_;
@@ -2491,6 +2525,108 @@ TEST_F(ResourceSchedulerTest, ProactiveThrottling_UnthrottledOnTimerFired) {
EXPECT_TRUE(low_1->started());
}
+// Verify that when the cache check timer is fired, those already cached and
+// long queued requests will be started. Non-cached, Non-GET, and requests with
+// load flags for bypassing cache or requiring validation won't be started.
+TEST_F(ResourceSchedulerTest, CheckCacheForQueuedRequests) {
+ network_quality_estimator_.SetAndNotifyObserversOfEffectiveConnectionType(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kCheckCacheForQueuedRequests);
+ InitializeScheduler();
+
+ const char* cached_resource_url =
+ "http://cache-check/already-cached-resource";
+ const char* not_cached_resource_url =
+ "http://cache-check/not-cached-resource";
+ const char* cached_resource_for_post_url =
+ "http://cache-check/already-cached-resource-for-post";
+ const char* cached_resource_with_load_flags_url =
+ "http://cache-check/already-cached-resource-with-load-flags";
+
+ // Prepare the cache for already cached requests.
+ CreateResourceEntryInCache(cached_resource_url);
+ CreateResourceEntryInCache(cached_resource_for_post_url);
+
+ int non_cache_check_load_flags[] = {
+ net::LOAD_DISABLE_CACHE,
+ net::LOAD_BYPASS_CACHE,
+ net::LOAD_VALIDATE_CACHE,
+ };
+
+ for (int flag : non_cache_check_load_flags) {
+ std::string url =
+ cached_resource_with_load_flags_url + base::NumberToString(flag);
+ CreateResourceEntryInCache(url);
+ }
+
+ // Create some low priority requests which are all started.
+ std::vector<std::unique_ptr<TestRequest>> test_requests;
+ // Should be in sync with resource_scheduler.cc for effective connection type
+ // (ECT) 2G. For ECT of 2G, number of low priority requests allowed are:
+ // 8 - 3 * count of high priority requests in flight. That expression computes
+ // to 8 - 0 = 8.
+ // Queue up to the maximum limit. Use different host names to prevent the
+ // per host limit from kicking in.
+ const int max_low_priority_requests_allowed = 8;
+ for (int i = 0; i < max_low_priority_requests_allowed; ++i) {
+ // Keep unique hostnames to prevent the per host limit from kicking in.
+ std::string url = "http://host" + base::NumberToString(i) + "/low";
+ test_requests.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(test_requests[i]->started());
+ }
+
+ // Newly created requests will be pending.
+ std::unique_ptr<TestRequest> cached_request(
+ NewRequest(cached_resource_url, net::LOWEST));
+ EXPECT_FALSE(cached_request->started());
+
+ std::unique_ptr<TestRequest> not_cached_request(
+ NewRequest(not_cached_resource_url, net::LOWEST));
+ EXPECT_FALSE(not_cached_request->started());
+
+ std::unique_ptr<TestRequest> post_cached_request(
+ NewRequest(cached_resource_for_post_url, net::LOWEST));
+ post_cached_request->SetMethod(net::HttpRequestHeaders::kPostMethod);
+ EXPECT_FALSE(post_cached_request->started());
+
+ std::vector<std::unique_ptr<TestRequest>> cached_requests_with_load_flags;
+ for (int flag : non_cache_check_load_flags) {
+ std::unique_ptr<TestRequest> request(NewRequest(
+ (cached_resource_with_load_flags_url + base::NumberToString(flag))
+ .c_str(),
+ net::LOWEST));
+ request->SetLoadFlags(request->url_request()->load_flags() | flag);
+ EXPECT_FALSE(request->started());
+ cached_requests_with_load_flags.push_back(std::move(request));
+ }
+
+ // Advance the clock by more than
+ // |features::kQueuedRequestsCacheCheckTimeThreshold|.
+ tick_clock_.SetNowTicks(
+ base::DefaultTickClock::GetInstance()->NowTicks() +
+ network::features::kQueuedRequestsCacheCheckTimeThreshold.Get() +
+ base::Milliseconds(1));
+
+ // Trigger the cache check timer. Cache check will be performed.
+ scheduler()->FireQueuedRequestsCacheCheckTimerForTesting();
+ base::RunLoop().RunUntilIdle();
+
+ // Long queued cached request is started.
+ EXPECT_TRUE(cached_request->started());
+ // Not cached request is still pending.
+ EXPECT_FALSE(not_cached_request->started());
+ // Cached request with 'POST' method is still pending.
+ EXPECT_FALSE(post_cached_request->started());
+ // Cached requests with load flags in |non_cache_check_load_flags| are still
+ // pending.
+ for (auto& request : cached_requests_with_load_flags) {
+ EXPECT_FALSE(request->started());
+ }
+}
+
} // unnamed namespace
} // namespace network
diff --git a/chromium/services/network/restricted_cookie_manager.cc b/chromium/services/network/restricted_cookie_manager.cc
index 425426fd5a2..c17b4d0d01e 100644
--- a/chromium/services/network/restricted_cookie_manager.cc
+++ b/chromium/services/network/restricted_cookie_manager.cc
@@ -10,10 +10,11 @@
#include "base/bind.h"
#include "base/compiler_specific.h" // for FALLTHROUGH;
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -161,7 +162,7 @@ CookieAccesses* RestrictedCookieManager::GetCookieAccessesForURLAndSite(
const GURL& url,
const net::SiteForCookies& site_for_cookies) {
std::unique_ptr<CookieAccesses>& entry =
- recent_cookie_accesses_[std::tie(url, site_for_cookies)];
+ recent_cookie_accesses_[std::make_pair(url, site_for_cookies)];
if (!entry) {
entry = std::make_unique<CookieAccesses>();
}
@@ -289,14 +290,14 @@ class RestrictedCookieManager::Listener : public base::LinkNode<Listener> {
}
// Expected to outlive |restricted_cookie_manager_| which outlives this.
- const net::CookieStore* cookie_store_;
+ raw_ptr<const net::CookieStore> cookie_store_;
// The CookieChangeDispatcher subscription used by this listener.
std::unique_ptr<net::CookieChangeSubscription> cookie_store_subscription_;
// Raw pointer usage is safe because RestrictedCookieManager owns this
// instance and is guaranteed to outlive it.
- const RestrictedCookieManager* const restricted_cookie_manager_;
+ const raw_ptr<const RestrictedCookieManager> restricted_cookie_manager_;
// The URL whose cookies this listener is interested in.
const GURL url_;
@@ -348,10 +349,11 @@ RestrictedCookieManager::~RestrictedCookieManager() {
}
void RestrictedCookieManager::ComputeCookiePartitionKey() {
- cookie_partition_key_ = net::CookiePartitionKey::FromNetworkIsolationKey(
+ cookie_partition_key_ = net::CookieAccessDelegate::CreateCookiePartitionKey(
+ cookie_store_->cookie_access_delegate(),
isolation_info_.network_isolation_key());
- cookie_partition_keychain_ =
- net::CookiePartitionKeychain::FromOptional(cookie_partition_key_);
+ cookie_partition_key_collection_ =
+ net::CookiePartitionKeyCollection::FromOptional(cookie_partition_key_);
}
void RestrictedCookieManager::GetAllForUrl(
@@ -377,7 +379,7 @@ void RestrictedCookieManager::GetAllForUrl(
net_options.set_return_excluded_cookies();
cookie_store_->GetCookieListWithOptionsAsync(
- url, net_options, cookie_partition_keychain_,
+ url, net_options, cookie_partition_key_collection_,
base::BindOnce(&RestrictedCookieManager::CookieListToGetAllForUrlCallback,
weak_ptr_factory_.GetWeakPtr(), url, site_for_cookies,
top_frame_origin, net_options, std::move(options),
@@ -534,12 +536,48 @@ void RestrictedCookieManager::SetCanonicalCookie(
GURL::SchemeIsCryptographic(origin_.scheme())
? net::CookieSourceScheme::kSecure
: net::CookieSourceScheme::kNonSecure;
+
+ // If the renderer's cookie has a partition key that was not created using
+ // CookiePartitionKey::FromScript, then the cookie's partition key should be
+ // equal to RestrictedCookieManager's partition key.
+ absl::optional<net::CookiePartitionKey> cookie_partition_key =
+ cookie.PartitionKey();
+ if (cookie_partition_key) {
+ // RestrictedCookieManager having a null partition key strictly implies the
+ // feature is disabled. If that is the case, we treat the cookie as
+ // unpartitioned.
+ if (!cookie_partition_key_) {
+ cookie_partition_key = absl::nullopt;
+ } else {
+ bool cookie_partition_key_ok =
+ cookie.PartitionKey()->from_script() ||
+ cookie.PartitionKey().value() == cookie_partition_key_.value();
+ UMA_HISTOGRAM_BOOLEAN("Net.RestrictedCookieManager.CookiePartitionKeyOK",
+ cookie_partition_key_ok);
+ if (!cookie_partition_key_ok) {
+ mojo::ReportBadMessage(
+ "RestrictedCookieManager: unexpected cookie partition key");
+ std::move(callback).Run(false);
+ return;
+ }
+ if (cookie.PartitionKey()->from_script()) {
+ cookie_partition_key = cookie_partition_key_;
+ }
+ }
+ }
+
auto sanitized_cookie = net::CanonicalCookie::FromStorage(
cookie.Name(), cookie.Value(), cookie.Domain(), cookie.Path(), now,
cookie.ExpiryDate(), now, cookie.IsSecure(), cookie.IsHttpOnly(),
cookie.SameSite(), cookie.Priority(), cookie.IsSameParty(),
- cookie.PartitionKey(), source_scheme, origin_.port());
+ cookie_partition_key, source_scheme, origin_.port());
DCHECK(sanitized_cookie);
+ // FromStorage() uses a less strict version of IsCanonical(), we need to check
+ // the stricter version as well here.
+ if (!sanitized_cookie->IsCanonical()) {
+ std::move(callback).Run(false);
+ return;
+ }
net::CanonicalCookie cookie_copy = *sanitized_cookie;
net::CookieOptions options = MakeOptionsForSet(
diff --git a/chromium/services/network/restricted_cookie_manager.h b/chromium/services/network/restricted_cookie_manager.h
index 4bdc38981ea..1333fcbee32 100644
--- a/chromium/services/network/restricted_cookie_manager.h
+++ b/chromium/services/network/restricted_cookie_manager.h
@@ -11,7 +11,7 @@
#include "base/component_export.h"
#include "base/containers/linked_list.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -179,11 +179,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
return isolation_info_.top_frame_origin().value();
}
- const absl::optional<net::CookiePartitionKey> CookiePartitionKey() const {
- return net::CookiePartitionKey::FromNetworkIsolationKey(
- isolation_info_.network_isolation_key());
- }
-
CookieAccesses* GetCookieAccessesForURLAndSite(
const GURL& url,
const net::SiteForCookies& site_for_cookies);
@@ -195,7 +190,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
const net::CookieWithAccessResult& cookie_item);
const mojom::RestrictedCookieManagerRole role_;
- net::CookieStore* const cookie_store_;
+ const raw_ptr<net::CookieStore> cookie_store_;
const CookieSettings& cookie_settings_;
url::Origin origin_;
@@ -214,10 +209,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
// Cookie partition key that the instance of RestrictedCookieManager will have
// access to.
absl::optional<net::CookiePartitionKey> cookie_partition_key_;
- // CookiePartitionKeychain that is either empty if `cookie_partition_key_` is
- // nullopt. If `cookie_partition_key_` is not null, the keychain contains its
- // value.
- net::CookiePartitionKeychain cookie_partition_keychain_;
+ // CookiePartitionKeyCollection that is either empty if
+ // `cookie_partition_key_` is nullopt. If `cookie_partition_key_` is not null,
+ // the key collection contains its value.
+ net::CookiePartitionKeyCollection cookie_partition_key_collection_;
// Contains a mapping of url/site -> recent cookie updates for duplicate
// update filtering.
diff --git a/chromium/services/network/restricted_cookie_manager_unittest.cc b/chromium/services/network/restricted_cookie_manager_unittest.cc
index c6fbdd4f284..3ec5579b6f9 100644
--- a/chromium/services/network/restricted_cookie_manager_unittest.cc
+++ b/chromium/services/network/restricted_cookie_manager_unittest.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
@@ -185,7 +186,7 @@ class RestrictedCookieManagerSync {
}
private:
- mojom::RestrictedCookieManager* cookie_service_;
+ raw_ptr<mojom::RestrictedCookieManager> cookie_service_;
};
namespace {
@@ -224,7 +225,7 @@ class TestCookieChangeListener : public network::mojom::CookieChangeListener {
mojo::Receiver<network::mojom::CookieChangeListener> receiver_;
// If not null, will be stopped when a cookie change notification is received.
- base::RunLoop* run_loop_ = nullptr;
+ raw_ptr<base::RunLoop> run_loop_ = nullptr;
};
} // namespace
@@ -1542,13 +1543,13 @@ INSTANTIATE_TEST_SUITE_P(
::testing::Values(mojom::RestrictedCookieManagerRole::SCRIPT,
mojom::RestrictedCookieManagerRole::NETWORK));
-class PartitionedCookiesEnabledRestrictedCookieManagerTest
+class PartitionedCookiesRestrictedCookieManagerTest
: public RestrictedCookieManagerTest {
public:
- PartitionedCookiesEnabledRestrictedCookieManagerTest() {
+ PartitionedCookiesRestrictedCookieManagerTest() {
feature_list_.InitAndEnableFeature(net::features::kPartitionedCookies);
}
- ~PartitionedCookiesEnabledRestrictedCookieManagerTest() override = default;
+ ~PartitionedCookiesRestrictedCookieManagerTest() override = default;
private:
base::test::ScopedFeatureList feature_list_;
@@ -1643,9 +1644,37 @@ TEST_P(RestrictedCookieManagerTest, PartitionedCookies) {
}
}
+TEST_P(RestrictedCookieManagerTest, PartitionKeyFromScript) {
+ const GURL kCookieURL("https://example.com");
+ const GURL kTopFrameURL("https://foo.com");
+ const net::SiteForCookies kSiteForCookies =
+ net::SiteForCookies::FromUrl(kTopFrameURL);
+ const url::Origin kTopFrameOrigin = url::Origin::Create(kTopFrameURL);
+ const net::IsolationInfo kIsolationInfo =
+ net::IsolationInfo::CreateForInternalRequest(kTopFrameOrigin);
+ service_->OverrideIsolationInfoForTesting(kIsolationInfo);
+
+ EXPECT_TRUE(sync_service_->SetCanonicalCookie(
+ *net::CanonicalCookie::Create(
+ kCookieURL,
+ "__Host-foo=bar; Secure; SameSite=None; Path=/; Partitioned",
+ base::Time::Now(), absl::nullopt /* server_time */,
+ net::CookiePartitionKey::FromScript()),
+ kCookieURL, kSiteForCookies, kTopFrameOrigin));
+
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies = sync_service_->GetAllForUrl(
+ kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options));
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_FALSE(cookies[0].IsPartitioned());
+ EXPECT_EQ("__Host-foo", cookies[0].Name());
+}
+
// Test Partitioned cookie behavior when feature is enabled.
-TEST_P(PartitionedCookiesEnabledRestrictedCookieManagerTest,
- PartitionedCookies) {
+TEST_P(PartitionedCookiesRestrictedCookieManagerTest, PartitionedCookies) {
const GURL kCookieURL("https://example.com");
const GURL kTopFrameURL("https://sub.foo.com");
const net::SiteForCookies kSiteForCookies =
@@ -1739,11 +1768,236 @@ TEST_P(PartitionedCookiesEnabledRestrictedCookieManagerTest,
second_listener->WaitForChange();
ASSERT_THAT(listener->observed_changes(), testing::SizeIs(0));
}
+
+ { // Test that a cookie cannot be set with a different partition key than
+ // RestrictedCookieManager's.
+ service_->OverrideIsolationInfoForTesting(kIsolationInfo);
+ ExpectBadMessage();
+ EXPECT_FALSE(sync_service_->SetCanonicalCookie(
+ *net::CanonicalCookie::Create(
+ kCookieURL,
+ "__Host-foo=bar; Secure; SameSite=None; Path=/; Partitioned",
+ base::Time::Now(), absl::nullopt /* server_time */,
+ absl::make_optional(net::CookiePartitionKey::FromURLForTesting(
+ GURL("https://foo.bar.com")))),
+ kCookieURL, kSiteForCookies, kTopFrameOrigin));
+ }
+}
+
+TEST_P(PartitionedCookiesRestrictedCookieManagerTest, PartitionKeyFromScript) {
+ const GURL kCookieURL("https://example.com");
+ const GURL kTopFrameURL("https://foo.com");
+ const net::SiteForCookies kSiteForCookies =
+ net::SiteForCookies::FromUrl(kTopFrameURL);
+ const url::Origin kTopFrameOrigin = url::Origin::Create(kTopFrameURL);
+ const net::IsolationInfo kIsolationInfo =
+ net::IsolationInfo::CreateForInternalRequest(kTopFrameOrigin);
+
+ service_->OverrideIsolationInfoForTesting(kIsolationInfo);
+ EXPECT_TRUE(sync_service_->SetCanonicalCookie(
+ *net::CanonicalCookie::Create(
+ kCookieURL,
+ "__Host-foo=bar; Secure; SameSite=None; Path=/; Partitioned",
+ base::Time::Now(), absl::nullopt /* server_time */,
+ net::CookiePartitionKey::FromScript()),
+ kCookieURL, kSiteForCookies, kTopFrameOrigin));
+
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies = sync_service_->GetAllForUrl(
+ kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options));
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_TRUE(cookies[0].IsPartitioned());
+ EXPECT_EQ(cookies[0].PartitionKey().value(),
+ net::CookiePartitionKey::FromURLForTesting(kTopFrameURL));
+ EXPECT_EQ("__Host-foo", cookies[0].Name());
+}
+
+// Tests the interaction between First-Party Sets and partitioned cookies in
+// RestrictedCookieManager. When FPS are enabled, RestrictedCookieManager
+// should use the same cookie partition key for all sites in
+TEST_P(PartitionedCookiesRestrictedCookieManagerTest,
+ PartitionedCookiesAndFirstPartySets) {
+ const GURL kOwnerURL("https://owner.com");
+ const net::SchemefulSite kOwnerSite(kOwnerURL);
+ const url::Origin kOwnerOrigin = url::Origin::Create(kOwnerURL);
+ const net::IsolationInfo kOwnerIsolationInfo =
+ net::IsolationInfo::CreateForInternalRequest(kOwnerOrigin);
+ const net::SiteForCookies kOwnerSiteForCookies =
+ net::SiteForCookies::FromUrl(kOwnerURL);
+
+ const GURL kMemberURL("https://member.com");
+ const net::SchemefulSite kMemberSite(kMemberURL);
+ const url::Origin kMemberOrigin = url::Origin::Create(kMemberURL);
+ const net::IsolationInfo kMemberIsolationInfo =
+ net::IsolationInfo::CreateForInternalRequest(kMemberOrigin);
+ const net::SiteForCookies kMemberSiteForCookies =
+ net::SiteForCookies::FromUrl(kMemberURL);
+
+ const GURL kNonMemberURL("https://nonmember.com");
+ const url::Origin kNonMemberOrigin = url::Origin::Create(kNonMemberURL);
+ const net::IsolationInfo kNonMemberIsolationInfo =
+ net::IsolationInfo::CreateForInternalRequest(kNonMemberOrigin);
+ const net::SiteForCookies kNonMemberSiteForCookies =
+ net::SiteForCookies::FromUrl(kNonMemberURL);
+
+ const GURL kCookieURL("https://example.com");
+
+ base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>
+ first_party_sets;
+ first_party_sets.insert(std::make_pair(
+ kOwnerSite, std::set<net::SchemefulSite>({kOwnerSite, kMemberSite})));
+ auto cookie_access_delegate =
+ std::make_unique<net::TestCookieAccessDelegate>();
+ cookie_access_delegate->SetFirstPartySets(first_party_sets);
+ cookie_monster_.SetCookieAccessDelegate(std::move(cookie_access_delegate));
+
+ // Set https://example.com cookie when the top-frame site is the owner
+ // of the set.
+ service_->OverrideIsolationInfoForTesting(kOwnerIsolationInfo);
+ sync_service_->SetCookieFromString(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin,
+ "__Host-foo=0; Secure; SameSite=None; Path=/; Partitioned");
+
+ {
+ // Check that its partition key is the set's owner site.
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies = sync_service_->GetAllForUrl(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin, std::move(options));
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_TRUE(cookies[0].IsPartitioned());
+ EXPECT_EQ(net::CookiePartitionKey::FromURLForTesting(kOwnerURL),
+ cookies[0].PartitionKey());
+ EXPECT_EQ("__Host-foo", cookies[0].Name());
+
+ auto listener = CreateCookieChangeListener(kCookieURL, kOwnerSiteForCookies,
+ kOwnerOrigin);
+
+ // Update partitioned cookie Max-Age: None -> 7200.
+ sync_service_->SetCookieFromString(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin,
+ "__Host-foo=0; Secure; SameSite=None; Path=/; Partitioned; "
+ "Max-Age: 7200");
+
+ listener->WaitForChange();
+ ASSERT_THAT(listener->observed_changes(), testing::SizeIs(1));
+ }
+
+ {
+ // Check that cookie is available to https://example.com when the top-frame
+ // site is a site that is a member of the set but not the owner.
+ service_->OverrideIsolationInfoForTesting(kMemberIsolationInfo);
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies = sync_service_->GetAllForUrl(
+ kCookieURL, kMemberSiteForCookies, kMemberOrigin, std::move(options));
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_TRUE(cookies[0].IsPartitioned());
+ EXPECT_EQ(net::CookiePartitionKey::FromURLForTesting(kOwnerURL),
+ cookies[0].PartitionKey());
+ EXPECT_EQ("__Host-foo", cookies[0].Name());
+
+ auto listener = CreateCookieChangeListener(
+ kCookieURL, kMemberSiteForCookies, kMemberOrigin);
+
+ // Update partitioned cookie Max-Age: None -> 7200.
+ service_->OverrideIsolationInfoForTesting(kOwnerIsolationInfo);
+ sync_service_->SetCookieFromString(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin,
+ "__Host-foo=0; Secure; SameSite=None; Path=/; Partitioned; "
+ "Max-Age: 3600");
+
+ listener->WaitForChange();
+ ASSERT_THAT(listener->observed_changes(), testing::SizeIs(1));
+ }
+
+ // Set https://example.com cookie when the top-frame site is a member of
+ // the set.
+ service_->OverrideIsolationInfoForTesting(kMemberIsolationInfo);
+ sync_service_->SetCookieFromString(
+ kCookieURL, kMemberSiteForCookies, kMemberOrigin,
+ "__Host-bar=1; Secure; SameSite=None; Path=/; Partitioned");
+
+ {
+ // Check that the new cookie's partition key is the set's owner site.
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies = sync_service_->GetAllForUrl(
+ kCookieURL, kMemberSiteForCookies, kMemberOrigin, std::move(options));
+ ASSERT_EQ(2u, cookies.size());
+
+ EXPECT_EQ("__Host-foo", cookies[0].Name());
+ EXPECT_EQ("__Host-bar", cookies[1].Name());
+ for (const auto& cookie : cookies) {
+ EXPECT_TRUE(cookie.IsPartitioned());
+ EXPECT_EQ(net::CookiePartitionKey::FromURLForTesting(kOwnerURL),
+ cookie.PartitionKey());
+ }
+ }
+
+ {
+ // Check that the owner site can also access both cookies.
+ service_->OverrideIsolationInfoForTesting(kOwnerIsolationInfo);
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies = sync_service_->GetAllForUrl(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin, std::move(options));
+ ASSERT_EQ(2u, cookies.size());
+ EXPECT_EQ("__Host-foo", cookies[0].Name());
+ EXPECT_EQ("__Host-bar", cookies[1].Name());
+ }
+
+ {
+ // Check that the cookies are not available to https://example.com when the
+ // top-frame site is not a member of the set.
+ service_->OverrideIsolationInfoForTesting(kNonMemberIsolationInfo);
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ net::CookieList cookies =
+ sync_service_->GetAllForUrl(kCookieURL, kNonMemberSiteForCookies,
+ kNonMemberOrigin, std::move(options));
+ ASSERT_EQ(0u, cookies.size());
+
+ auto listener = CreateCookieChangeListener(
+ kCookieURL, kNonMemberSiteForCookies, kNonMemberOrigin);
+
+ // Set a new listener with the original IsolationInfo, we wait for this
+ // listener to receive an event to verify that the second listener was
+ // either called or skipped.
+ service_->OverrideIsolationInfoForTesting(kOwnerIsolationInfo);
+ auto second_listener = CreateCookieChangeListener(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin);
+
+ // Update partitioned cookie __Host-bar's Max-Age: None -> 3600.
+ service_->OverrideIsolationInfoForTesting(kOwnerIsolationInfo);
+ sync_service_->SetCookieFromString(
+ kCookieURL, kOwnerSiteForCookies, kOwnerOrigin,
+ "__Host-bar=1; Secure; SameSite=None; Path=/; Partitioned; "
+ "Max-Age: 3600");
+
+ // The listener set on the non-member top-frame site should not be able to
+ // observe the change.
+ second_listener->WaitForChange();
+ ASSERT_THAT(listener->observed_changes(), testing::SizeIs(0));
+ }
}
INSTANTIATE_TEST_SUITE_P(
PartitionedCookies,
- PartitionedCookiesEnabledRestrictedCookieManagerTest,
+ PartitionedCookiesRestrictedCookieManagerTest,
::testing::Values(mojom::RestrictedCookieManagerRole::SCRIPT,
mojom::RestrictedCookieManagerRole::NETWORK));
diff --git a/chromium/services/network/sct_auditing/README.md b/chromium/services/network/sct_auditing/README.md
index 6ae6426def3..ecedccb5529 100644
--- a/chromium/services/network/sct_auditing/README.md
+++ b/chromium/services/network/sct_auditing/README.md
@@ -9,3 +9,27 @@ The current implementation is described in the
[Opt-in SCT Auditing design doc][1].
[1]: https://docs.google.com/document/d/1G1Jy8LJgSqJ-B673GnTYIG4b7XRw2ZLtvvSlrqFcl4A/edit
+
+The SCT auditing code is composed of three main components:
+
+* `SCTAuditingCache`: This is the main entrypoint for new SCT auditing
+ reports. There is one cache instance owned by the NetworkService that is
+ shared across all NetworkContexts.
+* `SCTAuditingHandler`: The SCTAuditingHandler keeps track of pending reports
+ for each NetworkContext. It is also responsible for persisting and restoring
+ pending reports across restarts.
+* `SCTAuditingReporter`: This class owns a single report and manages its
+ lifetime (sending to the server, handling retries, etc.).
+
+The `SCTAuditingDelegate` interface is defined in `//net` with a concrete
+implementation (of the same name) in `NetworkContext`. This exposes an interface
+for SCT auditing collection points in `//net` to enqueue reports with the SCT
+auditing system in the network service by passing it along via the
+NetworkContext. Collection points outside of `//net` (that are aware of the
+network service) instead use `NetworkContext::MaybeEnqueueSCTReport()` directly.
+
+SCT auditing is disabled by default, and is enabled and initialized by the
+embedder calling `NetworkService::ConfigureSCTAuditing()` (which is exposed via
+Mojo). Separately, each NetworkContext tracks whether it has SCT auditing
+enabled, which can be configured by `NetworkContext::SetSCTAuditingEnabled()`
+(which is also exposed via Mojo).
diff --git a/chromium/services/network/sct_auditing/sct_auditing_cache.cc b/chromium/services/network/sct_auditing/sct_auditing_cache.cc
index 70c91f2d8fc..258482e8fb0 100644
--- a/chromium/services/network/sct_auditing/sct_auditing_cache.cc
+++ b/chromium/services/network/sct_auditing/sct_auditing_cache.cc
@@ -5,36 +5,23 @@
#include "services/network/sct_auditing/sct_auditing_cache.h"
#include "base/callback.h"
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/rand_util.h"
#include "components/version_info/version_info.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
-#include "net/base/elements_upload_data_stream.h"
#include "net/base/hash_value.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/load_flags.h"
-#include "net/base/net_errors.h"
-#include "net/base/request_priority.h"
-#include "net/base/upload_bytes_element_reader.h"
#include "net/cert/ct_serialization.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/cert/x509_certificate.h"
-#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/simple_url_loader.h"
-#include "services/network/public/mojom/network_context.mojom.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "services/network/network_context.h"
#include "services/network/public/proto/sct_audit_report.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "services/network/sct_auditing/sct_auditing_handler.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
@@ -42,19 +29,10 @@ namespace network {
namespace {
-constexpr int kSendSCTReportTimeoutSeconds = 30;
-
-// Overrides the initial retry delay in SCTAuditingReporter::kBackoffPolicy if
-// not nullopt.
-absl::optional<base::TimeDelta> g_retry_delay_for_testing = absl::nullopt;
-
// Records the high-water mark of the cache size (in number of reports).
-void RecordSCTAuditingCacheHighWaterMarkMetrics(size_t cache_hwm,
- size_t reporters_hwm) {
+void RecordSCTAuditingCacheHighWaterMarkMetrics(size_t cache_hwm) {
base::UmaHistogramCounts1000("Security.SCTAuditing.OptIn.DedupeCacheHWM",
cache_hwm);
- base::UmaHistogramCounts1000("Security.SCTAuditing.OptIn.ReportersHWM",
- reporters_hwm);
}
// Records whether a new report is deduplicated against an existing report in
@@ -78,208 +56,15 @@ void RecordSCTAuditingReportSizeMetrics(size_t report_size) {
report_size);
}
-// Records whether sending the report to the reporting server succeeded for each
-// report sent.
-void RecordSCTAuditingReportSucceededMetrics(bool success) {
- base::UmaHistogramBoolean("Security.SCTAuditing.OptIn.ReportSucceeded",
- success);
-}
-
-// Records whether a report succeeded/failed with retries.
-void ReportSCTAuditingCompletionStatusMetrics(
- SCTAuditingReporter::CompletionStatus status) {
- base::UmaHistogramEnumeration(
- "Security.SCTAuditing.OptIn.ReportCompletionStatus", status);
-}
-
} // namespace
-// static
-const net::BackoffEntry::Policy SCTAuditingReporter::kDefaultBackoffPolicy = {
- // Don't ignore initial errors; begin exponential back-off rules immediately
- // if the first attempt fails.
- .num_errors_to_ignore = 0,
- // Start with a 30s delay, including for the first attempt (due to setting
- // `always_use_initial_delay = true` below).
- .initial_delay_ms = 30 * 1000,
- // Double the backoff delay each retry.
- .multiply_factor = 2.0,
- // Spread requests randomly between 80-100% of the calculated backoff time.
- .jitter_factor = 0.2,
- // Max retry delay is 1 day.
- .maximum_backoff_ms = 24 * 60 * 60 * 1000,
- // Never discard the entry.
- .entry_lifetime_ms = -1,
- // Initial attempt will be delayed (and jittered). This reduces the risk of
- // a "thundering herd" of reports on startup if a user has many reports
- // persisted (once pending reports are persisted and recreated at startup
- // with a new BackoffEntry).
- .always_use_initial_delay = true,
-};
-
-// How many times an SCTAuditingReporter should retry sending an audit report.
-// Given kDefaultBackoffPolicy above and 15 total retries, this means there will
-// be five attempts in the first 30 minutes and then occasional retries for
-// roughly the next five days.
-// See more discussion in the SCT Auditing Retry and Persistence design doc:
-// https://docs.google.com/document/d/1YTUzoG6BDF1QIxosaQDp2H5IzYY7_fwH8qNJXSVX8OQ/edit
-constexpr size_t kMaxRetries = 15;
-
-SCTAuditingReporter::SCTAuditingReporter(
- net::SHA256HashValue reporter_key,
- std::unique_ptr<sct_auditing::SCTClientReport> report,
- mojom::URLLoaderFactory& url_loader_factory,
- const GURL& report_uri,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
- ReporterDoneCallback done_callback)
- : reporter_key_(reporter_key),
- report_(std::move(report)),
- traffic_annotation_(traffic_annotation),
- report_uri_(report_uri),
- done_callback_(std::move(done_callback)),
- num_retries_(0),
- max_retries_(kMaxRetries) {
- // Clone the URLLoaderFactory to avoid any dependencies on its lifetime. The
- // Reporter instance can maintain its own copy.
- // Relatively few Reporters are expected to exist at a time (due to sampling
- // and deduplication), so some cost of copying is reasonable. If more
- // optimization is needed, this could potentially use a mojo::SharedRemote
- // or a WrappedPendingSharedURLLoaderFactory instead.
- url_loader_factory.Clone(
- url_loader_factory_remote_.BindNewPipeAndPassReceiver());
-
- // Override the retry delay if set by tests.
- backoff_policy_ = kDefaultBackoffPolicy;
- if (g_retry_delay_for_testing) {
- backoff_policy_.initial_delay_ms =
- g_retry_delay_for_testing->InMilliseconds();
- }
- backoff_entry_ = std::make_unique<net::BackoffEntry>(&backoff_policy_);
-
- // Informing the backoff entry of a success will force it to use the initial
- // delay (and jitter) for the first attempt. Otherwise, ShouldRejectRequest()
- // will return `true` despite the policy specifying
- // `always_use_initial_delay = true`.
- backoff_entry_->InformOfRequest(true);
-
- // Start sending the report.
- ScheduleReport();
-}
-
-SCTAuditingReporter::~SCTAuditingReporter() = default;
-
-void SCTAuditingReporter::ScheduleReport() {
- if (base::FeatureList::IsEnabled(
- features::kSCTAuditingRetryAndPersistReports) &&
- backoff_entry_->ShouldRejectRequest()) {
- // TODO(crbug.com/1199827): Investigate if explicit task traits should be
- // used for these tasks (e.g., BEST_EFFORT and SKIP_ON_SHUTDOWN).
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&SCTAuditingReporter::SendReport,
- weak_factory_.GetWeakPtr()),
- backoff_entry_->GetTimeUntilRelease());
- } else {
- SendReport();
- }
-}
-
-void SCTAuditingReporter::SendReport() {
- DCHECK(url_loader_factory_remote_);
-
- // Create a SimpleURLLoader for the request.
- auto report_request = std::make_unique<ResourceRequest>();
- report_request->url = report_uri_;
- report_request->method = "POST";
- report_request->load_flags = net::LOAD_DISABLE_CACHE;
- report_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
-
- url_loader_ = SimpleURLLoader::Create(
- std::move(report_request),
- static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation_));
- url_loader_->SetTimeoutDuration(base::Seconds(kSendSCTReportTimeoutSeconds));
- // Retry is handled by SCTAuditingReporter.
- url_loader_->SetRetryOptions(0, SimpleURLLoader::RETRY_NEVER);
-
- // Serialize the report and attach it to the loader.
- // TODO(crbug.com/1199566): Should we store the serialized report instead, so
- // we don't serialize on every retry?
- std::string report_data;
- bool ok = report_->SerializeToString(&report_data);
- DCHECK(ok);
- url_loader_->AttachStringForUpload(report_data, "application/octet-stream");
-
- // The server acknowledges receiving the report via a successful HTTP status
- // with no response body, so this uses DownloadHeadersOnly for simplicity.
- // If the loader is destroyed, the callback will be canceled, so using
- // base::Unretained here is safe.
- url_loader_->DownloadHeadersOnly(
- url_loader_factory_remote_.get(),
- base::BindOnce(&SCTAuditingReporter::OnSendReportComplete,
- base::Unretained(this)));
-}
-
-void SCTAuditingReporter::OnSendReportComplete(
- scoped_refptr<net::HttpResponseHeaders> headers) {
- int response_code = 0;
- if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) {
- response_code = url_loader_->ResponseInfo()->headers->response_code();
- }
- bool success =
- url_loader_->NetError() == net::OK && response_code == net::HTTP_OK;
-
- RecordSCTAuditingReportSucceededMetrics(success);
-
- if (base::FeatureList::IsEnabled(
- features::kSCTAuditingRetryAndPersistReports)) {
- if (success) {
- // Report succeeded.
- if (num_retries_ == 0) {
- ReportSCTAuditingCompletionStatusMetrics(
- CompletionStatus::kSuccessFirstTry);
- } else {
- ReportSCTAuditingCompletionStatusMetrics(
- CompletionStatus::kSuccessAfterRetries);
- }
-
- // Notify the Cache that this Reporter is done. This will delete |this|,
- // so do not add code after this point.
- std::move(done_callback_).Run(reporter_key_);
- return;
- }
- // Sending the report failed.
- if (num_retries_ >= max_retries_) {
- // Retry limit reached.
- ReportSCTAuditingCompletionStatusMetrics(
- CompletionStatus::kRetriesExhausted);
-
- // Notify the Cache that this Reporter is done. This will delete |this|,
- // so do not add code after this point.
- std::move(done_callback_).Run(reporter_key_);
- return;
- } else {
- // Schedule a retry.
- ++num_retries_;
- backoff_entry_->InformOfRequest(false);
- ScheduleReport();
- }
- } else {
- // Retry is not enabled, so just notify the Cache that this Reporter is
- // done. This will delete |this|, so do not add code after this point.
- std::move(done_callback_).Run(reporter_key_);
- return;
- }
-}
-
SCTAuditingCache::SCTAuditingCache(size_t cache_size)
- : dedupe_cache_(cache_size),
- dedupe_cache_size_hwm_(0),
- pending_reporters_(cache_size),
- pending_reporters_size_hwm_(0) {}
+ : dedupe_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&
@@ -375,43 +160,14 @@ void SCTAuditingCache::MaybeEnqueueReport(
return;
}
- // Create a Reporter, which will own the report and handle sending and
- // retrying. When complete, the Reporter will call the callback which will
- // handle deleting the Reporter. The callback takes a WeakPtr in case the
- // SCTAuditingCache or Network Service were destroyed before the callback
- // triggers.
- pending_reporters_.Put(
- cache_key, std::make_unique<SCTAuditingReporter>(
- cache_key, std::move(report), *url_loader_factory_,
- report_uri_, traffic_annotation_,
- base::BindOnce(&SCTAuditingCache::OnReporterFinished,
- weak_factory_.GetWeakPtr())));
- if (pending_reporters_.size() > pending_reporters_size_hwm_)
- pending_reporters_size_hwm_ = pending_reporters_.size();
-}
-
-void SCTAuditingCache::OnReporterFinished(net::SHA256HashValue reporter_key) {
- auto it = pending_reporters_.Get(reporter_key);
- if (it != pending_reporters_.end()) {
- pending_reporters_.Erase(it);
- }
-
- if (completion_callback_for_testing_)
- std::move(completion_callback_for_testing_).Run();
-
- // TODO(crbug.com/1144205): Delete any persisted state for the reporter.
+ context->sct_auditing_handler()->AddReporter(
+ cache_key, std::move(report), *url_loader_factory_, report_uri_,
+ traffic_annotation_);
}
void SCTAuditingCache::ClearCache() {
// Empty the deduplication cache.
dedupe_cache_.Clear();
- // Delete any outstanding Reporters. This will delete any extant URLLoader
- // instances owned by the Reporters, which will cancel any outstanding
- // requests/connections. Pending (delayed) retry tasks will fast-fail when
- // they trigger as they use a WeakPtr to the Reporter instance that posted the
- // task.
- pending_reporters_.Clear();
- // TODO(crbug.com/1144205): Clear any persisted state.
}
void SCTAuditingCache::set_enabled(bool enabled) {
@@ -419,21 +175,10 @@ void SCTAuditingCache::set_enabled(bool enabled) {
SetPeriodicMetricsEnabled(enabled);
}
-void SCTAuditingCache::SetRetryDelayForTesting(
- absl::optional<base::TimeDelta> delay) {
- g_retry_delay_for_testing = delay;
-}
-
-void SCTAuditingCache::SetCompletionCallbackForTesting(
- base::OnceClosure callback) {
- completion_callback_for_testing_ = std::move(callback);
-}
-
void SCTAuditingCache::ReportHWMMetrics() {
if (!enabled_)
return;
- RecordSCTAuditingCacheHighWaterMarkMetrics(dedupe_cache_size_hwm_,
- pending_reporters_size_hwm_);
+ RecordSCTAuditingCacheHighWaterMarkMetrics(dedupe_cache_size_hwm_);
}
void SCTAuditingCache::SetPeriodicMetricsEnabled(bool enabled) {
diff --git a/chromium/services/network/sct_auditing/sct_auditing_cache.h b/chromium/services/network/sct_auditing/sct_auditing_cache.h
index 63679929e44..dac50c684a8 100644
--- a/chromium/services/network/sct_auditing/sct_auditing_cache.h
+++ b/chromium/services/network/sct_auditing/sct_auditing_cache.h
@@ -9,10 +9,9 @@
#include <vector>
#include "base/component_export.h"
-#include "base/containers/mru_cache.h"
+#include "base/containers/lru_cache.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "net/base/backoff_entry.h"
#include "net/base/hash_value.h"
#include "net/base/host_port_pair.h"
#include "net/cert/sct_auditing_delegate.h"
@@ -24,101 +23,35 @@
#include "url/gurl.h"
namespace net {
-class HttpResponseHeaders;
class X509Certificate;
}
namespace network {
-class SimpleURLLoader;
+class NetworkContext;
-// Owns an SCT auditing report and handles sending it and retrying on failures.
-// An SCTAuditingReporter begins trying to send the report to the report server
-// on creation, retrying over time based on the backoff policy defined in
-// `kBackoffPolicy`, and then runs the ReporterDoneCallback provided by the
-// SCTAuditingCache to notify the cache when it has completed (either success or
-// running out of retries). If an SCTAuditingReporter instance is deleted, any
-// outstanding requests are canceled, pending retry tasks will fail, and
-// `done_callback` will not called.
-//
-// An SCTAuditingReporter instance is uniquely identified by its `reporter_key`
-// hash, which is the SHA256HashValue of the set of SCTs included in the
-// SCTClientReport that the reporter owns.
+// SCTAuditingCache is the main entrypoint for new SCT auditing reports. 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.
//
-// Declared here for testing visibility.
-class SCTAuditingReporter {
- public:
- // Callback to notify the SCTAuditingCache that this reporter has completed.
- // The SHA256HashValue `reporter_key` is passed to uniquely identify this
- // reporter instance.
- using ReporterDoneCallback = base::OnceCallback<void(net::SHA256HashValue)>;
-
- SCTAuditingReporter(
- net::SHA256HashValue reporter_key,
- std::unique_ptr<sct_auditing::SCTClientReport> report,
- mojom::URLLoaderFactory& url_loader_factory,
- const GURL& report_uri,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
- ReporterDoneCallback done_callback);
- ~SCTAuditingReporter();
-
- SCTAuditingReporter(const SCTAuditingReporter&) = delete;
- SCTAuditingReporter& operator=(const SCTAuditingReporter&) = delete;
-
- static const net::BackoffEntry::Policy kDefaultBackoffPolicy;
-
- sct_auditing::SCTClientReport* report() { return report_.get(); }
-
- // These values are persisted to logs. Entries should not be renumbered and
- // numeric values should never be reused.
- enum class CompletionStatus {
- kSuccessFirstTry = 0,
- kSuccessAfterRetries = 1,
- kRetriesExhausted = 2,
- kMaxValue = kRetriesExhausted,
- };
-
- private:
- void ScheduleReport();
- void SendReport();
- void OnSendReportComplete(scoped_refptr<net::HttpResponseHeaders> headers);
-
- net::SHA256HashValue reporter_key_;
- std::unique_ptr<sct_auditing::SCTClientReport> report_;
- mojo::Remote<mojom::URLLoaderFactory> url_loader_factory_remote_;
- std::unique_ptr<SimpleURLLoader> url_loader_;
- net::NetworkTrafficAnnotationTag traffic_annotation_;
- GURL report_uri_;
- ReporterDoneCallback done_callback_;
-
- net::BackoffEntry::Policy backoff_policy_;
- std::unique_ptr<net::BackoffEntry> backoff_entry_;
-
- size_t num_retries_;
- size_t max_retries_;
-
- base::WeakPtrFactory<SCTAuditingReporter> weak_factory_{this};
-};
-
// 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.
//
-// The SCTAuditingCache also handles sending reports to a specified report URI
-// using a specified URLLoaderFactory (for a specific NetworkContext). These
-// are configured by the embedder via the network service's
-// ConfigureSCTAuditing() API. The actual reporting and retrying logic is
-// handled by one SCTAuditingReporter per report. Pending reporters are owned
-// by the SCTAuditingCache and tracked in the `pending_reporters_` set.
+// Once the SCTAuditingCache has selected a report to be sampled, it creates a
+// new SCTAuditingReporter and passes it to the SCTAuditingHandler for the
+// NetworkContext that triggered the report. The actual reporting and retrying
+// logic is handled by one SCTAuditingReporter per report. Pending reporters are
+// owned by the SCTAuditingHandler.
//
-// 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.
+// The SCTAuditingCache allows the embedder to configure SCT auditing via the
+// network service's ConfigureSCTAuditing() API.
class COMPONENT_EXPORT(NETWORK_SERVICE) SCTAuditingCache {
public:
- explicit SCTAuditingCache(size_t cache_size);
+ explicit SCTAuditingCache(size_t cache_size = 1024);
~SCTAuditingCache();
SCTAuditingCache(const SCTAuditingCache&) = delete;
@@ -130,6 +63,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SCTAuditingCache {
// to determine whether to send a report. This means we sample a subset of
// *certificates* rather than a subset of *connections*.
void MaybeEnqueueReport(
+ NetworkContext* context,
const net::HostPortPair& host_port_pair,
const net::X509Certificate* validated_certificate_chain,
const net::SignedCertificateTimestampAndStatusList&
@@ -149,40 +83,20 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SCTAuditingCache {
url_loader_factory_.Bind(std::move(factory));
}
- base::MRUCache<net::SHA256HashValue, bool>* GetCacheForTesting() {
+ base::LRUCache<net::SHA256HashValue, bool>* GetCacheForTesting() {
return &dedupe_cache_;
}
- base::MRUCache<net::SHA256HashValue, std::unique_ptr<SCTAuditingReporter>>*
- GetPendingReportersForTesting() {
- return &pending_reporters_;
- }
-
- void SetRetryDelayForTesting(absl::optional<base::TimeDelta> delay);
-
- void SetCompletionCallbackForTesting(base::OnceClosure callback);
-
private:
- void OnReporterFinished(net::SHA256HashValue reporter_key);
void ReportHWMMetrics();
void SetPeriodicMetricsEnabled(bool enabled);
// Value `bool` is ignored in the dedupe cache. This cache only stores
// recently seen hashes of SCTs in order to deduplicate on SCTs, and the bool
// will always be `true`.
- base::MRUCache<net::SHA256HashValue, bool> dedupe_cache_;
+ base::LRUCache<net::SHA256HashValue, bool> dedupe_cache_;
// Tracks high-water-mark of `dedupe_cache_.size()`.
- size_t dedupe_cache_size_hwm_;
-
- // The pending reporters set is an MRUCache, so that the total number of
- // pending reporters can be capped. The MRUCache means that reporters will be
- // evicted (and canceled) oldest first. If a new report is triggered for the
- // same SCTs it will get deduplicated if a previous report is still pending,
- // but the last-seen time will be updated.
- base::MRUCache<net::SHA256HashValue, std::unique_ptr<SCTAuditingReporter>>
- pending_reporters_;
- // Tracks high-water-mark of `pending_reporters_.size()`.
- size_t pending_reporters_size_hwm_;
+ size_t dedupe_cache_size_hwm_ = 0;
bool enabled_ = false;
double sampling_rate_ = 0;
@@ -190,11 +104,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SCTAuditingCache {
net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
mojo::Remote<mojom::URLLoaderFactory> url_loader_factory_;
- base::OnceClosure completion_callback_for_testing_;
-
base::RepeatingTimer histogram_timer_;
-
- base::WeakPtrFactory<SCTAuditingCache> weak_factory_{this};
};
} // namespace network
diff --git a/chromium/services/network/sct_auditing/sct_auditing_cache_unittest.cc b/chromium/services/network/sct_auditing/sct_auditing_cache_unittest.cc
index 0ae08213888..1391aab87f3 100644
--- a/chromium/services/network/sct_auditing/sct_auditing_cache_unittest.cc
+++ b/chromium/services/network/sct_auditing/sct_auditing_cache_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "services/network/sct_auditing/sct_auditing_cache.h"
-
#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/field_trial_params.h"
@@ -23,9 +22,15 @@
#include "net/test/test_data_directory.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/proto/sct_audit_report.pb.h"
+#include "services/network/sct_auditing/sct_auditing_handler.h"
+#include "services/network/sct_auditing/sct_auditing_reporter.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_factory.h"
+#include "services/network/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
@@ -37,7 +42,8 @@ namespace {
class SCTAuditingCacheTest : public testing::Test {
public:
- SCTAuditingCacheTest() {}
+ SCTAuditingCacheTest()
+ : network_service_(NetworkService::CreateForTesting()) {}
~SCTAuditingCacheTest() override = default;
SCTAuditingCacheTest(const SCTAuditingCacheTest&) = delete;
@@ -47,6 +53,22 @@ class SCTAuditingCacheTest : public testing::Test {
chain_ =
net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
ASSERT_TRUE(chain_.get());
+
+ // Set up a NetworkContext so that a working SCTAuditingHandler gets set up
+ // and the SCTAuditingCache can dispatch new reports.
+ mojo::Remote<mojom::NetworkContext> network_context_remote;
+ auto context_params = CreateNetworkContextParamsForTesting();
+
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
+ context_params->enable_sct_auditing = true;
+
+ network_context_ = std::make_unique<NetworkContext>(
+ network_service_.get(),
+ network_context_remote.BindNewPipeAndPassReceiver(),
+ std::move(context_params));
}
protected:
@@ -98,8 +120,12 @@ class SCTAuditingCacheTest : public testing::Test {
// Use MOCK_TIME so tests (particularly those involving retry and backoff) can
// use TaskEnvironment::FastForwardUntilNoTasksRemain() and FastForwardBy().
base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO,
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ std::unique_ptr<NetworkService> network_service_;
+ std::unique_ptr<NetworkContext> network_context_;
+
std::unique_ptr<TestURLLoaderFactory> url_loader_factory_;
scoped_refptr<net::X509Certificate> chain_;
@@ -165,10 +191,13 @@ TEST_F(SCTAuditingCacheTest, NoReportsCachedWhenAuditingDisabled) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature1", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
EXPECT_EQ(0u, cache.GetCacheForTesting()->size());
- EXPECT_EQ(0u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(0u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// Test that inserting and retrieving a report works.
@@ -181,10 +210,13 @@ TEST_F(SCTAuditingCacheTest, InsertAndRetrieveReport) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature1", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
EXPECT_EQ(1u, cache.GetCacheForTesting()->size());
- EXPECT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// Tests that old entries are evicted when the dedupe cache and pending
@@ -203,9 +235,12 @@ TEST_F(SCTAuditingCacheTest, EvictLRUAfterCacheFull) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature1", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair1, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
+ chain_.get(), sct_list);
ASSERT_EQ(1u, cache.GetCacheForTesting()->size());
- ASSERT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ ASSERT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
// Save the initial cache key for later inspection.
first_key = ComputeCacheKey(sct_list);
@@ -216,9 +251,12 @@ TEST_F(SCTAuditingCacheTest, EvictLRUAfterCacheFull) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature2", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair2, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
+ chain_.get(), sct_list);
ASSERT_EQ(2u, cache.GetCacheForTesting()->size());
- ASSERT_EQ(2u, cache.GetPendingReportersForTesting()->size());
+ ASSERT_EQ(2u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// Cache is now full. Add another entry to trigger eviction.
@@ -227,14 +265,15 @@ TEST_F(SCTAuditingCacheTest, EvictLRUAfterCacheFull) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature3", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair3, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair3,
+ chain_.get(), sct_list);
ASSERT_EQ(2u, cache.GetCacheForTesting()->size());
- ASSERT_EQ(2u, cache.GetPendingReportersForTesting()->size());
+ auto* pending_reporters = network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting();
+ ASSERT_EQ(3u, pending_reporters->size());
// The key for the first entry should not be in the cache anymore.
EXPECT_EQ(cache.GetCacheForTesting()->Get(first_key),
cache.GetCacheForTesting()->end());
- EXPECT_EQ(cache.GetPendingReportersForTesting()->Get(first_key),
- cache.GetPendingReportersForTesting()->end());
}
}
@@ -251,15 +290,19 @@ TEST_F(SCTAuditingCacheTest, ReportWithSameSCTsDeduplicated) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature1", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair1, chain_.get(), 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(host_port_pair2, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
+ chain_.get(), sct_list);
EXPECT_EQ(1u, cache.GetCacheForTesting()->size());
- EXPECT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// When a report gets deduplicated, the existing entry should have its last-seen
@@ -277,18 +320,21 @@ TEST_F(SCTAuditingCacheTest, DeduplicationUpdatesLastSeenTime) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature1", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list1);
- cache.MaybeEnqueueReport(host_port_pair1, chain_.get(), 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_OK, &sct_list2);
- cache.MaybeEnqueueReport(host_port_pair2, chain_.get(), 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(host_port_pair1, chain_.get(), sct_list1);
+ 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,
@@ -298,7 +344,8 @@ TEST_F(SCTAuditingCacheTest, DeduplicationUpdatesLastSeenTime) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions3", "signature3", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list3);
- cache.MaybeEnqueueReport(host_port_pair3, chain_.get(), sct_list3);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair3,
+ chain_.get(), sct_list3);
EXPECT_EQ(2u, cache.GetCacheForTesting()->size());
@@ -318,14 +365,17 @@ TEST_F(SCTAuditingCacheTest, ReportsCachedButNotSentWhenSamplingIsZero) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Check that there is one entry in the cache.
EXPECT_EQ(1u, cache.GetCacheForTesting()->size());
// Check that there are no pending reports.
EXPECT_EQ(0, url_loader_factory()->NumPending());
- EXPECT_EQ(0u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(0u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// Tests that when a new report is sampled, it will be sent to the server.
@@ -342,11 +392,14 @@ TEST_F(SCTAuditingCacheTest, ReportsSentWithServerOK) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Check that there is one pending report.
EXPECT_EQ(1, url_loader_factory()->NumPending());
- EXPECT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
// Simulate the server returning 200 OK to the report request.
url_loader_factory()->AddResponse("https://example.test",
@@ -359,7 +412,9 @@ TEST_F(SCTAuditingCacheTest, ReportsSentWithServerOK) {
EXPECT_EQ(0, url_loader_factory()->NumPending());
// Check that the pending reporter was deleted on successful completion.
- EXPECT_TRUE(cache.GetPendingReportersForTesting()->empty());
+ EXPECT_TRUE(network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->empty());
}
// Tests when the report server returns an HTTP error code.
@@ -373,7 +428,8 @@ TEST_F(SCTAuditingCacheTest, ReportSentWithServerError) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Check that there is one pending report.
EXPECT_EQ(1, url_loader_factory()->NumPending());
@@ -388,7 +444,9 @@ TEST_F(SCTAuditingCacheTest, ReportSentWithServerError) {
EXPECT_EQ(0, url_loader_factory()->NumPending());
// Without retry enabled, the pending reporter should get cleared on error.
- EXPECT_EQ(0u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(0u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// Tests that cache size high water mark metrics are correctly logged.
@@ -406,16 +464,20 @@ TEST_F(SCTAuditingCacheTest, HighWaterMarkMetrics) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions1", "signature1", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list1);
- cache.MaybeEnqueueReport(host_port_pair1, chain_.get(), 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_OK, &sct_list2);
- cache.MaybeEnqueueReport(host_port_pair2, chain_.get(), sct_list2);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
+ chain_.get(), sct_list2);
EXPECT_EQ(2u, cache.GetCacheForTesting()->size());
- EXPECT_EQ(2u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(2u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
// High-water-mark metrics are recorded once an hour.
task_environment_.FastForwardBy(base::Hours(1));
@@ -442,10 +504,12 @@ TEST_F(SCTAuditingCacheTest, ReportSizeMetrics) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Get the size of the pending report and test that it is correctly logged.
- size_t report_size = cache.GetPendingReportersForTesting()
+ size_t report_size = network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
->begin()
->second->report()
->ByteSizeLong();
@@ -454,7 +518,8 @@ TEST_F(SCTAuditingCacheTest, ReportSizeMetrics) {
report_size, 1);
// Retry enqueueing the same report which will be deduplicated.
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
histograms.ExpectTotalCount("Security.SCTAuditing.OptIn.ReportSampled", 1);
histograms.ExpectTotalCount("Security.SCTAuditing.OptIn.ReportSize", 1);
@@ -476,7 +541,8 @@ TEST_F(SCTAuditingCacheTest, ReportSampleDroppedMetrics) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
histograms.ExpectUniqueSample("Security.SCTAuditing.OptIn.ReportSampled",
false, 1);
@@ -496,10 +562,13 @@ TEST_F(SCTAuditingCacheTest, ReportNotGeneratedIfNoValidSCTs) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_INVALID_SIGNATURE, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
EXPECT_EQ(0u, cache.GetCacheForTesting()->size());
- EXPECT_EQ(0u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(0u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
}
// Connections that have a mix of valid and invalid SCTs should only include the
@@ -521,12 +590,15 @@ TEST_F(SCTAuditingCacheTest, ReportsOnlyIncludesValidSCTs) {
net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
"extensions3", "invalid_log", base::Time::Now(),
net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
- ASSERT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ auto* pending_reporters =
+ network_context_->sct_auditing_handler()->GetPendingReportersForTesting();
+ ASSERT_EQ(1u, pending_reporters->size());
// No invalid SCTs should be in any of the pending reports.
- for (const auto& reporter : *cache.GetPendingReportersForTesting()) {
+ for (const auto& reporter : *pending_reporters) {
for (auto& sct_and_status :
reporter.second->report()->certificate_report(0).included_sct()) {
// Decode the SCT and check that only the valid SCT was included.
@@ -557,10 +629,13 @@ TEST_F(SCTAuditingCacheTest, ReportSucceedsOnSecondTry) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Check that there is one pending report.
- EXPECT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
// Wait for initial request.
WaitForRequests(1u);
@@ -574,7 +649,9 @@ TEST_F(SCTAuditingCacheTest, ReportSucceedsOnSecondTry) {
EXPECT_EQ(0, url_loader_factory()->NumPending());
// With retry enabled, the pending reporter should remain on failure.
- EXPECT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
// Simulate the server returning 200 OK to the report request. The request is
// not yet pending, so set the "default" response. Then when
@@ -591,7 +668,9 @@ TEST_F(SCTAuditingCacheTest, ReportSucceedsOnSecondTry) {
EXPECT_EQ(0, url_loader_factory()->NumPending());
// Check that the pending reporter was deleted on successful completion.
- EXPECT_TRUE(cache.GetPendingReportersForTesting()->empty());
+ EXPECT_TRUE(network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->empty());
histograms.ExpectUniqueSample(
"Security.SCTAuditing.OptIn.ReportCompletionStatus",
@@ -615,10 +694,13 @@ TEST_F(SCTAuditingCacheTest, ExhaustAllRetriesShouldDeleteReporter) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Check that there is one pending reporter.
- EXPECT_EQ(1u, cache.GetPendingReportersForTesting()->size());
+ EXPECT_EQ(1u, network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->size());
// Simulate the server returning 429 TOO MANY REQUEST to every request
url_loader_factory()->AddResponse("https://example.test",
@@ -629,7 +711,9 @@ TEST_F(SCTAuditingCacheTest, ExhaustAllRetriesShouldDeleteReporter) {
WaitForRequests(16u);
// The reporter should be deleted when it runs out of retries.
- EXPECT_TRUE(cache.GetPendingReportersForTesting()->empty());
+ EXPECT_TRUE(network_context_->sct_auditing_handler()
+ ->GetPendingReportersForTesting()
+ ->empty());
// The Reporter should send 16 requests: 1 initial attempt, and 15 retries
// (the default max_retries for SCTAuditingReporter).
@@ -658,7 +742,8 @@ TEST_F(SCTAuditingCacheTest, RetriesEnabledSucceedFirstTryMetrics) {
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
"extensions", "signature", base::Time::Now(),
net::ct::SCT_STATUS_OK, &sct_list);
- cache.MaybeEnqueueReport(host_port_pair, chain_.get(), sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
// Wait for the initial request to be pending.
WaitForRequests(1u);
diff --git a/chromium/services/network/sct_auditing/sct_auditing_handler.cc b/chromium/services/network/sct_auditing/sct_auditing_handler.cc
new file mode 100644
index 00000000000..673b5ccc7f7
--- /dev/null
+++ b/chromium/services/network/sct_auditing/sct_auditing_handler.cc
@@ -0,0 +1,87 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/sct_auditing/sct_auditing_handler.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
+#include "net/base/hash_value.h"
+#include "services/network/public/proto/sct_audit_report.pb.h"
+#include "services/network/sct_auditing/sct_auditing_reporter.h"
+
+namespace network {
+
+SCTAuditingHandler::SCTAuditingHandler(size_t cache_size)
+ : pending_reporters_(cache_size) {}
+
+SCTAuditingHandler::~SCTAuditingHandler() = default;
+
+void SCTAuditingHandler::AddReporter(
+ net::SHA256HashValue reporter_key,
+ std::unique_ptr<sct_auditing::SCTClientReport> report,
+ mojom::URLLoaderFactory& url_loader_factory,
+ const GURL& report_uri,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
+ if (!enabled_) {
+ return;
+ }
+
+ auto reporter = std::make_unique<SCTAuditingReporter>(
+ reporter_key, std::move(report), url_loader_factory, report_uri,
+ traffic_annotation,
+ base::BindOnce(&SCTAuditingHandler::OnReporterFinished, GetWeakPtr()));
+ reporter->Start();
+ pending_reporters_.Put(reporter->key(), std::move(reporter));
+
+ if (pending_reporters_.size() > pending_reporters_size_hwm_)
+ pending_reporters_size_hwm_ = pending_reporters_.size();
+}
+
+void SCTAuditingHandler::ClearPendingReports() {
+ // Delete any outstanding Reporters. This will delete any extant URLLoader
+ // instances owned by the Reporters, which will cancel any outstanding
+ // requests/connections. Pending (delayed) retry tasks will fast-fail when
+ // they trigger as they use a WeakPtr to the Reporter instance that posted the
+ // task.
+ pending_reporters_.Clear();
+ // TODO(crbug.com/1144205): Clear any persisted state.
+}
+
+void SCTAuditingHandler::SetEnabled(bool enabled) {
+ enabled_ = enabled;
+
+ // High-water-mark metrics get logged hourly (rather than once-per-session at
+ // shutdown, as Network Service shutdown is not consistent and non-browser
+ // processes can fail to report metrics during shutdown). The timer should
+ // only be running if SCT auditing is enabled.
+ if (enabled) {
+ histogram_timer_.Start(FROM_HERE, base::Hours(1), this,
+ &SCTAuditingHandler::ReportHWMMetrics);
+ } else {
+ histogram_timer_.Stop();
+ ClearPendingReports();
+ }
+}
+
+base::WeakPtr<SCTAuditingHandler> SCTAuditingHandler::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+void SCTAuditingHandler::OnReporterFinished(net::SHA256HashValue reporter_key) {
+ auto it = pending_reporters_.Get(reporter_key);
+ if (it != pending_reporters_.end()) {
+ pending_reporters_.Erase(it);
+ }
+ // TODO(crbug.com/1144205): Delete any persisted state for the reporter.
+}
+
+void SCTAuditingHandler::ReportHWMMetrics() {
+ if (!enabled_) {
+ return;
+ }
+ base::UmaHistogramCounts1000("Security.SCTAuditing.OptIn.ReportersHWM",
+ pending_reporters_size_hwm_);
+}
+
+} // namespace network
diff --git a/chromium/services/network/sct_auditing/sct_auditing_handler.h b/chromium/services/network/sct_auditing/sct_auditing_handler.h
new file mode 100644
index 00000000000..e10280b1a2e
--- /dev/null
+++ b/chromium/services/network/sct_auditing/sct_auditing_handler.h
@@ -0,0 +1,81 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_SCT_AUDITING_SCT_AUDITING_HANDLER_H_
+#define SERVICES_NETWORK_SCT_AUDITING_SCT_AUDITING_HANDLER_H_
+
+#include <memory>
+
+#include "base/containers/lru_cache.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "net/base/hash_value.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "url/gurl.h"
+
+namespace sct_auditing {
+class SCTClientReport;
+} // namespace sct_auditing
+
+namespace network {
+
+class SCTAuditingReporter;
+
+// SCTAuditingHandler owns SCT auditing reports for a specific NetworkContext.
+// Each SCTAuditingHandler is owned by its matching NetworkContext.
+class SCTAuditingHandler {
+ public:
+ explicit SCTAuditingHandler(size_t cache_size = 1024);
+ ~SCTAuditingHandler();
+
+ SCTAuditingHandler(const SCTAuditingHandler&) = delete;
+ SCTAuditingHandler& operator=(const SCTAuditingHandler&) = delete;
+
+ // Creates a new SCTAuditingReporter for the report and adds it to this
+ // SCTAuditingHandler's pending reporters set. After creating the reporter,
+ // this will call SCTAuditingReporter::Start() to initiate sending the report.
+ void AddReporter(
+ net::SHA256HashValue,
+ std::unique_ptr<sct_auditing::SCTClientReport> report,
+ mojom::URLLoaderFactory& url_loader_factory,
+ const GURL& report_uri,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
+
+ // Clears the set of pending reporters for this SCTAuditingHandler.
+ void ClearPendingReports();
+
+ base::LRUCache<net::SHA256HashValue, std::unique_ptr<SCTAuditingReporter>>*
+ GetPendingReportersForTesting() {
+ return &pending_reporters_;
+ }
+
+ void SetEnabled(bool enabled);
+ bool is_enabled() { return enabled_; }
+
+ base::WeakPtr<SCTAuditingHandler> GetWeakPtr();
+
+ private:
+ void OnReporterFinished(net::SHA256HashValue reporter_key);
+ void ReportHWMMetrics();
+
+ // The pending reporters set is an LRUCache, so that the total number of
+ // pending reporters can be capped. The LRUCache means that reporters will be
+ // evicted (and canceled) oldest first. If a new report is triggered for the
+ // same SCTs it will get deduplicated if a previous report is still pending,
+ // but the last-seen time will be updated.
+ base::LRUCache<net::SHA256HashValue, std::unique_ptr<SCTAuditingReporter>>
+ pending_reporters_;
+ // Tracks high-water-mark of `pending_reporters_.size()`.
+ size_t pending_reporters_size_hwm_ = 0;
+
+ bool enabled_ = false;
+ base::RepeatingTimer histogram_timer_;
+
+ base::WeakPtrFactory<SCTAuditingHandler> weak_factory_{this};
+};
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_SCT_AUDITING_SCT_AUDITING_HANDLER_H_
diff --git a/chromium/services/network/sct_auditing/sct_auditing_reporter.cc b/chromium/services/network/sct_auditing/sct_auditing_reporter.cc
new file mode 100644
index 00000000000..4c448bc3e2c
--- /dev/null
+++ b/chromium/services/network/sct_auditing/sct_auditing_reporter.cc
@@ -0,0 +1,231 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/sct_auditing/sct_auditing_reporter.h"
+
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_functions.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace network {
+
+namespace {
+
+constexpr int kSendSCTReportTimeoutSeconds = 30;
+
+// Overrides the initial retry delay in SCTAuditingReporter::kBackoffPolicy if
+// not nullopt.
+absl::optional<base::TimeDelta> g_retry_delay_for_testing = absl::nullopt;
+
+// Records whether sending the report to the reporting server succeeded for each
+// report sent.
+void RecordSCTAuditingReportSucceededMetrics(bool success) {
+ base::UmaHistogramBoolean("Security.SCTAuditing.OptIn.ReportSucceeded",
+ success);
+}
+
+// Records whether a report succeeded/failed with retries.
+void ReportSCTAuditingCompletionStatusMetrics(
+ SCTAuditingReporter::CompletionStatus status) {
+ base::UmaHistogramEnumeration(
+ "Security.SCTAuditing.OptIn.ReportCompletionStatus", status);
+}
+
+} // namespace
+
+// static
+const net::BackoffEntry::Policy SCTAuditingReporter::kDefaultBackoffPolicy = {
+ // Don't ignore initial errors; begin exponential back-off rules immediately
+ // if the first attempt fails.
+ .num_errors_to_ignore = 0,
+ // Start with a 30s delay, including for the first attempt (due to setting
+ // `always_use_initial_delay = true` below).
+ .initial_delay_ms = 30 * 1000,
+ // Double the backoff delay each retry.
+ .multiply_factor = 2.0,
+ // Spread requests randomly between 80-100% of the calculated backoff time.
+ .jitter_factor = 0.2,
+ // Max retry delay is 1 day.
+ .maximum_backoff_ms = 24 * 60 * 60 * 1000,
+ // Never discard the entry.
+ .entry_lifetime_ms = -1,
+ // Initial attempt will be delayed (and jittered). This reduces the risk of
+ // a "thundering herd" of reports on startup if a user has many reports
+ // persisted (once pending reports are persisted and recreated at startup
+ // with a new BackoffEntry).
+ .always_use_initial_delay = true,
+};
+
+// How many times an SCTAuditingReporter should retry sending an audit report.
+// Given kDefaultBackoffPolicy above and 15 total retries, this means there will
+// be five attempts in the first 30 minutes and then occasional retries for
+// roughly the next five days.
+// See more discussion in the SCT Auditing Retry and Persistence design doc:
+// https://docs.google.com/document/d/1YTUzoG6BDF1QIxosaQDp2H5IzYY7_fwH8qNJXSVX8OQ/edit
+constexpr size_t kMaxRetries = 15;
+
+SCTAuditingReporter::SCTAuditingReporter(
+ net::SHA256HashValue reporter_key,
+ std::unique_ptr<sct_auditing::SCTClientReport> report,
+ mojom::URLLoaderFactory& url_loader_factory,
+ const GURL& report_uri,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+ ReporterDoneCallback done_callback)
+ : reporter_key_(reporter_key),
+ report_(std::move(report)),
+ traffic_annotation_(traffic_annotation),
+ report_uri_(report_uri),
+ done_callback_(std::move(done_callback)),
+ num_retries_(0),
+ max_retries_(kMaxRetries) {
+ // Clone the URLLoaderFactory to avoid any dependencies on its lifetime. The
+ // Reporter instance can maintain its own copy.
+ // Relatively few Reporters are expected to exist at a time (due to sampling
+ // and deduplication), so some cost of copying is reasonable. If more
+ // optimization is needed, this could potentially use a mojo::SharedRemote
+ // or a WrappedPendingSharedURLLoaderFactory instead.
+ url_loader_factory.Clone(
+ url_loader_factory_remote_.BindNewPipeAndPassReceiver());
+
+ // Override the retry delay if set by tests.
+ backoff_policy_ = kDefaultBackoffPolicy;
+ if (g_retry_delay_for_testing) {
+ backoff_policy_.initial_delay_ms =
+ g_retry_delay_for_testing->InMilliseconds();
+ }
+ backoff_entry_ = std::make_unique<net::BackoffEntry>(&backoff_policy_);
+}
+
+SCTAuditingReporter::~SCTAuditingReporter() = default;
+
+void SCTAuditingReporter::Start() {
+ // Informing the backoff entry of a success will force it to use the initial
+ // delay (and jitter) for the first attempt. Otherwise, ShouldRejectRequest()
+ // will return `true` despite the policy specifying
+ // `always_use_initial_delay = true`.
+ backoff_entry_->InformOfRequest(true);
+
+ // Start sending the report.
+ ScheduleReport();
+}
+
+void SCTAuditingReporter::SetRetryDelayForTesting(
+ absl::optional<base::TimeDelta> delay) {
+ g_retry_delay_for_testing = delay;
+}
+
+void SCTAuditingReporter::ScheduleReport() {
+ if (base::FeatureList::IsEnabled(
+ features::kSCTAuditingRetryAndPersistReports) &&
+ backoff_entry_->ShouldRejectRequest()) {
+ // TODO(crbug.com/1199827): Investigate if explicit task traits should be
+ // used for these tasks (e.g., BEST_EFFORT and SKIP_ON_SHUTDOWN).
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&SCTAuditingReporter::SendReport,
+ weak_factory_.GetWeakPtr()),
+ backoff_entry_->GetTimeUntilRelease());
+ } else {
+ SendReport();
+ }
+}
+
+void SCTAuditingReporter::SendReport() {
+ DCHECK(url_loader_factory_remote_);
+
+ // Create a SimpleURLLoader for the request.
+ auto report_request = std::make_unique<ResourceRequest>();
+ report_request->url = report_uri_;
+ report_request->method = "POST";
+ report_request->load_flags = net::LOAD_DISABLE_CACHE;
+ report_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+
+ url_loader_ = SimpleURLLoader::Create(
+ std::move(report_request),
+ static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation_));
+ url_loader_->SetTimeoutDuration(base::Seconds(kSendSCTReportTimeoutSeconds));
+ // Retry is handled by SCTAuditingReporter.
+ url_loader_->SetRetryOptions(0, SimpleURLLoader::RETRY_NEVER);
+
+ // Serialize the report and attach it to the loader.
+ // TODO(crbug.com/1199566): Should we store the serialized report instead, so
+ // we don't serialize on every retry?
+ std::string report_data;
+ bool ok = report_->SerializeToString(&report_data);
+ DCHECK(ok);
+ url_loader_->AttachStringForUpload(report_data, "application/octet-stream");
+
+ // The server acknowledges receiving the report via a successful HTTP status
+ // with no response body, so this uses DownloadHeadersOnly for simplicity.
+ // If the loader is destroyed, the callback will be canceled, so using
+ // base::Unretained here is safe.
+ url_loader_->DownloadHeadersOnly(
+ url_loader_factory_remote_.get(),
+ base::BindOnce(&SCTAuditingReporter::OnSendReportComplete,
+ base::Unretained(this)));
+}
+
+void SCTAuditingReporter::OnSendReportComplete(
+ scoped_refptr<net::HttpResponseHeaders> headers) {
+ int response_code = 0;
+ if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) {
+ response_code = url_loader_->ResponseInfo()->headers->response_code();
+ }
+ bool success =
+ url_loader_->NetError() == net::OK && response_code == net::HTTP_OK;
+
+ RecordSCTAuditingReportSucceededMetrics(success);
+
+ if (base::FeatureList::IsEnabled(
+ features::kSCTAuditingRetryAndPersistReports)) {
+ if (success) {
+ // Report succeeded.
+ if (num_retries_ == 0) {
+ ReportSCTAuditingCompletionStatusMetrics(
+ CompletionStatus::kSuccessFirstTry);
+ } else {
+ ReportSCTAuditingCompletionStatusMetrics(
+ CompletionStatus::kSuccessAfterRetries);
+ }
+
+ // Notify the Cache that this Reporter is done. This will delete |this|,
+ // so do not add code after this point.
+ std::move(done_callback_).Run(reporter_key_);
+ return;
+ }
+ // Sending the report failed.
+ if (num_retries_ >= max_retries_) {
+ // Retry limit reached.
+ ReportSCTAuditingCompletionStatusMetrics(
+ CompletionStatus::kRetriesExhausted);
+
+ // Notify the Cache that this Reporter is done. This will delete |this|,
+ // so do not add code after this point.
+ std::move(done_callback_).Run(reporter_key_);
+ return;
+ } else {
+ // Schedule a retry.
+ ++num_retries_;
+ backoff_entry_->InformOfRequest(false);
+ ScheduleReport();
+ }
+ } else {
+ // Retry is not enabled, so just notify the Cache that this Reporter is
+ // done. This will delete |this|, so do not add code after this point.
+ std::move(done_callback_).Run(reporter_key_);
+ return;
+ }
+}
+
+} // namespace network
diff --git a/chromium/services/network/sct_auditing/sct_auditing_reporter.h b/chromium/services/network/sct_auditing/sct_auditing_reporter.h
new file mode 100644
index 00000000000..06f5bc41945
--- /dev/null
+++ b/chromium/services/network/sct_auditing/sct_auditing_reporter.h
@@ -0,0 +1,103 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_SCT_AUDITING_SCT_AUDITING_REPORTER_H_
+#define SERVICES_NETWORK_SCT_AUDITING_SCT_AUDITING_REPORTER_H_
+
+#include <memory>
+
+#include "base/component_export.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/backoff_entry.h"
+#include "net/base/hash_value.h"
+#include "net/cert/signed_certificate_timestamp_and_status.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/proto/sct_audit_report.pb.h"
+#include "url/gurl.h"
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace network {
+
+class SimpleURLLoader;
+
+// Owns an SCT auditing report and handles sending it and retrying on failures.
+// An SCTAuditingReporter begins trying to send the report to the report server
+// on creation, retrying over time based on the backoff policy defined in
+// `kBackoffPolicy`, and then runs the ReporterDoneCallback provided by the
+// SCTAuditingHandler to notify the handler when it has completed (either
+// success or running out of retries). If an SCTAuditingReporter instance is
+// deleted, any outstanding requests are canceled, pending retry tasks will
+// fail, and `done_callback` will not called.
+//
+// An SCTAuditingReporter instance is uniquely identified by its `reporter_key`
+// hash, which is the SHA256HashValue of the set of SCTs included in the
+// SCTClientReport that the reporter owns.
+class COMPONENT_EXPORT(NETWORK_SERVICE) SCTAuditingReporter {
+ public:
+ // Callback to notify the SCTAuditingHandler that this reporter has completed.
+ // The SHA256HashValue `reporter_key` is passed to uniquely identify this
+ // reporter instance.
+ using ReporterDoneCallback = base::OnceCallback<void(net::SHA256HashValue)>;
+
+ SCTAuditingReporter(
+ net::SHA256HashValue reporter_key,
+ std::unique_ptr<sct_auditing::SCTClientReport> report,
+ mojom::URLLoaderFactory& url_loader_factory,
+ const GURL& report_uri,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+ ReporterDoneCallback done_callback);
+ ~SCTAuditingReporter();
+
+ SCTAuditingReporter(const SCTAuditingReporter&) = delete;
+ SCTAuditingReporter& operator=(const SCTAuditingReporter&) = delete;
+
+ static const net::BackoffEntry::Policy kDefaultBackoffPolicy;
+
+ void Start();
+
+ net::SHA256HashValue key() { return reporter_key_; }
+ sct_auditing::SCTClientReport* report() { return report_.get(); }
+
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class CompletionStatus {
+ kSuccessFirstTry = 0,
+ kSuccessAfterRetries = 1,
+ kRetriesExhausted = 2,
+ kMaxValue = kRetriesExhausted,
+ };
+
+ static void SetRetryDelayForTesting(absl::optional<base::TimeDelta> delay);
+
+ private:
+ void ScheduleReport();
+ void SendReport();
+ void OnSendReportComplete(scoped_refptr<net::HttpResponseHeaders> headers);
+
+ net::SHA256HashValue reporter_key_;
+ std::unique_ptr<sct_auditing::SCTClientReport> report_;
+ mojo::Remote<mojom::URLLoaderFactory> url_loader_factory_remote_;
+ std::unique_ptr<SimpleURLLoader> url_loader_;
+ net::NetworkTrafficAnnotationTag traffic_annotation_;
+ GURL report_uri_;
+ ReporterDoneCallback done_callback_;
+
+ net::BackoffEntry::Policy backoff_policy_;
+ std::unique_ptr<net::BackoffEntry> backoff_entry_;
+
+ size_t num_retries_;
+ size_t max_retries_;
+
+ base::WeakPtrFactory<SCTAuditingReporter> weak_factory_{this};
+};
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_SCT_AUDITING_SCT_AUDITING_REPORTER_H_
diff --git a/chromium/services/network/session_cleanup_cookie_store.cc b/chromium/services/network/session_cleanup_cookie_store.cc
index 52f86cccee8..a876da004f5 100644
--- a/chromium/services/network/session_cleanup_cookie_store.cc
+++ b/chromium/services/network/session_cleanup_cookie_store.cc
@@ -12,8 +12,8 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/values.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
@@ -31,10 +31,10 @@ base::Value CookieStoreOriginFiltered(const std::string& origin,
net::NetLogCaptureMode capture_mode) {
if (!net::NetLogCaptureIncludesSensitive(capture_mode))
return base::Value();
- base::DictionaryValue dict;
- dict.SetString("origin", origin);
- dict.SetBoolean("is_https", is_https);
- return std::move(dict);
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey("origin", origin);
+ dict.SetBoolKey("is_https", is_https);
+ return dict;
}
} // namespace
diff --git a/chromium/services/network/session_cleanup_cookie_store.h b/chromium/services/network/session_cleanup_cookie_store.h
index 46c6a84dc3b..ec56aeca174 100644
--- a/chromium/services/network/session_cleanup_cookie_store.h
+++ b/chromium/services/network/session_cleanup_cookie_store.h
@@ -13,7 +13,6 @@
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/cookies/cookie_monster.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
@@ -40,6 +39,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SessionCleanupCookieStore
explicit SessionCleanupCookieStore(
const scoped_refptr<net::SQLitePersistentCookieStore>& cookie_store);
+ SessionCleanupCookieStore(const SessionCleanupCookieStore&) = delete;
+ SessionCleanupCookieStore& operator=(const SessionCleanupCookieStore&) =
+ delete;
+
// net::CookieMonster::PersistentCookieStore:
void Load(LoadedCallback loaded_callback,
const net::NetLogWithSource& net_log) override;
@@ -76,8 +79,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SessionCleanupCookieStore
bool force_keep_session_state_ = false;
net::NetLogWithSource net_log_;
-
- DISALLOW_COPY_AND_ASSIGN(SessionCleanupCookieStore);
};
} // namespace network
diff --git a/chromium/services/network/session_cleanup_cookie_store_unittest.cc b/chromium/services/network/session_cleanup_cookie_store_unittest.cc
index b8db2a48117..b28c8fa067c 100644
--- a/chromium/services/network/session_cleanup_cookie_store_unittest.cc
+++ b/chromium/services/network/session_cleanup_cookie_store_unittest.cc
@@ -9,8 +9,8 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/task_environment.h"
@@ -46,7 +46,7 @@ class SessionCleanupCookieStoreTest : public testing::Test {
CanonicalCookieVector cookies;
store_->Load(base::BindOnce(&SessionCleanupCookieStoreTest::OnLoaded,
base::Unretained(this), &run_loop, &cookies),
- net_log_.bound());
+ net::NetLogWithSource::Make(net::NetLogSourceType::NONE));
run_loop.Run();
return cookies;
}
@@ -89,7 +89,7 @@ class SessionCleanupCookieStoreTest : public testing::Test {
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
base::ScopedTempDir temp_dir_;
scoped_refptr<SessionCleanupCookieStore> store_;
- net::RecordingBoundTestNetLog net_log_;
+ net::RecordingNetLogObserver net_log_observer_;
};
TEST_F(SessionCleanupCookieStoreTest, TestPersistence) {
@@ -144,7 +144,7 @@ TEST_F(SessionCleanupCookieStoreTest, TestNetLogIncludeCookies) {
}));
DestroyStore();
- auto entries = net_log_.GetEntries();
+ auto entries = net_log_observer_.GetEntries();
size_t pos = net::ExpectLogContainsSomewhere(
entries, 0, net::NetLogEventType::COOKIE_PERSISTENT_STORE_ORIGIN_FILTERED,
net::NetLogEventPhase::NONE);
@@ -163,7 +163,7 @@ TEST_F(SessionCleanupCookieStoreTest, TestNetLogDoNotIncludeCookies) {
base::Time t = base::Time::Now();
AddCookie("A", "B", "nonpersistent.com", "/", t);
- net_log_.SetObserverCaptureMode(net::NetLogCaptureMode::kDefault);
+ net_log_observer_.SetObserverCaptureMode(net::NetLogCaptureMode::kDefault);
// Cookies from "nonpersistent.com" should be deleted.
store_->DeleteSessionCookies(
base::BindRepeating([](const std::string& domain, bool is_https) {
@@ -171,7 +171,7 @@ TEST_F(SessionCleanupCookieStoreTest, TestNetLogDoNotIncludeCookies) {
}));
DestroyStore();
- auto entries = net_log_.GetEntries();
+ auto entries = net_log_observer_.GetEntries();
size_t pos = net::ExpectLogContainsSomewhere(
entries, 0, net::NetLogEventType::COOKIE_PERSISTENT_STORE_ORIGIN_FILTERED,
net::NetLogEventPhase::NONE);
diff --git a/chromium/services/network/socket_data_pump.h b/chromium/services/network/socket_data_pump.h
index 61b8c1ad8fc..1cef9cbe786 100644
--- a/chromium/services/network/socket_data_pump.h
+++ b/chromium/services/network/socket_data_pump.h
@@ -6,7 +6,7 @@
#define SERVICES_NETWORK_SOCKET_DATA_PUMP_H_
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -84,8 +84,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SocketDataPump {
void OnNetworkWriteCompleted(int result);
void ShutdownSend();
- net::StreamSocket* const socket_;
- Delegate* const delegate_;
+ const raw_ptr<net::StreamSocket> socket_;
+ const raw_ptr<Delegate> delegate_;
// The *stream handles will be null when there's a pending read from |socket_|
// to |pending_receive_buffer_|, or while there is a pending write from
diff --git a/chromium/services/network/socket_data_pump_unittest.cc b/chromium/services/network/socket_data_pump_unittest.cc
index 3f5b0dddef6..74f90797fbd 100644
--- a/chromium/services/network/socket_data_pump_unittest.cc
+++ b/chromium/services/network/socket_data_pump_unittest.cc
@@ -9,7 +9,6 @@
#include "base/callback_helpers.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/system/simple_watcher.h"
diff --git a/chromium/services/network/socket_factory.h b/chromium/services/network/socket_factory.h
index 6edd06823ab..eebbff63539 100644
--- a/chromium/services/network/socket_factory.h
+++ b/chromium/services/network/socket_factory.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_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"
@@ -99,9 +99,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SocketFactory
std::unique_ptr<TCPConnectedSocket> socket,
mojo::PendingReceiver<mojom::TCPConnectedSocket> receiver) override;
- net::NetLog* const net_log_;
+ const raw_ptr<net::NetLog> net_log_;
- net::ClientSocketFactory* client_socket_factory_;
+ raw_ptr<net::ClientSocketFactory> client_socket_factory_;
TLSSocketFactory tls_socket_factory_;
mojo::UniqueReceiverSet<mojom::UDPSocket> udp_socket_receivers_;
mojo::UniqueReceiverSet<mojom::TCPServerSocket> tcp_server_socket_receivers_;
diff --git a/chromium/services/network/ssl_config_service_mojo.h b/chromium/services/network/ssl_config_service_mojo.h
index 32b86ae3492..150ce5cedc5 100644
--- a/chromium/services/network/ssl_config_service_mojo.h
+++ b/chromium/services/network/ssl_config_service_mojo.h
@@ -6,6 +6,7 @@
#define SERVICES_NETWORK_SSL_CONFIG_SERVICE_MOJO_H_
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/cert/cert_verifier.h"
@@ -58,8 +59,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SSLConfigServiceMojo
net::SSLContextConfig ssl_context_config_;
net::CertVerifier::Config cert_verifier_config_;
- net::CertVerifier* cert_verifier_;
- CRLSetDistributor* crl_set_distributor_;
+ raw_ptr<net::CertVerifier> cert_verifier_;
+ raw_ptr<CRLSetDistributor> crl_set_distributor_;
// The list of domains and subdomains from enterprise policy where connection
// coalescing is allowed when client certs are in use if the hosts being
diff --git a/chromium/services/network/ssl_config_service_mojo_unittest.cc b/chromium/services/network/ssl_config_service_mojo_unittest.cc
index 356cd677796..848124f1c08 100644
--- a/chromium/services/network/ssl_config_service_mojo_unittest.cc
+++ b/chromium/services/network/ssl_config_service_mojo_unittest.cc
@@ -7,6 +7,7 @@
#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
@@ -86,7 +87,7 @@ class TestSSLConfigServiceObserver : public net::SSLConfigService::Observer {
int observed_changes() const { return observed_changes_; }
private:
- net::SSLConfigService* const ssl_config_service_;
+ const raw_ptr<net::SSLConfigService> ssl_config_service_;
int observed_changes_ = 0;
int changes_to_wait_for_ = 0;
net::SSLContextConfig ssl_context_config_during_change_;
diff --git a/chromium/services/network/ssl_config_type_converter.cc b/chromium/services/network/ssl_config_type_converter.cc
index c67df7e64ba..286559ac3fd 100644
--- a/chromium/services/network/ssl_config_type_converter.cc
+++ b/chromium/services/network/ssl_config_type_converter.cc
@@ -30,15 +30,12 @@ net::SSLContextConfig MojoSSLConfigToSSLContextConfig(
net_config.version_min =
MojoSSLVersionToNetSSLVersion(mojo_config->version_min);
- net_config.version_min_warn =
- MojoSSLVersionToNetSSLVersion(mojo_config->version_min_warn);
net_config.version_max =
MojoSSLVersionToNetSSLVersion(mojo_config->version_max);
DCHECK_LE(net_config.version_min, net_config.version_max);
net_config.disabled_cipher_suites = mojo_config->disabled_cipher_suites;
net_config.cecpq2_enabled = mojo_config->cecpq2_enabled;
- net_config.triple_des_enabled = mojo_config->triple_des_enabled;
return net_config;
}
diff --git a/chromium/services/network/tcp_bound_socket.h b/chromium/services/network/tcp_bound_socket.h
index a9f73cdd455..54a01f9b186 100644
--- a/chromium/services/network/tcp_bound_socket.h
+++ b/chromium/services/network/tcp_bound_socket.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -76,7 +76,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) TCPBoundSocket
net::IPEndPoint bind_address_;
mojo::ReceiverId receiver_id_ = -1;
- SocketFactory* const socket_factory_;
+ const raw_ptr<SocketFactory> socket_factory_;
std::unique_ptr<net::TCPSocket> socket_;
const net::NetworkTrafficAnnotationTag traffic_annotation_;
diff --git a/chromium/services/network/tcp_connected_socket.h b/chromium/services/network/tcp_connected_socket.h
index c05b6bbc02f..deba4436227 100644
--- a/chromium/services/network/tcp_connected_socket.h
+++ b/chromium/services/network/tcp_connected_socket.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -108,9 +108,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) TCPConnectedSocket
const mojo::Remote<mojom::SocketObserver> observer_;
- net::NetLog* const net_log_;
- net::ClientSocketFactory* const client_socket_factory_;
- TLSSocketFactory* tls_socket_factory_;
+ const raw_ptr<net::NetLog> net_log_;
+ const raw_ptr<net::ClientSocketFactory> client_socket_factory_;
+ raw_ptr<TLSSocketFactory> tls_socket_factory_;
std::unique_ptr<net::TransportClientSocket> socket_;
diff --git a/chromium/services/network/tcp_server_socket.h b/chromium/services/network/tcp_server_socket.h
index 5d5976ac755..6fdaf59ee95 100644
--- a/chromium/services/network/tcp_server_socket.h
+++ b/chromium/services/network/tcp_server_socket.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -86,7 +86,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) TCPServerSocket
// Process the next Accept() from |pending_accepts_queue_|.
void ProcessNextAccept();
- Delegate* const delegate_;
+ const raw_ptr<Delegate> delegate_;
std::unique_ptr<net::ServerSocket> socket_;
int backlog_;
std::vector<std::unique_ptr<PendingAccept>> pending_accepts_queue_;
diff --git a/chromium/services/network/tcp_socket_unittest.cc b/chromium/services/network/tcp_socket_unittest.cc
index 47e9194040d..15b587244d7 100644
--- a/chromium/services/network/tcp_socket_unittest.cc
+++ b/chromium/services/network/tcp_socket_unittest.cc
@@ -11,7 +11,7 @@
#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/location.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -120,7 +120,7 @@ class MockServerSocket : public net::ServerSocket {
net::IoMode mode_ = net::SYNCHRONOUS;
int accept_result_ = net::OK;
net::CompletionOnceCallback accept_callback_;
- std::unique_ptr<net::StreamSocket>* accept_socket_;
+ raw_ptr<std::unique_ptr<net::StreamSocket>> accept_socket_;
base::RunLoop run_loop_;
std::vector<std::unique_ptr<net::StaticSocketDataProvider>> data_providers_;
size_t next_data_provider_index_ = 0;
@@ -583,11 +583,8 @@ TEST_F(TCPSocketTest, SocketClosed) {
// 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.
- // This behavior is known to exist as late as 10.12. Whether it exists after
- // that is unknown.
// See https://crbug.com/1034991
- if (base::mac::IsAtMostOS10_12())
- result_ok |= result == net::ERR_FAILED;
+ result_ok |= result == net::ERR_FAILED;
#endif
EXPECT_TRUE(result_ok) << "actual result: " << result;
}
diff --git a/chromium/services/network/test_chunked_data_pipe_getter.h b/chromium/services/network/test_chunked_data_pipe_getter.h
index 4832189e79d..4039e61f358 100644
--- a/chromium/services/network/test_chunked_data_pipe_getter.h
+++ b/chromium/services/network/test_chunked_data_pipe_getter.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chromium/services/network/test_mojo_proxy_resolver_factory.h b/chromium/services/network/test_mojo_proxy_resolver_factory.h
index e7057e16c2b..6de6fe81fea 100644
--- a/chromium/services/network/test_mojo_proxy_resolver_factory.h
+++ b/chromium/services/network/test_mojo_proxy_resolver_factory.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/proxy_resolver/proxy_resolver_factory_impl.h"
diff --git a/chromium/services/network/throttling/network_conditions.h b/chromium/services/network/throttling/network_conditions.h
index db9eed0ff7f..f8c8214b34b 100644
--- a/chromium/services/network/throttling/network_conditions.h
+++ b/chromium/services/network/throttling/network_conditions.h
@@ -6,7 +6,6 @@
#define SERVICES_NETWORK_THROTTLING_NETWORK_CONDITIONS_H_
#include "base/component_export.h"
-#include "base/macros.h"
namespace network {
diff --git a/chromium/services/network/throttling/scoped_throttling_token.h b/chromium/services/network/throttling/scoped_throttling_token.h
index af4ea1d662e..7132cefdf01 100644
--- a/chromium/services/network/throttling/scoped_throttling_token.h
+++ b/chromium/services/network/throttling/scoped_throttling_token.h
@@ -10,7 +10,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
diff --git a/chromium/services/network/throttling/throttling_controller.cc b/chromium/services/network/throttling/throttling_controller.cc
index c4f3f7a60d0..176e45bb5d3 100644
--- a/chromium/services/network/throttling/throttling_controller.cc
+++ b/chromium/services/network/throttling/throttling_controller.cc
@@ -45,15 +45,6 @@ void ThrottlingController::UnregisterNetLogSource(uint32_t net_log_source_id) {
instance().Unregister(net_log_source_id);
}
-// static
-bool ThrottlingController::HasInterceptor(
- const base::UnguessableToken& throttling_profile_id) {
- DCHECK_CALLED_ON_VALID_THREAD(instance().thread_checker_);
-
- return instance().interceptors_.find(throttling_profile_id) !=
- instance().interceptors_.end();
-}
-
void ThrottlingController::Register(
uint32_t net_log_source_id,
const base::UnguessableToken& throttling_profile_id) {
diff --git a/chromium/services/network/throttling/throttling_controller.h b/chromium/services/network/throttling/throttling_controller.h
index feb763393cf..e0db884ba66 100644
--- a/chromium/services/network/throttling/throttling_controller.h
+++ b/chromium/services/network/throttling/throttling_controller.h
@@ -9,7 +9,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/threading/thread_checker.h"
#include "base/unguessable_token.h"
@@ -25,6 +24,9 @@ class ThrottlingNetworkInterceptor;
// profile ID and their throttling conditions.
class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingController {
public:
+ ThrottlingController(const ThrottlingController&) = delete;
+ ThrottlingController& operator=(const ThrottlingController&) = delete;
+
// Applies network emulation configuration.
static void SetConditions(const base::UnguessableToken& throttling_profile_id,
std::unique_ptr<NetworkConditions>);
@@ -51,11 +53,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingController {
// Unregister the NetLog source. This is called from ScopedThrottlingToken.
static void UnregisterNetLogSource(uint32_t net_log_source_id);
- // Returns whether there is an interceptor for the profile ID. This is called
- // from ScopedThrottlingToken.
- static bool HasInterceptor(
- const base::UnguessableToken& throttling_profile_id);
-
void Register(uint32_t net_log_source_id,
const base::UnguessableToken& throttling_profile_id);
void Unregister(uint32_t net_log_source_id);
@@ -78,8 +75,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingController {
InterceptorMap interceptors_;
NetLogSourceProfileMap net_log_source_profile_map_;
THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(ThrottlingController);
};
} // namespace network
diff --git a/chromium/services/network/throttling/throttling_controller_unittest.cc b/chromium/services/network/throttling/throttling_controller_unittest.cc
index 72bcc50afa7..bffd6999b4c 100644
--- a/chromium/services/network/throttling/throttling_controller_unittest.cc
+++ b/chromium/services/network/throttling/throttling_controller_unittest.cc
@@ -57,10 +57,11 @@ class TestCallback {
class ThrottlingControllerTestHelper {
public:
- ThrottlingControllerTestHelper()
+ explicit ThrottlingControllerTestHelper(
+ MockTransaction mock_transaction = kSimpleGET_Transaction)
: completion_callback_(base::BindRepeating(&TestCallback::Run,
base::Unretained(&callback_))),
- mock_transaction_(kSimpleGET_Transaction),
+ mock_transaction_(mock_transaction),
buffer_(base::MakeRefCounted<net::IOBuffer>(64)),
net_log_with_source_(
net::NetLogWithSource::Make(net::NetLog::Get(),
@@ -108,10 +109,12 @@ class ThrottlingControllerTestHelper {
return rv;
}
- int Read() {
- return transaction_->Read(buffer_.get(), 64, completion_callback_);
+ int Read(net::IOBuffer* buffer, int buffer_size) {
+ return transaction_->Read(buffer, buffer_size, completion_callback_);
}
+ int Read() { return Read(buffer_.get(), 64); }
+
bool ShouldFail() {
if (transaction_->interceptor_)
return transaction_->interceptor_->IsOffline();
@@ -335,4 +338,29 @@ TEST(ThrottlingControllerTest, UploadOnly) {
EXPECT_EQ(callback->value(), static_cast<int>(base::size(kUploadData)));
}
+TEST(ThrottlingControllerTest, DownloadIsStreamed) {
+ MockTransaction mock_transaction = kSimpleGET_Transaction;
+ const int kLargeDataSize = 1024 * 1024;
+ std::string large_data(kLargeDataSize, 'x');
+ mock_transaction.data = large_data.c_str();
+ ThrottlingControllerTestHelper helper(mock_transaction);
+ TestCallback* callback = helper.callback();
+
+ helper.SetNetworkState(false, 1, 0);
+ int rv = helper.Start(false);
+ EXPECT_EQ(rv, net::ERR_IO_PENDING);
+ helper.FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(callback->run_count(), 1);
+ EXPECT_GE(callback->value(), net::OK);
+
+ auto large_data_buffer = base::MakeRefCounted<net::IOBuffer>(kLargeDataSize);
+ helper.Read(large_data_buffer.get(), kLargeDataSize);
+ EXPECT_EQ(rv, net::ERR_IO_PENDING);
+ EXPECT_EQ(callback->run_count(), 1);
+ helper.FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(callback->run_count(), 2);
+ EXPECT_GT(callback->value(), net::OK);
+ EXPECT_LT(callback->value(), kLargeDataSize);
+}
+
} // namespace network
diff --git a/chromium/services/network/throttling/throttling_network_interceptor.h b/chromium/services/network/throttling/throttling_network_interceptor.h
index b30403b793f..aca3e51a084 100644
--- a/chromium/services/network/throttling/throttling_network_interceptor.h
+++ b/chromium/services/network/throttling/throttling_network_interceptor.h
@@ -13,7 +13,6 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/timer/timer.h"
namespace base {
diff --git a/chromium/services/network/throttling/throttling_network_transaction.cc b/chromium/services/network/throttling/throttling_network_transaction.cc
index 239047ce408..4f8ba641d97 100644
--- a/chromium/services/network/throttling/throttling_network_transaction.cc
+++ b/chromium/services/network/throttling/throttling_network_transaction.cc
@@ -4,6 +4,7 @@
#include "services/network/throttling/throttling_network_transaction.h"
+#include <algorithm>
#include <memory>
#include <utility>
@@ -204,6 +205,8 @@ bool ThrottlingNetworkTransaction::IsReadyToRestartForAuth() {
int ThrottlingNetworkTransaction::Read(net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback) {
+ constexpr int kPacketSize = 1500;
+
if (CheckFailed())
return net::ERR_INTERNET_DISCONNECTED;
if (!interceptor_)
@@ -211,7 +214,7 @@ int ThrottlingNetworkTransaction::Read(net::IOBuffer* buf,
callback_ = std::move(callback);
int result = network_transaction_->Read(
- buf, buf_len,
+ buf, std::min(buf_len, kPacketSize),
base::BindOnce(&ThrottlingNetworkTransaction::IOCallback,
base::Unretained(this), false));
// URLRequestJob relies on synchronous end-of-stream notification.
diff --git a/chromium/services/network/throttling/throttling_network_transaction.h b/chromium/services/network/throttling/throttling_network_transaction.h
index 8065b4fddb2..ce7a26de4f9 100644
--- a/chromium/services/network/throttling/throttling_network_transaction.h
+++ b/chromium/services/network/throttling/throttling_network_transaction.h
@@ -10,7 +10,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "net/base/completion_once_callback.h"
#include "net/base/load_states.h"
@@ -107,7 +107,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingNetworkTransaction
ThrottlingNetworkInterceptor::ThrottleCallback throttle_callback_;
int64_t throttled_byte_count_;
- ThrottlingController* controller_;
+ raw_ptr<ThrottlingController> controller_;
base::WeakPtr<ThrottlingNetworkInterceptor> interceptor_;
// Modified upload data stream. Should be destructed after |custom_request_|.
@@ -122,7 +122,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingNetworkTransaction
// User callback.
net::CompletionOnceCallback callback_;
- const net::HttpRequestInfo* request_;
+ raw_ptr<const net::HttpRequestInfo> request_;
// True if Fail was already invoked.
bool failed_;
diff --git a/chromium/services/network/throttling/throttling_network_transaction_factory.h b/chromium/services/network/throttling/throttling_network_transaction_factory.h
index 390698c22a4..7165c4cabfe 100644
--- a/chromium/services/network/throttling/throttling_network_transaction_factory.h
+++ b/chromium/services/network/throttling/throttling_network_transaction_factory.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "net/base/request_priority.h"
#include "net/http/http_transaction_factory.h"
diff --git a/chromium/services/network/throttling/throttling_upload_data_stream.h b/chromium/services/network/throttling/throttling_upload_data_stream.h
index a1f10d0f59c..2382ee20f62 100644
--- a/chromium/services/network/throttling/throttling_upload_data_stream.h
+++ b/chromium/services/network/throttling/throttling_upload_data_stream.h
@@ -7,7 +7,7 @@
#include <stdint.h>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "net/base/upload_data_stream.h"
#include "services/network/throttling/throttling_network_interceptor.h"
@@ -48,7 +48,7 @@ class ThrottlingUploadDataStream : public net::UploadDataStream {
ThrottlingNetworkInterceptor::ThrottleCallback throttle_callback_;
int64_t throttled_byte_count_;
- net::UploadDataStream* upload_data_stream_;
+ raw_ptr<net::UploadDataStream> upload_data_stream_;
base::WeakPtr<ThrottlingNetworkInterceptor> interceptor_;
};
diff --git a/chromium/services/network/tls_client_socket.h b/chromium/services/network/tls_client_socket.h
index f898cc14c43..2330f52ec10 100644
--- a/chromium/services/network/tls_client_socket.h
+++ b/chromium/services/network/tls_client_socket.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/network/tls_client_socket_unittest.cc b/chromium/services/network/tls_client_socket_unittest.cc
index 5ff6f6d64fd..d4629ea9ec4 100644
--- a/chromium/services/network/tls_client_socket_unittest.cc
+++ b/chromium/services/network/tls_client_socket_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check_op.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -484,8 +483,8 @@ TEST_P(TLSClientSocketTest, UpgradeToTLSWithCustomSSLConfig) {
data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
- ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_1;
- ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
+ ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_2;
+ ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_3;
mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
SocketHandle client_socket;
@@ -501,8 +500,8 @@ TEST_P(TLSClientSocketTest, UpgradeToTLSWithCustomSSLConfig) {
base::RunLoop run_loop;
mojom::TLSClientSocketOptionsPtr options =
mojom::TLSClientSocketOptions::New();
- options->version_min = mojom::SSLVersion::kTLS11;
- options->version_max = mojom::SSLVersion::kTLS12;
+ options->version_min = mojom::SSLVersion::kTLS12;
+ options->version_max = mojom::SSLVersion::kTLS13;
int net_error = net::ERR_FAILED;
auto upgrade_callback = base::BindLambdaForTesting(
[&](int result, mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
diff --git a/chromium/services/network/tls_socket_factory.h b/chromium/services/network/tls_socket_factory.h
index 772305d0197..dc1c38cfb67 100644
--- a/chromium/services/network/tls_socket_factory.h
+++ b/chromium/services/network/tls_socket_factory.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
@@ -88,8 +88,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) TLSSocketFactory {
std::unique_ptr<net::CTPolicyEnforcer> no_verification_ct_policy_enforcer_;
net::SSLClientContext ssl_client_context_;
- net::ClientSocketFactory* client_socket_factory_;
- net::SSLConfigService* const ssl_config_service_;
+ raw_ptr<net::ClientSocketFactory> client_socket_factory_;
+ const raw_ptr<net::SSLConfigService> ssl_config_service_;
mojo::UniqueReceiverSet<mojom::TLSClientSocket> tls_socket_receivers_;
};
diff --git a/chromium/services/network/transitional_url_loader_factory_owner.h b/chromium/services/network/transitional_url_loader_factory_owner.h
index 3337e6833a8..167ab97db86 100644
--- a/chromium/services/network/transitional_url_loader_factory_owner.h
+++ b/chromium/services/network/transitional_url_loader_factory_owner.h
@@ -8,11 +8,10 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/synchronization/atomic_flag.h"
+#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
diff --git a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h
index 27ebd8f5720..02a87aa4936 100644
--- a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h
+++ b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_NETWORK_TRUST_TOKENS_EXPIRY_INSPECTING_RECORD_EXPIRY_DELEGATE_H_
#define SERVICES_NETWORK_TRUST_TOKENS_EXPIRY_INSPECTING_RECORD_EXPIRY_DELEGATE_H_
+#include "base/memory/raw_ptr.h"
#include "services/network/trust_tokens/suitable_trust_token_origin.h"
#include "services/network/trust_tokens/trust_token_store.h"
@@ -37,7 +38,8 @@ class ExpiryInspectingRecordExpiryDelegate
const SuitableTrustTokenOrigin& issuer) override;
private:
- const SynchronousTrustTokenKeyCommitmentGetter* key_commitment_getter_;
+ raw_ptr<const SynchronousTrustTokenKeyCommitmentGetter>
+ key_commitment_getter_;
};
} // namespace network
diff --git a/chromium/services/network/trust_tokens/has_trust_tokens_answerer.h b/chromium/services/network/trust_tokens/has_trust_tokens_answerer.h
index e0f0938b733..48304f1571c 100644
--- a/chromium/services/network/trust_tokens/has_trust_tokens_answerer.h
+++ b/chromium/services/network/trust_tokens/has_trust_tokens_answerer.h
@@ -6,6 +6,7 @@
#define SERVICES_NETWORK_TRUST_TOKENS_HAS_TRUST_TOKENS_ANSWERER_H_
#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/suitable_trust_token_origin.h"
@@ -47,7 +48,7 @@ class HasTrustTokensAnswerer : public mojom::HasTrustTokensAnswerer {
TrustTokenStore* trust_token_store);
const SuitableTrustTokenOrigin top_frame_origin_;
- PendingTrustTokenStore* pending_trust_token_store_;
+ raw_ptr<PendingTrustTokenStore> pending_trust_token_store_;
base::WeakPtrFactory<HasTrustTokensAnswerer> weak_factory_{this};
};
diff --git a/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc b/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc
index da420d5725d..1e578256092 100644
--- a/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc
+++ b/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc
@@ -7,8 +7,8 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_split.h"
+#include "base/task/sequenced_task_runner.h"
#include "components/sqlite_proto/key_value_data.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/trust_tokens/proto/storage.pb.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_client_data_canonicalization.cc b/chromium/services/network/trust_tokens/trust_token_client_data_canonicalization.cc
index 8e1fb8f6e3c..0f7d542eb03 100644
--- a/chromium/services/network/trust_tokens/trust_token_client_data_canonicalization.cc
+++ b/chromium/services/network/trust_tokens/trust_token_client_data_canonicalization.cc
@@ -42,7 +42,7 @@ CanonicalizeTrustTokenClientDataForRedemption(
base::TimeDelta redemption_timestamp_minus_unix_epoch =
redemption_timestamp - base::Time::UnixEpoch();
- if (redemption_timestamp_minus_unix_epoch < base::TimeDelta())
+ if (redemption_timestamp_minus_unix_epoch.is_negative())
return absl::nullopt;
map[cbor::Value(kRedemptionTimestampKey, cbor::Value::Type::STRING)] =
diff --git a/chromium/services/network/trust_tokens/trust_token_database_owner.cc b/chromium/services/network/trust_tokens/trust_token_database_owner.cc
index 91028c8f160..eaacd27ef71 100644
--- a/chromium/services/network/trust_tokens/trust_token_database_owner.cc
+++ b/chromium/services/network/trust_tokens/trust_token_database_owner.cc
@@ -12,7 +12,7 @@
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "components/sqlite_proto/key_value_data.h"
#include "components/sqlite_proto/key_value_table.h"
#include "components/sqlite_proto/proto_table_manager.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_database_owner.h b/chromium/services/network/trust_tokens/trust_token_database_owner.h
index d71a9be50c7..af0204e0cb2 100644
--- a/chromium/services/network/trust_tokens/trust_token_database_owner.h
+++ b/chromium/services/network/trust_tokens/trust_token_database_owner.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "components/sqlite_proto/key_value_data.h"
#include "components/sqlite_proto/key_value_table.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h
index c949219214c..69a6fcc8ec5 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h
+++ b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
#include "net/log/net_log_with_source.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
@@ -108,8 +109,8 @@ class TrustTokenRequestHelperFactory {
base::OnceCallback<void(TrustTokenStatusOrRequestHelper)> done,
TrustTokenStore* store);
- PendingTrustTokenStore* store_;
- const TrustTokenKeyCommitmentGetter* key_commitment_getter_;
+ raw_ptr<PendingTrustTokenStore> store_;
+ raw_ptr<const TrustTokenKeyCommitmentGetter> key_commitment_getter_;
base::RepeatingCallback<mojom::NetworkContextClient*(void)>
context_client_provider_;
base::RepeatingCallback<bool(void)> authorizer_;
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 e751480f555..ea4868e93c6 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
@@ -67,7 +67,6 @@ class TrustTokenRequestHelperFactoryTest : public ::testing::Test {
const mojom::TrustTokenParams& suitable_signing_params() const {
return *suitable_params_;
}
- const net::NetLog& net_log() const { return *maker_.net_log(); }
std::unique_ptr<net::URLRequest> CreateSuitableRequest() {
auto ret = maker_.MakeURLRequest("https://destination.example");
diff --git a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h
index 230ddf13ced..f6f041722bf 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h
+++ b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece_forward.h"
#include "net/log/net_log_with_source.h"
@@ -267,8 +268,8 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper {
// operation's execution.
absl::optional<SuitableTrustTokenOrigin> issuer_;
const SuitableTrustTokenOrigin top_level_origin_;
- TrustTokenStore* const token_store_;
- const TrustTokenKeyCommitmentGetter* const key_commitment_getter_;
+ const raw_ptr<TrustTokenStore> token_store_;
+ const raw_ptr<const TrustTokenKeyCommitmentGetter> key_commitment_getter_;
mojom::TrustTokenProtocolVersion protocol_version_;
@@ -293,7 +294,7 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper {
base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
is_current_os_callback_;
- MetricsDelegate* const metrics_delegate_;
+ const raw_ptr<MetricsDelegate> metrics_delegate_;
net::NetLogWithSource net_log_;
absl::optional<size_t> num_obtained_tokens_;
diff --git a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h
index 67ea906059d..96da41c9094 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h
+++ b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece_forward.h"
#include "net/log/net_log_with_source.h"
@@ -211,8 +212,8 @@ class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper {
// alongside the RR if redemption succeeds.
std::string token_verification_key_;
- TrustTokenStore* const token_store_;
- const TrustTokenKeyCommitmentGetter* const key_commitment_getter_;
+ const raw_ptr<TrustTokenStore> token_store_;
+ const raw_ptr<const TrustTokenKeyCommitmentGetter> key_commitment_getter_;
const std::unique_ptr<KeyPairGenerator> key_pair_generator_;
const std::unique_ptr<Cryptographer> cryptographer_;
net::NetLogWithSource net_log_;
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 b8a0d1c287e..6be6937005c 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
@@ -10,6 +10,7 @@
#include "base/base64.h"
#include "base/containers/flat_set.h"
+#include "base/ignore_result.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
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 3bc06221765..1352258fcf4 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
@@ -11,6 +11,7 @@
#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/containers/span.h"
+#include "base/memory/raw_ptr.h"
#include "net/http/http_request_headers.h"
#include "net/log/net_log_with_source.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
@@ -253,7 +254,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
const TrustTokenRedemptionRecord& record,
const std::vector<std::string>& headers_to_sign);
- TrustTokenStore* token_store_;
+ raw_ptr<TrustTokenStore> token_store_;
Params params_;
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 7bb81974373..762b116fffe 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
@@ -24,6 +24,7 @@
#include "components/cbor/writer.h"
#include "net/base/request_priority.h"
#include "net/http/structured_headers.h"
+#include "net/log/net_log.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"
@@ -693,11 +694,11 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) {
// FailingSigner will fail to sign the request, so we should see the operation
// fail.
- net::RecordingTestNetLog net_log;
+ net::RecordingNetLogObserver net_log_observer;
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FailingSigner>(),
std::make_unique<TrustTokenRequestCanonicalizer>(),
- net::NetLogWithSource::Make(&net_log,
+ net::NetLogWithSource::Make(net::NetLog::Get(),
net::NetLogSourceType::URL_REQUEST));
auto my_request = MakeURLRequest("https://destination.com/");
@@ -712,7 +713,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) {
EXPECT_THAT(*my_request, Not(Header("Sec-Signature")));
EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty()));
EXPECT_TRUE(base::ranges::any_of(
- net_log.GetEntriesWithType(
+ net_log_observer.GetEntriesWithType(
net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_SIGNING),
[](const net::NetLogEntry& entry) {
absl::optional<std::string> key = net::GetOptionalStringValueFromParams(
diff --git a/chromium/services/network/trust_tokens/trust_token_store.cc b/chromium/services/network/trust_tokens/trust_token_store.cc
index adbb5a82791..ed6d1de08dd 100644
--- a/chromium/services/network/trust_tokens/trust_token_store.cc
+++ b/chromium/services/network/trust_tokens/trust_token_store.cc
@@ -82,7 +82,7 @@ absl::optional<base::TimeDelta> TrustTokenStore::TimeSinceLastIssuance(
return absl::nullopt;
base::TimeDelta ret = base::Time::Now() - *maybe_last_issuance;
- if (ret < base::TimeDelta())
+ if (ret.is_negative())
return absl::nullopt;
return ret;
@@ -115,7 +115,7 @@ absl::optional<base::TimeDelta> TrustTokenStore::TimeSinceLastRedemption(
return absl::nullopt;
base::TimeDelta ret = base::Time::Now() - *maybe_last_redemption;
- if (ret < base::TimeDelta())
+ if (ret.is_negative())
return absl::nullopt;
return ret;
}
diff --git a/chromium/services/network/trust_tokens/trust_token_store.h b/chromium/services/network/trust_tokens/trust_token_store.h
index 6c9907a0b40..0451f7cae8d 100644
--- a/chromium/services/network/trust_tokens/trust_token_store.h
+++ b/chromium/services/network/trust_tokens/trust_token_store.h
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
diff --git a/chromium/services/network/udp_socket.h b/chromium/services/network/udp_socket.h
index 32dfd9c9c89..b51291d9506 100644
--- a/chromium/services/network/udp_socket.h
+++ b/chromium/services/network/udp_socket.h
@@ -11,7 +11,7 @@
#include "base/component_export.h"
#include "base/containers/span.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -145,7 +145,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket {
void OnRecvFromCompleted(uint32_t buffer_size, int net_result);
void OnSendToCompleted(int net_result);
- net::NetLog* net_log_;
+ raw_ptr<net::NetLog> net_log_;
// Whether a Bind() has been successfully executed.
bool is_bound_;
diff --git a/chromium/services/network/udp_socket_unittest.cc b/chromium/services/network/udp_socket_unittest.cc
index 744aef7755a..a1cd83a9aa2 100644
--- a/chromium/services/network/udp_socket_unittest.cc
+++ b/chromium/services/network/udp_socket_unittest.cc
@@ -11,7 +11,6 @@
#include "services/network/udp_socket.h"
#include "base/bind.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "base/run_loop.h"
diff --git a/chromium/services/network/upload_progress_tracker.h b/chromium/services/network/upload_progress_tracker.h
index 600676387ff..fc943f8a677 100644
--- a/chromium/services/network/upload_progress_tracker.h
+++ b/chromium/services/network/upload_progress_tracker.h
@@ -9,9 +9,9 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -57,7 +57,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UploadProgressTracker {
void ReportUploadProgressIfNeeded();
- net::URLRequest* request_; // Not owned.
+ raw_ptr<net::URLRequest> request_; // Not owned.
uint64_t last_upload_position_ = 0;
bool waiting_for_upload_progress_ack_ = false;
diff --git a/chromium/services/network/upload_progress_tracker_unittest.cc b/chromium/services/network/upload_progress_tracker_unittest.cc
index a463966af31..7922e46bf18 100644
--- a/chromium/services/network/upload_progress_tracker_unittest.cc
+++ b/chromium/services/network/upload_progress_tracker_unittest.cc
@@ -6,9 +6,8 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "net/base/upload_progress.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,6 +27,10 @@ class TestingUploadProgressTracker : public UploadProgressTracker {
std::move(task_runner)),
current_time_(base::TimeTicks::Now()) {}
+ TestingUploadProgressTracker(const TestingUploadProgressTracker&) = delete;
+ TestingUploadProgressTracker& operator=(const TestingUploadProgressTracker&) =
+ delete;
+
void set_upload_progress(const net::UploadProgress& upload_progress) {
upload_progress_ = upload_progress;
}
@@ -45,8 +48,6 @@ class TestingUploadProgressTracker : public UploadProgressTracker {
base::TimeTicks current_time_;
net::UploadProgress upload_progress_;
-
- DISALLOW_COPY_AND_ASSIGN(TestingUploadProgressTracker);
};
} // namespace
@@ -62,6 +63,10 @@ class UploadProgressTrackerTest : public ::testing::Test {
base::Unretained(this)),
task_environment_.GetMainThreadTaskRunner()) {}
+ UploadProgressTrackerTest(const UploadProgressTrackerTest&) = delete;
+ UploadProgressTrackerTest& operator=(const UploadProgressTrackerTest&) =
+ delete;
+
private:
void OnUploadProgressReported(const net::UploadProgress& progress) {
++report_count_;
@@ -77,8 +82,6 @@ class UploadProgressTrackerTest : public ::testing::Test {
base::test::SingleThreadTaskEnvironment task_environment_;
TestingUploadProgressTracker upload_progress_tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(UploadProgressTrackerTest);
};
TEST_F(UploadProgressTrackerTest, NoACK) {
diff --git a/chromium/services/network/url_loader.cc b/chromium/services/network/url_loader.cc
index 136427ff144..e53ff47c6f4 100644
--- a/chromium/services/network/url_loader.cc
+++ b/chromium/services/network/url_loader.cc
@@ -16,6 +16,7 @@
#include "base/debug/dump_without_crashing.h"
#include "base/files/file.h"
#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
@@ -27,6 +28,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "base/trace_event/typed_macros.h"
#include "build/build_config.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/elements_upload_data_stream.h"
@@ -44,6 +46,8 @@
#include "net/cookies/static_cookie_policy.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_request_headers.h"
+#include "net/log/net_log_source_type.h"
+#include "net/log/net_log_with_source.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_private_key.h"
@@ -91,6 +95,7 @@
#include "url/origin.h"
#if defined(OS_ANDROID)
+#include "net/base/features.h"
#include "services/network/radio_monitor_android.h"
#endif
@@ -286,6 +291,9 @@ class SSLPrivateKeyInternal : public net::SSLPrivateKey {
base::Unretained(this)));
}
+ SSLPrivateKeyInternal(const SSLPrivateKeyInternal&) = delete;
+ SSLPrivateKeyInternal& operator=(const SSLPrivateKeyInternal&) = delete;
+
// net::SSLPrivateKey:
std::string GetProviderName() override { return provider_name_; }
@@ -327,8 +335,6 @@ class SSLPrivateKeyInternal : public net::SSLPrivateKey {
std::string provider_name_;
std::vector<uint16_t> algorithm_preferences_;
mojo::Remote<mojom::SSLPrivateKey> ssl_private_key_;
-
- DISALLOW_COPY_AND_ASSIGN(SSLPrivateKeyInternal);
};
bool ShouldNotifyAboutCookie(net::CookieInclusionStatus status) {
@@ -546,6 +552,8 @@ URLLoader::URLLoader(
request.request_body &&
request.request_body->AllowHTTP1ForStreamingUpload()),
accept_ch_frame_observer_(std::move(accept_ch_frame_observer)) {
+ TRACE_EVENT("loading", "URLLoader::URLLoader",
+ perfetto::Flow::FromPointer(this));
DCHECK(delete_callback_);
DCHECK(factory_params_);
@@ -571,15 +579,16 @@ URLLoader::URLLoader(
base::BindOnce(&URLLoader::OnMojoDisconnect, base::Unretained(this)));
url_request_ = url_request_context_->CreateRequest(
GURL(request.url), request.priority, this, traffic_annotation,
- /*is_for_websockets=*/false,
- request.net_log_params
- ? absl::make_optional(request.net_log_params->source_id)
- : absl::nullopt);
+ /*is_for_websockets=*/false, request.net_log_create_info);
url_request_->set_method(request.method);
url_request_->set_site_for_cookies(request.site_for_cookies);
if (ShouldForceIgnoreSiteForCookies(request))
url_request_->set_force_ignore_site_for_cookies(true);
+ if (!request.navigation_redirect_chain.empty()) {
+ DCHECK_EQ(request.mode, mojom::RequestMode::kNavigate);
+ url_request_->SetURLChain(request.navigation_redirect_chain);
+ }
url_request_->SetReferrer(request.referrer.GetAsReferrer().spec());
url_request_->set_referrer_policy(request.referrer_policy);
url_request_->set_upgrade_if_insecure(request.upgrade_if_insecure);
@@ -606,6 +615,18 @@ URLLoader::URLLoader(
if (ShouldForceIgnoreTopFramePartyForCookies())
url_request_->set_force_ignore_top_frame_party_for_cookies(true);
+ // When a service worker forwards a navigation request it uses the
+ // service worker's IsolationInfo. This causes the cookie code to fail
+ // to send SameSite=Lax cookies for main-frame navigations passed through
+ // a service worker. To fix this we check to see if the original destination
+ // of the request was a main frame document and then set a flag indicating
+ // SameSite cookies should treat it as a main frame navigation.
+ if (request.mode == mojom::RequestMode::kNavigate &&
+ request.destination == mojom::RequestDestination::kEmpty &&
+ request.original_destination == mojom::RequestDestination::kDocument) {
+ url_request_->set_force_main_frame_for_same_site_cookies(true);
+ }
+
if (factory_params_->disable_secure_dns ||
(request.trusted_params && request.trusted_params->disable_secure_dns)) {
url_request_->SetSecureDnsPolicy(net::SecureDnsPolicy::kDisable);
@@ -682,10 +703,16 @@ URLLoader::URLLoader(
*factory_params_->top_frame_id, keepalive_request_size_);
}
+ if (request.net_log_reference_info) {
+ // Log source object that created the request, if avairable.
+ url_request_->net_log().AddEventReferencingSource(
+ net::NetLogEventType::CREATED_BY,
+ request.net_log_reference_info.value());
+ }
+
#if defined(OS_ANDROID)
- if (base::FeatureList::IsEnabled(features::kRecordRadioWakeupTrigger)) {
- RadioMonitorAndroid::GetInstance().MaybeRecordURLLoaderAnnotationId(
- traffic_annotation);
+ if (base::FeatureList::IsEnabled(net::features::kRecordRadioWakeupTrigger)) {
+ MaybeRecordURLLoaderCreationForWakeupTrigger(request, traffic_annotation);
}
#endif
@@ -791,9 +818,9 @@ class URLLoader::FileOpenerForUpload {
// The paths of files for upload
const std::vector<base::FilePath> paths_;
- URLLoader* const url_loader_;
+ const raw_ptr<URLLoader> url_loader_;
const int32_t process_id_;
- mojom::NetworkContextClient* const network_context_client_;
+ const raw_ptr<mojom::NetworkContextClient> network_context_client_;
SetUpUploadCallback set_up_upload_callback_;
// The files opened so far.
std::vector<base::File> opened_files_;
@@ -960,6 +987,8 @@ void URLLoader::ScheduleStart() {
}
URLLoader::~URLLoader() {
+ TRACE_EVENT("loading", "URLLoader::~URLLoader",
+ perfetto::TerminatingFlow::FromPointer(this));
RecordBodyReadFromNetBeforePausedIfNeeded();
if (keepalive_ && keepalive_statistics_recorder_) {
keepalive_statistics_recorder_->OnLoadFinished(
@@ -980,9 +1009,13 @@ void URLLoader::FollowRedirect(
return;
}
+ // Set seen_raw_request_headers_ to false in order to make sure this redirect
+ // also calls the devtools observer.
+ seen_raw_request_headers_ = false;
+
// Removing headers can't make the set of pre-existing headers unsafe, but
// adding headers can.
- if (!AreRequestHeadersSafe(modified_headers) |
+ if (!AreRequestHeadersSafe(modified_headers) ||
!AreRequestHeadersSafe(modified_cors_exempt_headers)) {
NotifyCompleted(net::ERR_INVALID_ARGUMENT);
// |this| may have been deleted.
@@ -1046,23 +1079,32 @@ void URLLoader::ResumeReadingBodyFromNet() {
}
}
-PrivateNetworkAccessCheckResult URLLoader::PrivateNetworkAccessCheck(
- mojom::IPAddressSpace resource_address_space) const {
+// WARNING: This should be kept in sync with similar logic in
+// `network::cors::CorsURLLoader::GetClientSecurityState()`.
+const mojom::ClientSecurityState* URLLoader::GetClientSecurityState() const {
// Depending on the type of URL request, we source the client security state
// from either the URLRequest's trusted params (for navigations, which share
// a factory) or the URLLoaderFactory's params. We prefer the factory params
// over the request params, as the former always come from the browser
// process.
- const mojom::ClientSecurityStatePtr& security_state =
- factory_params_->client_security_state
- ? factory_params_->client_security_state
- : request_client_security_state_;
+ if (factory_params_->client_security_state) {
+ return factory_params_->client_security_state.get();
+ }
+
+ return request_client_security_state_.get();
+}
+
+PrivateNetworkAccessCheckResult URLLoader::PrivateNetworkAccessCheck(
+ const net::TransportInfo& transport_info) {
+ resource_ip_address_space_ = TransportInfoToIPAddressSpace(transport_info);
+
+ const mojom::ClientSecurityState* security_state = GetClientSecurityState();
// Fully-qualify function name to disambiguate it, otherwise it resolves to
// `URLLoader::PrivateNetworkAccessCheck()` and fails to compile.
PrivateNetworkAccessCheckResult result = network::PrivateNetworkAccessCheck(
- security_state.get(), target_ip_address_space_, options_,
- resource_address_space);
+ security_state, target_ip_address_space_, options_,
+ resource_ip_address_space_);
bool is_warning = false;
switch (result) {
@@ -1084,7 +1126,7 @@ PrivateNetworkAccessCheckResult URLLoader::PrivateNetworkAccessCheck(
if (auto* devtools_observer = GetDevToolsObserver()) {
devtools_observer->OnPrivateNetworkRequest(
devtools_request_id(), url_request_->url(), is_warning,
- resource_address_space, security_state->Clone());
+ resource_ip_address_space_, security_state->Clone());
}
return result;
@@ -1100,18 +1142,15 @@ int URLLoader::OnConnected(net::URLRequest* url_request,
// Now that the request endpoint's address has been resolved, check if
// this request should be blocked per Private Network Access.
- mojom::IPAddressSpace resource_address_space =
- IPEndPointToIPAddressSpace(info.endpoint);
-
absl::optional<mojom::CorsError> cors_error =
PrivateNetworkAccessCheckResultToCorsError(
- PrivateNetworkAccessCheck(resource_address_space));
+ PrivateNetworkAccessCheck(info));
if (cors_error.has_value()) {
// Remember the CORS error so we can annotate the URLLoaderCompletionStatus
// with it later, then fail the request with the same net error code as
// other CORS errors.
cors_error_status_ = CorsErrorStatus(*cors_error, target_ip_address_space_,
- resource_address_space);
+ resource_ip_address_space_);
return net::ERR_FAILED;
}
@@ -1154,7 +1193,7 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
auto response = network::mojom::URLResponseHead::New();
PopulateResourceResponse(url_request_.get(), is_load_timing_enabled_,
options_, response.get());
-
+ DispatchOnRawResponse();
ReportFlaggedResponseCookies();
const CrossOriginEmbedderPolicy kEmpty;
@@ -1198,6 +1237,8 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
&redirect_info.new_url, *factory_params_,
origin_access_list_);
+ DCHECK_EQ(emitted_devtools_raw_request_, emitted_devtools_raw_response_);
+ response->emitted_extra_info = emitted_devtools_raw_request_;
url_loader_client_.Get()->OnReceiveRedirect(redirect_info,
std::move(response));
}
@@ -1299,6 +1340,7 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
response_ = network::mojom::URLResponseHead::New();
PopulateResourceResponse(url_request_.get(), is_load_timing_enabled_,
options_, response_.get());
+ DispatchOnRawResponse();
// Parse and remove the Trust Tokens response headers, if any are expected,
// potentially failing the request if an error occurs.
@@ -1714,10 +1756,14 @@ void URLLoader::OnBeforeURLRequest() {
return url_loader_factory_->OnBeforeURLRequest();
}
-net::LoadState URLLoader::GetLoadStateForTesting() const {
+net::LoadState URLLoader::GetLoadState() const {
return url_request_->GetLoadState().state;
}
+net::UploadProgress URLLoader::GetUploadProgress() const {
+ return url_request_->GetUploadProgress();
+}
+
int32_t URLLoader::GetProcessId() const {
return factory_params_->process_id;
}
@@ -1902,8 +1948,10 @@ void URLLoader::DeleteSelf() {
}
void URLLoader::SendResponseToClient() {
- TRACE_EVENT1("loading", "network::URLLoader::SendResponseToClient", "url",
- url_request_->url().possibly_invalid_spec());
+ TRACE_EVENT("loading", "network::URLLoader::SendResponseToClient",
+ perfetto::Flow::FromPointer(this), "url", url_request_->url());
+ DCHECK_EQ(emitted_devtools_raw_request_, emitted_devtools_raw_response_);
+ response_->emitted_extra_info = emitted_devtools_raw_request_;
url_loader_client_.Get()->OnReceiveResponse(std::move(response_));
url_loader_client_.Get()->OnStartLoadingResponseBody(
std::move(consumer_handle_));
@@ -1967,7 +2015,10 @@ void URLLoader::NotifyEarlyResponse(
void URLLoader::SetRawRequestHeadersAndNotify(
net::HttpRawRequestHeaders headers) {
auto* devtools_observer = GetDevToolsObserver();
- if (devtools_observer && devtools_request_id()) {
+ // If we have seen_raw_request_headers_, then don't notify DevTools to prevent
+ // duplicate ExtraInfo events.
+ if (!seen_raw_request_headers_ && devtools_observer &&
+ devtools_request_id()) {
std::vector<network::mojom::HttpRawHeaderPairPtr> header_array;
header_array.reserve(headers.headers().size());
@@ -1978,21 +2029,7 @@ void URLLoader::SetRawRequestHeadersAndNotify(
pair->value = header.second;
header_array.push_back(std::move(pair));
}
-
- mojom::ClientSecurityStatePtr client_security_state;
- if (factory_params_->client_security_state) {
- client_security_state = factory_params_->client_security_state->Clone();
- } else if (request_client_security_state_) {
- client_security_state = request_client_security_state_->Clone();
- }
-
- net::LoadTimingInfo load_timing_info;
- url_request_->GetLoadTimingInfo(&load_timing_info);
-
- devtools_observer->OnRawRequest(
- devtools_request_id().value(), url_request_->maybe_sent_cookies(),
- std::move(header_array), load_timing_info.request_start,
- std::move(client_security_state));
+ DispatchOnRawRequest(std::move(header_array));
}
if (auto* cookie_observer = GetCookieAccessObserver()) {
@@ -2014,9 +2051,90 @@ void URLLoader::SetRawRequestHeadersAndNotify(
devtools_request_id()));
}
}
+}
+
+void URLLoader::DispatchOnRawRequest(
+ std::vector<network::mojom::HttpRawHeaderPairPtr> headers) {
+ auto* devtools_observer = GetDevToolsObserver();
+ DCHECK(devtools_observer && devtools_request_id());
+
+ seen_raw_request_headers_ = true;
+
+ mojom::ClientSecurityStatePtr client_security_state;
+ if (factory_params_->client_security_state) {
+ client_security_state = factory_params_->client_security_state->Clone();
+ } else if (request_client_security_state_) {
+ client_security_state = request_client_security_state_->Clone();
+ }
+
+ net::LoadTimingInfo load_timing_info;
+ url_request_->GetLoadTimingInfo(&load_timing_info);
- if (devtools_request_id())
- raw_request_headers_.Assign(std::move(headers));
+ emitted_devtools_raw_request_ = true;
+ devtools_observer->OnRawRequest(
+ devtools_request_id().value(), url_request_->maybe_sent_cookies(),
+ std::move(headers), load_timing_info.request_start,
+ std::move(client_security_state));
+}
+
+bool URLLoader::DispatchOnRawResponse() {
+ auto* devtools_observer = GetDevToolsObserver();
+ if (!devtools_observer || !devtools_request_id() ||
+ !url_request_->response_headers()) {
+ return false;
+ }
+
+ std::vector<network::mojom::HttpRawHeaderPairPtr> header_array;
+
+ // This is gated by enable_reporting_raw_headers_ to be backwards compatible
+ // with the old report_raw_headers behavior, where we wouldn't even send
+ // raw_response_headers_ to the trusted browser process based devtools
+ // instrumentation. This is observed in the case of HSTS redirects, where
+ // url_request_->response_headers has the HSTS redirect headers, like
+ // Non-Authoritative-Reason, but raw_response_headers_ has something else
+ // which doesn't include HSTS information. This is tested by
+ // DevToolsTest.TestRawHeadersWithRedirectAndHSTS.
+ // TODO(crbug.com/1234823): Remove enable_reporting_raw_headers_
+ const net::HttpResponseHeaders* response_headers =
+ raw_response_headers_ && enable_reporting_raw_headers_
+ ? raw_response_headers_.get()
+ : url_request_->response_headers();
+
+ size_t iterator = 0;
+ std::string name, value;
+ while (response_headers->EnumerateHeaderLines(&iterator, &name, &value)) {
+ network::mojom::HttpRawHeaderPairPtr pair =
+ network::mojom::HttpRawHeaderPair::New();
+ pair->key = name;
+ pair->value = value;
+ header_array.push_back(std::move(pair));
+ }
+
+ // Only send the "raw" header text when the headers were actually send in
+ // text form (i.e. not QUIC or SPDY)
+ absl::optional<std::string> raw_response_headers;
+
+ const net::HttpResponseInfo& response_info = url_request_->response_info();
+
+ if (!response_info.DidUseQuic() && !response_info.was_fetched_via_spdy) {
+ raw_response_headers =
+ absl::make_optional(net::HttpUtil::ConvertHeadersBackToHTTPResponse(
+ response_headers->raw_headers()));
+ }
+
+ if (!seen_raw_request_headers_) {
+ // If we send OnRawResponse(), make sure we send OnRawRequest() event if
+ // we haven't had the callback from net, to make the client life easier.
+ DispatchOnRawRequest({});
+ }
+
+ emitted_devtools_raw_response_ = true;
+ devtools_observer->OnRawResponse(
+ devtools_request_id().value(), url_request_->maybe_stored_cookies(),
+ std::move(header_array), raw_response_headers, resource_ip_address_space_,
+ response_headers->response_code());
+
+ return true;
}
void URLLoader::SendUploadProgress(const net::UploadProgress& progress) {
@@ -2182,54 +2300,6 @@ URLLoader::BlockResponseForCorbResult URLLoader::BlockResponseForCorb(
}
void URLLoader::ReportFlaggedResponseCookies() {
- auto* devtools_observer = GetDevToolsObserver();
- if (devtools_observer && devtools_request_id() &&
- url_request_->response_headers()) {
- std::vector<network::mojom::HttpRawHeaderPairPtr> header_array;
-
- // This is gated by enable_reporting_raw_headers_ to be backwards compatible
- // with the old report_raw_headers behavior, where we wouldn't even send
- // raw_response_headers_ to the trusted browser process based devtools
- // instrumentation. This is observed in the case of HSTS redirects, where
- // url_request_->response_headers has the HSTS redirect headers, like
- // Non-Authoritative-Reason, but raw_response_headers_ has something else
- // which doesn't include HSTS information. This is tested by
- // DevToolsTest.TestRawHeadersWithRedirectAndHSTS.
- // TODO(crbug.com/1234823): Remove enable_reporting_raw_headers_
- const net::HttpResponseHeaders* response_headers =
- raw_response_headers_ && enable_reporting_raw_headers_
- ? raw_response_headers_.get()
- : url_request_->response_headers();
-
- size_t iterator = 0;
- std::string name, value;
- while (response_headers->EnumerateHeaderLines(&iterator, &name, &value)) {
- network::mojom::HttpRawHeaderPairPtr pair =
- network::mojom::HttpRawHeaderPair::New();
- pair->key = name;
- pair->value = value;
- header_array.push_back(std::move(pair));
- }
-
- // Only send the "raw" header text when the headers were actually send in
- // text form (i.e. not QUIC or SPDY)
- absl::optional<std::string> raw_response_headers;
-
- const net::HttpResponseInfo& response_info = url_request_->response_info();
-
- if (!response_info.DidUseQuic() && !response_info.was_fetched_via_spdy) {
- raw_response_headers =
- absl::make_optional(net::HttpUtil::ConvertHeadersBackToHTTPResponse(
- response_headers->raw_headers()));
- }
-
- devtools_observer->OnRawResponse(
- devtools_request_id().value(), url_request_->maybe_stored_cookies(),
- std::move(header_array), raw_response_headers,
- IPEndPointToIPAddressSpace(response_info.remote_endpoint),
- response_headers->response_code());
- }
-
if (auto* cookie_observer = GetCookieAccessObserver()) {
std::vector<mojom::CookieOrLineWithAccessResultPtr> reported_cookies;
for (const auto& cookie_line_and_access_result :
@@ -2420,9 +2490,7 @@ void URLLoader::SetRequestCredentials(const GURL& url) {
// aren't used for those requests.
if (!coep_allow_credentials) {
DCHECK(base::FeatureList::IsEnabled(
- features::kCrossOriginEmbedderPolicyCredentialless) ||
- base::FeatureList::IsEnabled(
- features::kCrossOriginEmbedderPolicyCredentiallessOriginTrial));
+ features::kCrossOriginEmbedderPolicyCredentialless));
url_request_->SetLoadFlags(url_request_->load_flags() |
net::LOAD_BYPASS_CACHE);
}
@@ -2449,9 +2517,7 @@ bool URLLoader::CoepAllowCredentials(const GURL& url) {
if (coep_policy != mojom::CrossOriginEmbedderPolicyValue::kCredentialless)
return true;
DCHECK(base::FeatureList::IsEnabled(
- features::kCrossOriginEmbedderPolicyCredentialless) ||
- base::FeatureList::IsEnabled(
- features::kCrossOriginEmbedderPolicyCredentiallessOriginTrial));
+ features::kCrossOriginEmbedderPolicyCredentialless));
url::Origin request_origin = url::Origin::Create(url);
url::Origin request_initiator =
diff --git a/chromium/services/network/url_loader.h b/chromium/services/network/url_loader.h
index f40ab2d8823..fcc47a2389c 100644
--- a/chromium/services/network/url_loader.h
+++ b/chromium/services/network/url_loader.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/unguessable_token.h"
@@ -24,7 +25,6 @@
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/load_states.h"
#include "net/base/network_delegate.h"
-#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/keepalive_statistics_recorder.h"
@@ -102,7 +102,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
kMaxValue = kVia,
};
- using DeleteCallback = base::OnceCallback<void(mojom::URLLoader* loader)>;
+ using DeleteCallback = base::OnceCallback<void(URLLoader* loader)>;
// Holds a sync and async implementation of URLLoaderClient. The sync
// implementation can be used if present to avoid posting a task to call back
@@ -232,7 +232,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
void ContinueWithoutCertificate() override;
void CancelRequest() override;
- net::LoadState GetLoadStateForTesting() const;
+ net::LoadState GetLoadState() const;
+ net::UploadProgress GetUploadProgress() const;
int32_t GetProcessId() const;
uint32_t GetResourceType() const;
@@ -287,12 +288,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
public:
explicit UnownedPointer(URLLoader* pointer) : pointer_(pointer) {}
+ UnownedPointer(const UnownedPointer&) = delete;
+ UnownedPointer& operator=(const UnownedPointer&) = delete;
+
URLLoader* get() const { return pointer_; }
private:
- URLLoader* const pointer_;
-
- DISALLOW_COPY_AND_ASSIGN(UnownedPointer);
+ const raw_ptr<URLLoader> pointer_;
};
class FileOpenerForUpload;
@@ -367,6 +369,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
void SetRawResponseHeaders(scoped_refptr<const net::HttpResponseHeaders>);
void NotifyEarlyResponse(scoped_refptr<const net::HttpResponseHeaders>);
void SetRawRequestHeadersAndNotify(net::HttpRawRequestHeaders);
+ void DispatchOnRawRequest(
+ std::vector<network::mojom::HttpRawHeaderPairPtr> headers);
+ bool DispatchOnRawResponse();
void SendUploadProgress(const net::UploadProgress& progress);
void OnUploadProgressACK();
void OnSSLCertificateErrorResponse(const net::SSLInfo& ssl_info,
@@ -414,14 +419,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// net::URLRequest.
bool ShouldForceIgnoreTopFramePartyForCookies() const;
+ // Returns the client security state that applies to the current request.
+ // May return nullptr.
+ const mojom::ClientSecurityState* GetClientSecurityState() const;
+
// Applies Private Network Access checks to the current request.
//
- // `resource_address_space` specifies the IP address space of the remote
- // endpoint.
- //
// Helper for `OnConnected()`.
PrivateNetworkAccessCheckResult PrivateNetworkAccessCheck(
- mojom::IPAddressSpace resource_address_space) const;
+ const net::TransportInfo& info);
mojom::DevToolsObserver* GetDevToolsObserver() const;
mojom::CookieAccessObserver* GetCookieAccessObserver() const;
@@ -437,13 +443,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// send or store credentials for no-cors cross-origin request.
bool CoepAllowCredentials(const GURL& url);
- net::URLRequestContext* url_request_context_;
+ raw_ptr<net::URLRequestContext> url_request_context_;
// |url_loader_factory_| is guaranteed to outlive URLLoader, so it is safe to
// store a raw pointer here. It can also be null in tests.
- URLLoaderFactory* const url_loader_factory_;
+ const raw_ptr<URLLoaderFactory> url_loader_factory_;
- mojom::NetworkContextClient* network_context_client_;
+ raw_ptr<mojom::NetworkContextClient> network_context_client_;
DeleteCallback delete_callback_;
int32_t options_;
@@ -454,9 +460,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// URLLoaderFactory is guaranteed to outlive URLLoader, so it is safe to
// store a raw pointer to mojom::URLLoaderFactoryParams.
- const mojom::URLLoaderFactoryParams* const factory_params_;
+ const raw_ptr<const mojom::URLLoaderFactoryParams> factory_params_;
// This also belongs to URLLoaderFactory and outlives this loader.
- mojom::CrossOriginEmbedderPolicyReporter* const coep_reporter_;
+ const raw_ptr<mojom::CrossOriginEmbedderPolicyReporter> coep_reporter_;
const uint32_t request_id_;
const int keepalive_request_size_;
@@ -498,7 +504,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
resource_scheduler_request_handle_;
bool enable_reporting_raw_headers_ = false;
- net::HttpRawRequestHeaders raw_request_headers_;
+ bool seen_raw_request_headers_ = false;
scoped_refptr<const net::HttpResponseHeaders> raw_response_headers_;
std::unique_ptr<UploadProgressTracker> upload_progress_tracker_;
@@ -561,12 +567,18 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
mojom::IPAddressSpace target_ip_address_space_ =
mojom::IPAddressSpace::kUnknown;
+ // The resource's address space, as computed using the |net::TransportInfo|
+ // argument to the |OnConnected()| callback. This info is only available then,
+ // so the computation result is stored for later use in this member.
+ mojom::IPAddressSpace resource_ip_address_space_ =
+ mojom::IPAddressSpace::kUnknown;
+
mojo::Remote<mojom::TrustedHeaderClient> header_client_;
std::unique_ptr<FileOpenerForUpload> file_opener_for_upload_;
// Will only be set for requests that have |obey_origin_policy| set.
- mojom::OriginPolicyManager* origin_policy_manager_ = nullptr;
+ raw_ptr<mojom::OriginPolicyManager> origin_policy_manager_ = nullptr;
// If the request is configured for Trust Tokens
// (https://github.com/WICG/trust-token-api) protocol operations, annotates
@@ -615,6 +627,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// Even if this is false but there is a QUIC/H2 stream, the upload is allowed.
const bool allow_http1_for_streaming_upload_;
+ bool emitted_devtools_raw_request_ = false;
+ bool emitted_devtools_raw_response_ = false;
+
mojo::Remote<mojom::AcceptCHFrameObserver> accept_ch_frame_observer_;
base::WeakPtrFactory<URLLoader> weak_ptr_factory_{this};
diff --git a/chromium/services/network/url_loader_factory.cc b/chromium/services/network/url_loader_factory.cc
index 33ba874909b..c090a148f1c 100644
--- a/chromium/services/network/url_loader_factory.cc
+++ b/chromium/services/network/url_loader_factory.cc
@@ -20,6 +20,7 @@
#include "services/network/cors/cors_url_loader_factory.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/load_info_util.h"
#include "services/network/public/cpp/resource_request.h"
@@ -41,6 +42,27 @@ namespace {
// The interval to send load updates.
constexpr auto kUpdateLoadStatesInterval = base::Milliseconds(250);
+bool LoadInfoIsMoreInteresting(uint32_t a_load_state,
+ uint64_t a_upload_size,
+ uint32_t b_load_state,
+ uint64_t b_upload_size) {
+ // Set |*_uploading_size| to be the size of the corresponding upload body if
+ // it's currently being uploaded.
+
+ uint64_t a_uploading_size = 0;
+ if (a_load_state == net::LOAD_STATE_SENDING_REQUEST)
+ a_uploading_size = a_upload_size;
+
+ uint64_t b_uploading_size = 0;
+ if (b_load_state == net::LOAD_STATE_SENDING_REQUEST)
+ b_uploading_size = b_upload_size;
+
+ if (a_uploading_size != b_uploading_size)
+ return a_uploading_size > b_uploading_size;
+
+ return a_load_state > b_load_state;
+}
+
} // namespace
constexpr int URLLoaderFactory::kMaxKeepaliveConnections;
@@ -267,7 +289,7 @@ void URLLoaderFactory::CreateLoaderAndStartWithSyncClient(
std::move(url_loader_network_observer), std::move(devtools_observer),
std::move(accept_ch_frame_observer));
- cors_url_loader_factory_->OnLoaderCreated(std::move(loader));
+ cors_url_loader_factory_->OnURLLoaderCreated(std::move(loader));
}
mojom::DevToolsObserver* URLLoaderFactory::GetDevToolsObserver() const {
@@ -314,15 +336,29 @@ void URLLoaderFactory::UpdateLoadInfo() {
mojom::LoadInfoPtr most_interesting;
URLLoader* most_interesting_url_loader = nullptr;
- for (auto* request : *context_->url_request_context()->url_requests()) {
- auto* loader = URLLoader::ForRequest(*request);
- if (!loader || loader->url_loader_factory() != this)
- continue;
- mojom::LoadInfoPtr load_info = loader->CreateLoadInfo();
- if (!most_interesting ||
- LoadInfoIsMoreInteresting(*load_info, *most_interesting)) {
- most_interesting = std::move(load_info);
- most_interesting_url_loader = loader;
+ SCOPED_UMA_HISTOGRAM_TIMER("NetworkService.URLLoaderFactory.UpdateLoadInfo");
+
+ if (base::FeatureList::IsEnabled(features::kOptimizeUpdateLoadInfo)) {
+ for (auto& loader : cors_url_loader_factory_->url_loaders()) {
+ if (!most_interesting ||
+ LoadInfoIsMoreInteresting(
+ loader->GetLoadState(), loader->GetUploadProgress().size(),
+ most_interesting->load_state, most_interesting->upload_size)) {
+ most_interesting = loader->CreateLoadInfo();
+ most_interesting_url_loader = loader.get();
+ }
+ }
+ } else {
+ for (auto* request : *context_->url_request_context()->url_requests()) {
+ auto* loader = URLLoader::ForRequest(*request);
+ if (!loader || loader->url_loader_factory() != this)
+ continue;
+ mojom::LoadInfoPtr load_info = loader->CreateLoadInfo();
+ if (!most_interesting ||
+ LoadInfoIsMoreInteresting(*load_info, *most_interesting)) {
+ most_interesting = std::move(load_info);
+ most_interesting_url_loader = loader;
+ }
}
}
diff --git a/chromium/services/network/url_loader_factory.h b/chromium/services/network/url_loader_factory.h
index bf5b490fbb2..28ae1d8f8d0 100644
--- a/chromium/services/network/url_loader_factory.h
+++ b/chromium/services/network/url_loader_factory.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_NETWORK_URL_LOADER_FACTORY_H_
#define SERVICES_NETWORK_URL_LOADER_FACTORY_H_
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -103,13 +103,13 @@ class URLLoaderFactory : public mojom::URLLoaderFactory {
void UpdateLoadInfo();
// The NetworkContext that indirectly owns |this|.
- NetworkContext* const context_;
+ const raw_ptr<NetworkContext> context_;
mojom::URLLoaderFactoryParamsPtr params_;
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client_;
mojo::Remote<mojom::TrustedURLLoaderHeaderClient> header_client_;
// |cors_url_loader_factory_| owns this.
- cors::CorsURLLoaderFactory* cors_url_loader_factory_;
+ raw_ptr<cors::CorsURLLoaderFactory> cors_url_loader_factory_;
mojo::Remote<mojom::CookieAccessObserver> cookie_observer_;
mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
diff --git a/chromium/services/network/url_loader_unittest.cc b/chromium/services/network/url_loader_unittest.cc
index 17cfbf62870..9876350ed59 100644
--- a/chromium/services/network/url_loader_unittest.cc
+++ b/chromium/services/network/url_loader_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/raw_ptr.h"
#include "stdint.h"
#include <limits>
@@ -18,7 +19,6 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/statistics_recorder.h"
@@ -112,6 +112,7 @@
#if defined(OS_ANDROID)
#include "base/android/radio_utils.h"
+#include "net/android/radio_activity_tracker.h"
#include "services/network/radio_monitor_android.h"
#endif
@@ -133,7 +134,7 @@ URLLoader::DeleteCallback DeleteLoaderCallback(
std::unique_ptr<URLLoader>* url_loader) {
return base::BindOnce(
[](base::RunLoop* run_loop, std::unique_ptr<URLLoader>* url_loader,
- mojom::URLLoader* url_loader_ptr) {
+ URLLoader* url_loader_ptr) {
DCHECK_EQ(url_loader->get(), url_loader_ptr);
url_loader->reset();
run_loop->Quit();
@@ -146,7 +147,7 @@ URLLoader::DeleteCallback DeleteLoaderCallback(
// this method, as URLLoaders don't expect to be alive after they invoke their
// delete callback.
URLLoader::DeleteCallback NeverInvokedDeleteLoaderCallback() {
- return base::BindOnce([](mojom::URLLoader* /* loader*/) { NOTREACHED(); });
+ return base::BindOnce([](URLLoader* /* loader*/) { NOTREACHED(); });
}
constexpr char kBodyReadFromNetBeforePausedHistogram[] =
@@ -385,7 +386,7 @@ class URLRequestSimulatedCacheJob : public net::URLRequestJob {
private:
void StartAsync() { NotifyHeadersComplete(); }
- scoped_refptr<net::IOBuffer>* simulated_cache_dest_;
+ raw_ptr<scoped_refptr<net::IOBuffer>> simulated_cache_dest_;
bool use_text_plain_;
base::WeakPtrFactory<URLRequestSimulatedCacheJob> weak_factory_{this};
};
@@ -398,6 +399,10 @@ class SimulatedCacheInterceptor : public net::URLRequestInterceptor {
: simulated_cache_dest_(simulated_cache_dest),
use_text_plain_(use_text_plain) {}
+ SimulatedCacheInterceptor(const SimulatedCacheInterceptor&) = delete;
+ SimulatedCacheInterceptor& operator=(const SimulatedCacheInterceptor&) =
+ delete;
+
std::unique_ptr<net::URLRequestJob> MaybeInterceptRequest(
net::URLRequest* request) const override {
return std::make_unique<URLRequestSimulatedCacheJob>(
@@ -405,9 +410,8 @@ class SimulatedCacheInterceptor : public net::URLRequestInterceptor {
}
private:
- scoped_refptr<net::IOBuffer>* simulated_cache_dest_;
+ raw_ptr<scoped_refptr<net::IOBuffer>> simulated_cache_dest_;
bool use_text_plain_;
- DISALLOW_COPY_AND_ASSIGN(SimulatedCacheInterceptor);
};
// Fakes the TransportInfo passed to URLRequest::Delegate::OnConnected().
@@ -585,7 +589,7 @@ class URLLoaderTest : public testing::Test {
scoped_feature_list_.InitWithFeatures(
/*enabled_features=*/{features::kAcceptCHFrame,
- features::kRecordRadioWakeupTrigger},
+ net::features::kRecordRadioWakeupTrigger},
/*disabled_features=*/{});
}
~URLLoaderTest() override {
@@ -1011,7 +1015,7 @@ class URLLoaderTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
net::EmbeddedTestServer test_server_;
std::unique_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_;
- net::TestNetworkDelegate*
+ raw_ptr<net::TestNetworkDelegate>
unowned_test_network_delegate_; // owned by |context_|
std::unique_ptr<net::URLRequestContext> context_;
ResourceScheduler resource_scheduler_;
@@ -1028,7 +1032,7 @@ class URLLoaderTest : public testing::Test {
bool expect_redirect_ = false;
mojom::ClientSecurityStatePtr factory_client_security_state_;
mojom::ClientSecurityStatePtr request_client_security_state_;
- MockDevToolsObserver* devtools_observer_ = nullptr;
+ raw_ptr<MockDevToolsObserver> devtools_observer_ = nullptr;
scoped_refptr<ResourceRequestBody> request_body_;
net::HttpRequestHeaders additional_headers_;
mojom::IPAddressSpace target_ip_address_space_ =
@@ -1044,7 +1048,7 @@ class URLLoaderTest : public testing::Test {
const cors::OriginAccessList kEmptyOriginAccessList;
- MockAcceptCHFrameObserver* accept_ch_frame_observer_ = nullptr;
+ raw_ptr<MockAcceptCHFrameObserver> accept_ch_frame_observer_ = nullptr;
};
class URLLoaderMockSocketTest : public URLLoaderTest {
@@ -1666,6 +1670,9 @@ struct URLLoaderFakeTransportInfoTestParams {
// The address space of the endpoint serving the request.
mojom::IPAddressSpace endpoint_address_space;
+ // The type of transport to set in `TransportInfo`.
+ net::TransportType transport_type;
+
// The expected request result.
int expected_result;
};
@@ -1675,6 +1682,8 @@ 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
+ << ", transport_type: "
+ << net::TransportTypeToString(params.transport_type)
<< ", expected_result: "
<< net::ErrorToString(params.expected_result) << " }";
}
@@ -1703,9 +1712,10 @@ class URLLoaderFakeTransportInfoTest
}
// 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),
- "");
+ static net::TransportInfo FakeTransportInfo(
+ const URLLoaderFakeTransportInfoTestParams& params) {
+ return net::TransportInfo(params.transport_type,
+ FakeEndpoint(params.endpoint_address_space), "");
}
};
@@ -1724,7 +1734,7 @@ TEST_P(URLLoaderFakeTransportInfoTest, PrivateNetworkRequestLoadsCorrectly) {
net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
url, std::make_unique<FakeTransportInfoInterceptor>(
- FakeTransportInfo(params.endpoint_address_space)));
+ FakeTransportInfo(params)));
// Despite its name, IsError(OK) asserts that the matched value is OK.
EXPECT_THAT(Load(url), IsError(params.expected_result));
@@ -1742,84 +1752,125 @@ constexpr URLLoaderFakeTransportInfoTestParams
{
mojom::IPAddressSpace::kUnknown,
mojom::IPAddressSpace::kUnknown,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kUnknown,
mojom::IPAddressSpace::kPublic,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kUnknown,
mojom::IPAddressSpace::kPrivate,
+ net::TransportType::kDirect,
net::ERR_FAILED,
},
{
mojom::IPAddressSpace::kUnknown,
mojom::IPAddressSpace::kLocal,
+ net::TransportType::kDirect,
net::ERR_FAILED,
},
// Client: kPublic
{
mojom::IPAddressSpace::kPublic,
mojom::IPAddressSpace::kUnknown,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kPublic,
mojom::IPAddressSpace::kPublic,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kPublic,
mojom::IPAddressSpace::kPrivate,
+ net::TransportType::kDirect,
net::ERR_FAILED,
},
{
mojom::IPAddressSpace::kPublic,
mojom::IPAddressSpace::kLocal,
+ net::TransportType::kDirect,
net::ERR_FAILED,
},
// Client: kPrivate
{
mojom::IPAddressSpace::kPrivate,
mojom::IPAddressSpace::kUnknown,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kPrivate,
mojom::IPAddressSpace::kPublic,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kPrivate,
mojom::IPAddressSpace::kPrivate,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kPrivate,
mojom::IPAddressSpace::kLocal,
+ net::TransportType::kDirect,
net::ERR_FAILED,
},
// Client: kLocal
{
mojom::IPAddressSpace::kLocal,
mojom::IPAddressSpace::kUnknown,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kLocal,
mojom::IPAddressSpace::kPublic,
+ net::TransportType::kDirect,
net::OK,
},
{
mojom::IPAddressSpace::kLocal,
mojom::IPAddressSpace::kPrivate,
+ net::TransportType::kDirect,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kLocal,
+ mojom::IPAddressSpace::kLocal,
+ net::TransportType::kDirect,
net::OK,
},
+ // TransportType: kProxied
{
+ mojom::IPAddressSpace::kUnknown,
mojom::IPAddressSpace::kLocal,
+ net::TransportType::kProxied,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPublic,
mojom::IPAddressSpace::kLocal,
+ net::TransportType::kProxied,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPublic,
+ mojom::IPAddressSpace::kPrivate,
+ net::TransportType::kProxied,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPrivate,
+ mojom::IPAddressSpace::kLocal,
+ net::TransportType::kProxied,
net::OK,
},
};
@@ -3631,8 +3682,7 @@ TEST_F(URLLoaderTest, ResourceSchedulerIntegration) {
for (const auto& pair : loaders) {
URLLoader* loader = pair.first.get();
ASSERT_NE(loader, nullptr);
- EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_RESPONSE,
- loader->GetLoadStateForTesting());
+ EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_RESPONSE, loader->GetLoadState());
}
mojo::PendingRemote<mojom::URLLoader> loader_remote;
@@ -3653,15 +3703,14 @@ TEST_F(URLLoaderTest, ResourceSchedulerIntegration) {
base::RunLoop().RunUntilIdle();
// Make sure that the ResourceScheduler throttles this request.
- EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_DELEGATE,
- loader->GetLoadStateForTesting());
+ EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_DELEGATE, loader->GetLoadState());
loader->SetPriority(net::HIGHEST, 0 /* intra_priority_value */);
base::RunLoop().RunUntilIdle();
// Make sure that the ResourceScheduler stops throtting.
EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET,
- loader->GetLoadStateForTesting());
+ loader->GetLoadState());
}
// This tests that case where a read pipe is closed while there's a post task to
@@ -3948,7 +3997,7 @@ class ClientCertAuthObserver : public TestURLLoaderNetworkObserver {
std::string provider_name_;
std::vector<uint16_t> algorithm_preferences_;
int on_certificate_requested_counter_ = 0;
- mojo::Remote<mojom::URLLoader>* url_loader_remote_ = nullptr;
+ raw_ptr<mojo::Remote<mojom::URLLoader>> url_loader_remote_ = nullptr;
};
TEST_F(URLLoaderTest, SetAuth) {
@@ -4287,6 +4336,9 @@ class TestSSLPrivateKey : public net::SSLPrivateKey {
explicit TestSSLPrivateKey(scoped_refptr<net::SSLPrivateKey> key)
: key_(std::move(key)) {}
+ TestSSLPrivateKey(const TestSSLPrivateKey&) = delete;
+ TestSSLPrivateKey& operator=(const TestSSLPrivateKey&) = delete;
+
void set_fail_signing(bool fail_signing) { fail_signing_ = fail_signing; }
int sign_count() const { return sign_count_; }
@@ -4314,8 +4366,6 @@ class TestSSLPrivateKey : public net::SSLPrivateKey {
scoped_refptr<net::SSLPrivateKey> key_;
bool fail_signing_ = false;
int sign_count_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(TestSSLPrivateKey);
};
#if !defined(OS_IOS)
@@ -6294,7 +6344,7 @@ class MockTrustTokenRequestHelper : public TrustTokenRequestHelper {
SyncOrAsync operation_synchrony_;
- bool* begin_done_flag_;
+ raw_ptr<bool> begin_done_flag_;
};
class NoopTrustTokenKeyCommitmentGetter : public TrustTokenKeyCommitmentGetter {
@@ -7278,43 +7328,78 @@ TEST_F(URLLoaderFakeTransportInfoTest, AcceptCHFrameIgnoreMalformed) {
#if defined(OS_ANDROID)
+namespace {
+
+void CheckRadioWakeupTriggerHistograms(base::HistogramTester& histograms,
+ size_t expected_count) {
+ histograms.ExpectTotalCount(
+ kUmaNamePossibleWakeupTriggerURLLoaderRequestDestination, expected_count);
+ histograms.ExpectTotalCount(
+ kUmaNamePossibleWakeupTriggerURLLoaderRequestPriority, expected_count);
+ histograms.ExpectTotalCount(
+ kUmaNamePossibleWakeupTriggerURLLoaderRequestIsPrefetch, expected_count);
+ histograms.ExpectTotalCount(
+ kUmaNamePossibleWakeupTriggerURLLoaderAnnotationId, expected_count);
+}
+
+} // namespace
+
TEST_F(URLLoaderTest, RecordRadioWakeupTrigger_Record) {
base::HistogramTester histograms;
- RadioMonitorAndroid::GetInstance().OverrideRadioActivityForTesting(
- base::android::RadioDataActivity::kDormant);
- RadioMonitorAndroid::GetInstance().OverrideRadioTypeForTesting(
+ net::android::RadioActivityTracker::GetInstance()
+ .OverrideRadioActivityForTesting(
+ base::android::RadioDataActivity::kDormant);
+ net::android::RadioActivityTracker::GetInstance().OverrideRadioTypeForTesting(
base::android::RadioConnectionType::kCell);
LoadAndCompareFile("simple_page.html");
- histograms.ExpectTotalCount(kUmaNamePossibleWakeupTriggerURLLoader, 1);
+ CheckRadioWakeupTriggerHistograms(histograms, /*expected_count=*/1);
}
TEST_F(URLLoaderTest, RecordRadioWakeupTrigger_RadioTypeIsNotCell) {
base::HistogramTester histograms;
- RadioMonitorAndroid::GetInstance().OverrideRadioActivityForTesting(
- base::android::RadioDataActivity::kDormant);
- RadioMonitorAndroid::GetInstance().OverrideRadioTypeForTesting(
+ net::android::RadioActivityTracker::GetInstance()
+ .OverrideRadioActivityForTesting(
+ base::android::RadioDataActivity::kDormant);
+ net::android::RadioActivityTracker::GetInstance().OverrideRadioTypeForTesting(
base::android::RadioConnectionType::kWifi);
LoadAndCompareFile("simple_page.html");
- histograms.ExpectTotalCount(kUmaNamePossibleWakeupTriggerURLLoader, 0);
+ CheckRadioWakeupTriggerHistograms(histograms, /*expected_count=*/0);
}
TEST_F(URLLoaderTest, RecordRadioWakeupTrigger_RadioActivityIsNotDormant) {
base::HistogramTester histograms;
- RadioMonitorAndroid::GetInstance().OverrideRadioActivityForTesting(
- base::android::RadioDataActivity::kInOut);
- RadioMonitorAndroid::GetInstance().OverrideRadioTypeForTesting(
+ net::android::RadioActivityTracker::GetInstance()
+ .OverrideRadioActivityForTesting(
+ base::android::RadioDataActivity::kInOut);
+ net::android::RadioActivityTracker::GetInstance().OverrideRadioTypeForTesting(
+ base::android::RadioConnectionType::kCell);
+
+ LoadAndCompareFile("simple_page.html");
+
+ CheckRadioWakeupTriggerHistograms(histograms, /*expected_count=*/0);
+}
+
+TEST_F(URLLoaderTest, RecordRadioWakeupTrigger_IntervalTooShort) {
+ base::HistogramTester histograms;
+
+ net::android::RadioActivityTracker::GetInstance()
+ .OverrideRadioActivityForTesting(
+ base::android::RadioDataActivity::kDormant);
+ net::android::RadioActivityTracker::GetInstance().OverrideRadioTypeForTesting(
base::android::RadioConnectionType::kCell);
+ net::android::RadioActivityTracker::GetInstance()
+ .OverrideLastCheckTimeForTesting(base::TimeTicks::Now());
LoadAndCompareFile("simple_page.html");
- histograms.ExpectTotalCount(kUmaNamePossibleWakeupTriggerURLLoader, 0);
+ CheckRadioWakeupTriggerHistograms(histograms, /*expected_count=*/0);
}
#endif // defined(OS_ANDROID)
diff --git a/chromium/services/network/url_request_context_builder_mojo.h b/chromium/services/network/url_request_context_builder_mojo.h
index 3f3a1abcf5c..bf3b5cbff56 100644
--- a/chromium/services/network/url_request_context_builder_mojo.h
+++ b/chromium/services/network/url_request_context_builder_mojo.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/web_bundle/web_bundle_manager_unittest.cc b/chromium/services/network/web_bundle/web_bundle_manager_unittest.cc
index b2ca3174836..222b1c99f6c 100644
--- a/chromium/services/network/web_bundle/web_bundle_manager_unittest.cc
+++ b/chromium/services/network/web_bundle/web_bundle_manager_unittest.cc
@@ -7,7 +7,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/unguessable_token.h"
-#include "components/web_package/test_support/web_bundle_builder.h"
+#include "components/web_package/web_bundle_builder.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -35,8 +35,7 @@ const int32_t process_id1 = 100;
const int32_t process_id2 = 200;
std::string CreateSmallBundleString() {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "200"}, {"content-type", "text/plain"}},
"body");
@@ -398,8 +397,7 @@ TEST_F(WebBundleManagerTest, MemoryQuota_QuotaErrorWhileReadingBody) {
// Create a not small size bundle to trigger the quota error while reading the
// body of the subresource.
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "200"}, {"content-type", "text/plain"}},
std::string(10000, 'X'));
diff --git a/chromium/services/network/web_bundle/web_bundle_url_loader_factory.cc b/chromium/services/network/web_bundle/web_bundle_url_loader_factory.cc
index d72379f0da5..c3cf4ac79b9 100644
--- a/chromium/services/network/web_bundle/web_bundle_url_loader_factory.cc
+++ b/chromium/services/network/web_bundle/web_bundle_url_loader_factory.cc
@@ -711,6 +711,22 @@ void WebBundleURLLoaderFactory::OnMetadataParsed(
std::move(urls));
}
+ if (metadata_->version == web_package::mojom::BundleFormatVersion::kB1) {
+ web_bundle_handle_->OnWebBundleError(
+ mojom::WebBundleErrorType::kDeprecationWarning,
+ "WebBundle format \"b1\" is deprecated. See migration guide at "
+ "https://bit.ly/3rpDuEX.");
+ }
+ for (auto& it : metadata_->requests) {
+ if (it.first.SchemeIs(url::kUrnScheme)) {
+ web_bundle_handle_->OnWebBundleError(
+ mojom::WebBundleErrorType::kDeprecationWarning,
+ "urn:uuid resource URL in WebBundles is deprecated. See migration "
+ "guide at https://bit.ly/3rpDuEX.");
+ break;
+ }
+ }
+
if (data_completed_)
MaybeReportLoadResult(SubresourceWebBundleLoadResult::kSuccess);
for (auto loader : pending_loaders_)
diff --git a/chromium/services/network/web_bundle/web_bundle_url_loader_factory.h b/chromium/services/network/web_bundle/web_bundle_url_loader_factory.h
index 8623879b3ba..080d6c76328 100644
--- a/chromium/services/network/web_bundle/web_bundle_url_loader_factory.h
+++ b/chromium/services/network/web_bundle/web_bundle_url_loader_factory.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/web_package/mojom/web_bundle_parser.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -112,7 +113,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebBundleURLLoaderFactory {
mojo::Remote<mojom::DevToolsObserver> devtools_observer_;
absl::optional<std::string> devtools_request_id_;
const CrossOriginEmbedderPolicy cross_origin_embedder_policy_;
- mojom::CrossOriginEmbedderPolicyReporter* coep_reporter_;
+ raw_ptr<mojom::CrossOriginEmbedderPolicyReporter> coep_reporter_;
std::unique_ptr<BundleDataSource> source_;
mojo::Remote<web_package::mojom::WebBundleParser> parser_;
web_package::mojom::BundleMetadataPtr metadata_;
diff --git a/chromium/services/network/web_bundle/web_bundle_url_loader_factory_unittest.cc b/chromium/services/network/web_bundle/web_bundle_url_loader_factory_unittest.cc
index 3598a87f6e9..e3bb7ecfad4 100644
--- a/chromium/services/network/web_bundle/web_bundle_url_loader_factory_unittest.cc
+++ b/chromium/services/network/web_bundle/web_bundle_url_loader_factory_unittest.cc
@@ -7,7 +7,7 @@
#include "base/callback_helpers.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
-#include "components/web_package/test_support/web_bundle_builder.h"
+#include "components/web_package/web_bundle_builder.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -30,6 +30,7 @@ const char kBundleRequestId[] = "bundle-devtools-request-id";
const char kResourceUrl[] = "https://example.com/";
const char kResourceUrl2[] = "https://example.com/another";
const char kResourceUrl3[] = "https://example.com/yetanother";
+const char kUrnUuidUrl[] = "urn:uuid:e9448fc0-3fef-4568-a910-55448df1b863";
const char kResourceRequestId[] = "resource-1-devtools-request-id";
const char kResourceRequestId2[] = "resource-2-devtools-request-id";
const char kResourceRequestId3[] = "resource-3-devtools-request-id";
@@ -45,8 +46,7 @@ using ::testing::Optional;
using ::testing::Pointee;
std::vector<uint8_t> CreateSmallBundle() {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "200"}, {"content-type", "text/plain"}},
"body");
@@ -54,8 +54,7 @@ std::vector<uint8_t> CreateSmallBundle() {
}
std::vector<uint8_t> CreateLargeBundle() {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "200"}, {"content-type", "text/plain"}},
"body");
@@ -69,8 +68,8 @@ std::vector<uint8_t> CreateLargeBundle() {
}
std::vector<uint8_t> CreateCrossOriginBundle() {
- web_package::test::WebBundleBuilder builder(kCrossOriginJsonUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kCrossOriginJsonUrl,
+ "" /* manifest_url */);
builder.AddExchange(
kCrossOriginJsonUrl,
{{":status", "200"}, {"content-type", "application/json"}},
@@ -81,6 +80,23 @@ std::vector<uint8_t> CreateCrossOriginBundle() {
return builder.CreateBundle();
}
+std::vector<uint8_t> CreateB1Bundle() {
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */,
+ web_package::BundleVersion::kB1);
+ builder.AddExchange(kResourceUrl,
+ {{":status", "200"}, {"content-type", "text/plain"}},
+ "body");
+ return builder.CreateBundle();
+}
+
+std::vector<uint8_t> CreateBundleWithUrnUuidResource() {
+ web_package::WebBundleBuilder builder(kUrnUuidUrl, "" /* manifest_url */);
+ builder.AddExchange(kUrnUuidUrl,
+ {{":status", "200"}, {"content-type", "text/plain"}},
+ "body");
+ return builder.CreateBundle();
+}
+
class TestWebBundleHandle : public mojom::WebBundleHandle {
public:
explicit TestWebBundleHandle(
@@ -304,8 +320,7 @@ TEST_F(WebBundleURLLoaderFactoryTest, MetadataParseError) {
}
TEST_F(WebBundleURLLoaderFactoryTest, ResponseParseError) {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */);
// An invalid response.
builder.AddExchange(kResourceUrl, {{":status", "0"}}, "body");
WriteBundle(builder.CreateBundle());
@@ -357,8 +372,7 @@ TEST_F(WebBundleURLLoaderFactoryTest, ResourceNotFoundInBundle) {
}
TEST_F(WebBundleURLLoaderFactoryTest, RedirectResponseIsNotAllowed) {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
+ web_package::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "301"}, {"location", kResourceUrl2}}, "");
builder.AddExchange(kResourceUrl2,
@@ -540,4 +554,50 @@ TEST_F(WebBundleURLLoaderFactoryTest, WrongBundleURL) {
"WebBundleURLLoaderFactory: Bundle URL does not match"));
}
+TEST_F(WebBundleURLLoaderFactoryTest, DeprecatedBundleVersion) {
+ WriteBundle(CreateB1Bundle());
+ FinishWritingBundle();
+
+ EXPECT_CALL(*devtools_observer_,
+ OnSubresourceWebBundleMetadata(kBundleRequestId,
+ ElementsAre(GURL(kResourceUrl))));
+ EXPECT_CALL(*devtools_observer_,
+ OnSubresourceWebBundleInnerResponse(
+ kResourceRequestId, GURL(kResourceUrl),
+ Optional(std::string(kBundleRequestId))));
+
+ auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
+ request.client->RunUntilComplete();
+
+ EXPECT_EQ(net::OK, request.client->completion_status().error_code);
+ EXPECT_EQ(last_bundle_error()->first,
+ mojom::WebBundleErrorType::kDeprecationWarning);
+ EXPECT_EQ(last_bundle_error()->second,
+ "WebBundle format \"b1\" is deprecated. See migration guide at "
+ "https://bit.ly/3rpDuEX.");
+}
+
+TEST_F(WebBundleURLLoaderFactoryTest, DeprecatedUrnUuidResource) {
+ WriteBundle(CreateBundleWithUrnUuidResource());
+ FinishWritingBundle();
+
+ EXPECT_CALL(*devtools_observer_,
+ OnSubresourceWebBundleMetadata(kBundleRequestId,
+ ElementsAre(GURL(kUrnUuidUrl))));
+ EXPECT_CALL(*devtools_observer_,
+ OnSubresourceWebBundleInnerResponse(
+ kResourceRequestId, GURL(kUrnUuidUrl),
+ Optional(std::string(kBundleRequestId))));
+
+ auto request = StartRequest(GURL(kUrnUuidUrl), kResourceRequestId);
+ request.client->RunUntilComplete();
+
+ EXPECT_EQ(net::OK, request.client->completion_status().error_code);
+ EXPECT_EQ(last_bundle_error()->first,
+ mojom::WebBundleErrorType::kDeprecationWarning);
+ EXPECT_EQ(last_bundle_error()->second,
+ "urn:uuid resource URL in WebBundles is deprecated. See migration "
+ "guide at https://bit.ly/3rpDuEX.");
+}
+
} // namespace network
diff --git a/chromium/services/network/web_transport.cc b/chromium/services/network/web_transport.cc
index 679aad19149..fcb487fc397 100644
--- a/chromium/services/network/web_transport.cc
+++ b/chromium/services/network/web_transport.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/strings/string_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -28,7 +29,7 @@ net::WebTransportParameters CreateParameters(
const std::vector<mojom::WebTransportCertificateFingerprintPtr>&
fingerprints) {
net::WebTransportParameters params;
- params.enable_quic_transport = true;
+ params.enable_quic_transport = false;
params.enable_web_transport_http3 = true;
for (const auto& fingerprint : fingerprints) {
@@ -173,7 +174,7 @@ class WebTransport::Stream final {
}
~Stream() {
- auto* stream = incoming_ ? incoming_ : outgoing_;
+ auto* stream = incoming_ ? incoming_.get() : outgoing_.get();
if (!stream) {
return;
}
@@ -352,14 +353,14 @@ class WebTransport::Stream final {
base::BindOnce(&Stream::Dispose, weak_factory_.GetWeakPtr()));
}
- WebTransport* const transport_; // outlives |this|.
+ const raw_ptr<WebTransport> transport_; // outlives |this|.
const uint32_t id_;
// |outgoing_| and |incoming_| point to the same stream when this is a
// bidirectional stream. They are owned by |transport_| (via
// quic::QuicSession), and the properties will be null-set when the streams
// are gone (via StreamVisitor).
- quic::WebTransportStream* outgoing_ = nullptr;
- quic::WebTransportStream* incoming_ = nullptr;
+ raw_ptr<quic::WebTransportStream> outgoing_ = nullptr;
+ raw_ptr<quic::WebTransportStream> incoming_ = nullptr;
mojo::ScopedDataPipeConsumerHandle readable_; // for |outgoing|
mojo::ScopedDataPipeProducerHandle writable_; // for |incoming|
diff --git a/chromium/services/network/web_transport.h b/chromium/services/network/web_transport.h
index 62cc1b644e3..00d9f561b6b 100644
--- a/chromium/services/network/web_transport.h
+++ b/chromium/services/network/web_transport.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/containers/queue.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -90,7 +90,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebTransport final
void Dispose();
const std::unique_ptr<net::WebTransportClient> transport_;
- NetworkContext* const context_; // outlives |this|.
+ const raw_ptr<NetworkContext> context_; // outlives |this|.
std::map<uint32_t, std::unique_ptr<Stream>> streams_;
diff --git a/chromium/services/network/web_transport_unittest.cc b/chromium/services/network/web_transport_unittest.cc
index 4407ed8765b..efa2012692d 100644
--- a/chromium/services/network/web_transport_unittest.cc
+++ b/chromium/services/network/web_transport_unittest.cc
@@ -296,7 +296,7 @@ class WebTransportTest : public testing::TestWithParam<base::StringPiece> {
network_context_.url_request_context()->set_cert_verifier(&cert_verifier_);
network_context_.url_request_context()->set_host_resolver(&host_resolver_);
- network_context_.url_request_context()->set_net_log(&net_log_);
+ network_context_.url_request_context()->set_net_log(net::NetLog::Get());
auto* quic_context = network_context_.url_request_context()->quic_context();
quic_context->params()->supported_versions.push_back(version_);
quic_context->params()->origins_to_force_quic_on.insert(
@@ -342,7 +342,7 @@ class WebTransportTest : public testing::TestWithParam<base::StringPiece> {
const url::Origin& origin() const { return origin_; }
const NetworkContext& network_context() const { return network_context_; }
NetworkContext& mutable_network_context() { return network_context_; }
- net::RecordingTestNetLog& net_log() { return net_log_; }
+ net::RecordingNetLogObserver& net_log_observer() { return net_log_observer_; }
void RunPendingTasks() {
base::RunLoop run_loop;
@@ -361,7 +361,7 @@ class WebTransportTest : public testing::TestWithParam<base::StringPiece> {
net::MockCertVerifier cert_verifier_;
net::MockHostResolver host_resolver_;
- net::RecordingTestNetLog net_log_;
+ net::RecordingNetLogObserver net_log_observer_;
NetworkContext network_context_;
@@ -574,8 +574,9 @@ TEST_F(WebTransportTest, EchoOnUnidirectionalStreams) {
EXPECT_TRUE(client.has_received_fin_for(incoming_stream_id));
EXPECT_FALSE(client.has_seen_mojo_connection_error());
- std::vector<net::NetLogEntry> resets_sent = net_log().GetEntriesWithType(
- net::NetLogEventType::QUIC_SESSION_RST_STREAM_FRAME_SENT);
+ std::vector<net::NetLogEntry> resets_sent =
+ net_log_observer().GetEntriesWithType(
+ net::NetLogEventType::QUIC_SESSION_RST_STREAM_FRAME_SENT);
EXPECT_EQ(0u, resets_sent.size());
}
diff --git a/chromium/services/network/websocket.cc b/chromium/services/network/websocket.cc
index 74f58b77eb3..4053a4d9169 100644
--- a/chromium/services/network/websocket.cc
+++ b/chromium/services/network/websocket.cc
@@ -12,15 +12,18 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/check.h"
+#include "base/check_op.h"
#include "base/feature_list.h"
+#include "base/ignore_result.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_conversions.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "net/base/auth.h"
@@ -172,7 +175,7 @@ class WebSocket::WebSocketEventHandler final
absl::optional<net::AuthCredentials>* credentials) override;
private:
- WebSocket* const impl_;
+ const raw_ptr<WebSocket> impl_;
};
WebSocket::WebSocketEventHandler::WebSocketEventHandler(WebSocket* impl)
@@ -273,7 +276,7 @@ void WebSocket::WebSocketEventHandler::OnDataFrame(
if (payload.size() > 0) {
impl_->pending_data_frames_.push(payload);
}
- impl_->SendPendingDataFrames();
+ impl_->SendPendingDataFrames(InterruptionReason::kNone);
}
void WebSocket::WebSocketEventHandler::OnSendDataFrameDone() {
@@ -465,7 +468,7 @@ WebSocket::WebSocket(
}
handshake_client_.set_disconnect_handler(base::BindOnce(
&WebSocket::OnConnectionError, base::Unretained(this), FROM_HERE));
- if (delay_ > base::TimeDelta()) {
+ if (delay_.is_positive()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&WebSocket::AddChannel, weak_ptr_factory_.GetWeakPtr(),
@@ -511,8 +514,9 @@ void WebSocket::SendMessage(mojom::WebSocketMessageType type,
// Safe if ReadAndSendFromDataPipe() deletes |this| because this method is
// only called from mojo.
- if (!blocked_on_websocket_channel_)
- ReadAndSendFromDataPipe();
+ if (!blocked_on_websocket_channel_) {
+ ReadAndSendFromDataPipe(InterruptionReason::kNone);
+ }
}
void WebSocket::StartReceiving() {
@@ -645,47 +649,51 @@ void WebSocket::OnWritable(MojoResult result,
OnConnectionError(FROM_HERE);
return;
}
- wait_for_writable_ = false;
- SendPendingDataFrames();
- if (pending_data_frames_.empty()) {
- ignore_result(channel_->ReadFrames());
- }
+ SendPendingDataFrames(InterruptionReason::kMojoPipe);
}
-void WebSocket::SendPendingDataFrames() {
+void WebSocket::SendPendingDataFrames(InterruptionReason resume_reason) {
DVLOG(3) << "WebSocket::SendPendingDataFrames @"
<< reinterpret_cast<void*>(this)
<< ", pending_data_frames_.size=" << pending_data_frames_.size()
- << ", wait_for_writable_?" << wait_for_writable_;
+ << ", incoming_frames_interrupted_="
+ << static_cast<int>(incoming_frames_interrupted_);
- if (wait_for_writable_) {
+ if (incoming_frames_interrupted_ != resume_reason)
return;
+
+ bool resuming_after_interruption = false;
+ if (incoming_frames_interrupted_ != InterruptionReason::kNone) {
+ incoming_frames_interrupted_ = InterruptionReason::kNone;
+ resuming_after_interruption = true;
}
while (!pending_data_frames_.empty()) {
base::span<const char>& data_frame = pending_data_frames_.front();
if (incoming_frame_interceptor_ &&
- !incoming_frame_interceptor_->IsFrameStarted()) {
- // `Intercept` always intercepts sending data per frame. Once intercepted,
- // the intercepteror needs to be notified when the whole frame is sent by
- // calling `FinishFrame`.
+ resume_reason == InterruptionReason::kNone) {
+ // `Intercept` always intercepts sending data per frame.
auto intercept_result = incoming_frame_interceptor_->Intercept(
data_frame.size(), base::BindOnce(&WebSocket::SendPendingDataFrames,
- base::Unretained(this)));
- if (intercept_result == WebSocketInterceptor::kShouldWait)
+ base::Unretained(this),
+ InterruptionReason::kInterceptor));
+ if (intercept_result == WebSocketInterceptor::kShouldWait) {
+ DCHECK_EQ(incoming_frames_interrupted_, InterruptionReason::kNone);
+ incoming_frames_interrupted_ = InterruptionReason::kInterceptor;
return;
+ }
}
SendDataFrame(&data_frame);
if (data_frame.size() > 0) {
// Mojo doesn't have any write buffer so far.
writable_watcher_.ArmOrNotify();
- wait_for_writable_ = true;
+ DCHECK_EQ(incoming_frames_interrupted_, InterruptionReason::kNone);
+ incoming_frames_interrupted_ = InterruptionReason::kMojoPipe;
return;
}
pending_data_frames_.pop();
- if (incoming_frame_interceptor_ &&
- incoming_frame_interceptor_->IsFrameStarted()) {
- incoming_frame_interceptor_->FinishFrame();
- }
+ }
+ if (resuming_after_interruption) {
+ ignore_result(channel_->ReadFrames());
}
}
@@ -729,40 +737,40 @@ void WebSocket::OnReadable(MojoResult result,
OnConnectionError(FROM_HERE);
return;
}
- wait_for_readable_ = false;
-
// Safe if ReadAndSendFromDataPipe() deletes |this| because this method is
// only called from mojo.
- ReadAndSendFromDataPipe();
+ ReadAndSendFromDataPipe(InterruptionReason::kMojoPipe);
}
-void WebSocket::ReadAndSendFromDataPipe() {
- if (wait_for_readable_) {
+void WebSocket::ReadAndSendFromDataPipe(InterruptionReason resume_reason) {
+ if (outgoing_frames_interrupted_ != resume_reason &&
+ outgoing_frames_interrupted_ != InterruptionReason::kNone)
return;
- }
+
+ if (outgoing_frames_interrupted_ != InterruptionReason::kNone)
+ outgoing_frames_interrupted_ = InterruptionReason::kNone;
+
while (!pending_send_data_frames_.empty()) {
DataFrame& data_frame = pending_send_data_frames_.front();
DVLOG(2) << " ConsumePendingDataFrame frame=(" << data_frame.type
<< ", (data_length = " << data_frame.data_length << "))";
if (outgoing_frame_interceptor_ &&
- !outgoing_frame_interceptor_->IsFrameStarted()) {
- // `Intercept` always intercepts reading data per frame. Once intercepted,
- // the intercepteror needs to be notified when the whole frame is read by
- // calling `FinishFrame`.
+ resume_reason == InterruptionReason::kNone) {
+ // `Intercept` always intercepts reading data per frame.
auto intercept_result = outgoing_frame_interceptor_->Intercept(
data_frame.data_length,
base::BindOnce(&WebSocket::ReadAndSendFromDataPipe,
- base::Unretained(this)));
- if (intercept_result == WebSocketInterceptor::kShouldWait)
+ base::Unretained(this),
+ InterruptionReason::kInterceptor));
+ if (intercept_result == WebSocketInterceptor::kShouldWait) {
+ DCHECK_EQ(outgoing_frames_interrupted_, InterruptionReason::kNone);
+ outgoing_frames_interrupted_ = InterruptionReason::kInterceptor;
return;
+ }
}
if (!ReadAndSendFrameFromDataPipe(&data_frame)) {
return;
}
- if (outgoing_frame_interceptor_ &&
- outgoing_frame_interceptor_->IsFrameStarted()) {
- outgoing_frame_interceptor_->FinishFrame();
- }
pending_send_data_frames_.pop();
}
if (pending_start_closing_handshake_) {
@@ -791,7 +799,8 @@ bool WebSocket::ReadAndSendFrameFromDataPipe(DataFrame* data_frame) {
const MojoResult begin_result = readable_->BeginReadData(
&buffer, &readable_size, MOJO_READ_DATA_FLAG_NONE);
if (begin_result == MOJO_RESULT_SHOULD_WAIT) {
- wait_for_readable_ = true;
+ DCHECK_EQ(outgoing_frames_interrupted_, InterruptionReason::kNone);
+ outgoing_frames_interrupted_ = InterruptionReason::kMojoPipe;
if (!blocked_on_websocket_channel_) {
readable_watcher_.ArmOrNotify();
}
diff --git a/chromium/services/network/websocket.h b/chromium/services/network/websocket.h
index 51c69738b73..d6a7a68a4c1 100644
--- a/chromium/services/network/websocket.h
+++ b/chromium/services/network/websocket.h
@@ -14,7 +14,7 @@
#include "base/component_export.h"
#include "base/containers/queue.h"
#include "base/containers/span.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
@@ -121,12 +121,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
public:
explicit UnownedPointer(WebSocket* pointer) : pointer_(pointer) {}
+ UnownedPointer(const UnownedPointer&) = delete;
+ UnownedPointer& operator=(const UnownedPointer&) = delete;
+
WebSocket* get() const { return pointer_; }
private:
- WebSocket* const pointer_;
-
- DISALLOW_COPY_AND_ASSIGN(UnownedPointer);
+ const raw_ptr<WebSocket> pointer_;
};
struct DataFrame final {
@@ -169,15 +170,25 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
void Reset();
+ enum class InterruptionReason {
+ // Not interrupted or not resuming after interruptions (but processing a
+ // brand new frame)
+ kNone,
+ // Interrupted by empty Mojo pipe or resuming afterwards
+ kMojoPipe,
+ // Interrupted by the interceptor or resuming afterwards
+ kInterceptor,
+ };
+
// Datapipe functions to receive.
void OnWritable(MojoResult result, const mojo::HandleSignalsState& state);
- void SendPendingDataFrames();
+ void SendPendingDataFrames(InterruptionReason resume_reason);
void SendDataFrame(base::span<const char>* data_span);
// Datapipe functions to send.
void OnReadable(MojoResult result, const mojo::HandleSignalsState& state);
- void ReadAndSendFromDataPipe();
+ void ReadAndSendFromDataPipe(InterruptionReason resume_reason);
// This helper method only called from ReadAndSendFromDataPipe.
// Note that it may indirectly delete |this|.
// Returns true if the frame has been sent completely.
@@ -185,7 +196,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
void ResumeDataPipeReading();
// |factory_| owns |this|.
- WebSocketFactory* const factory_;
+ const raw_ptr<WebSocketFactory> factory_;
mojo::Receiver<mojom::WebSocket> receiver_{this};
mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
@@ -217,17 +228,18 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
bool handshake_succeeded_ = false;
const HasRawHeadersAccess has_raw_headers_access_;
+ InterruptionReason incoming_frames_interrupted_ = InterruptionReason::kNone;
+ InterruptionReason outgoing_frames_interrupted_ = InterruptionReason::kNone;
+
// Datapipe fields to receive.
mojo::ScopedDataPipeProducerHandle writable_;
mojo::SimpleWatcher writable_watcher_;
base::queue<base::span<const char>> pending_data_frames_;
- bool wait_for_writable_ = false;
// Datapipe fields to send.
mojo::ScopedDataPipeConsumerHandle readable_;
mojo::SimpleWatcher readable_watcher_;
base::queue<DataFrame> pending_send_data_frames_;
- bool wait_for_readable_ = false;
bool blocked_on_websocket_channel_ = false;
// True if we should preserve the old behaviour where <=64KB messages were
diff --git a/chromium/services/network/websocket_factory.h b/chromium/services/network/websocket_factory.h
index 0167b8f270a..a088489cc60 100644
--- a/chromium/services/network/websocket_factory.h
+++ b/chromium/services/network/websocket_factory.h
@@ -10,6 +10,7 @@
#include "base/callback_forward.h"
#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/websocket.mojom.h"
@@ -82,7 +83,7 @@ class WebSocketFactory final {
WebSocketThrottler throttler_;
// |context_| outlives this object.
- NetworkContext* const context_;
+ const raw_ptr<NetworkContext> context_;
};
} // namespace network
diff --git a/chromium/services/network/websocket_interceptor.cc b/chromium/services/network/websocket_interceptor.cc
index 8c34ef6db38..a1ca0f09400 100644
--- a/chromium/services/network/websocket_interceptor.cc
+++ b/chromium/services/network/websocket_interceptor.cc
@@ -36,7 +36,6 @@ WebSocketInterceptor::InterceptResult WebSocketInterceptor::Intercept(
size_t size,
base::OnceClosure retry_callback) {
DCHECK(!pending_callback_);
- DCHECK(!frame_started_);
auto* throttling_interceptor =
ThrottlingController::GetInterceptor(net_log_source_id_);
@@ -44,7 +43,6 @@ WebSocketInterceptor::InterceptResult WebSocketInterceptor::Intercept(
if (!throttling_interceptor)
return kContinue;
- frame_started_ = true;
throttling_interceptor->SetSuspendWhenOffline(true);
int start_throttle_result = throttling_interceptor->StartThrottle(
/*result=*/0, size, /*send_end=*/base::TimeTicks(), /*start=*/false,
@@ -56,12 +54,6 @@ WebSocketInterceptor::InterceptResult WebSocketInterceptor::Intercept(
return kContinue;
}
-void WebSocketInterceptor::FinishFrame() {
- DCHECK(frame_started_);
- DCHECK(pending_callback_.is_null());
- frame_started_ = false;
-}
-
void WebSocketInterceptor::ThrottleCallback(int result, int64_t bytes) {
if (pending_callback_)
std::move(pending_callback_).Run();
diff --git a/chromium/services/network/websocket_interceptor.h b/chromium/services/network/websocket_interceptor.h
index b3fd4c29fcd..9e468bd620f 100644
--- a/chromium/services/network/websocket_interceptor.h
+++ b/chromium/services/network/websocket_interceptor.h
@@ -46,12 +46,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketInterceptor {
// * kShouldWait: frame processing should be paused until `retry_callback`
// is invoked.
// Calling Intercept again before the callback runs is not allowed.
- // Calling Intercept again before calling FinishFrame is also not allowed.
InterceptResult Intercept(size_t size, base::OnceClosure retry_callback);
- // This is meant to be called when processing of a single frame is done and it
- // resets the interceptor state.
- void FinishFrame();
- bool IsFrameStarted() { return frame_started_; }
private:
void ThrottleCallback(int result, int64_t bytes);
@@ -62,7 +57,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketInterceptor {
const std::unique_ptr<ScopedThrottlingToken> throttling_token_;
base::OnceClosure pending_callback_;
- bool frame_started_ = false;
};
} // namespace network
diff --git a/chromium/services/network/websocket_interceptor_unittest.cc b/chromium/services/network/websocket_interceptor_unittest.cc
index c9030a7b7f5..ea38faa9825 100644
--- a/chromium/services/network/websocket_interceptor_unittest.cc
+++ b/chromium/services/network/websocket_interceptor_unittest.cc
@@ -85,7 +85,6 @@ TEST_F(WebSocketInterceptorTest, SubsequentInterceptWhenSlow) {
EXPECT_CALL(mock_callback_, Callback()).Times(1);
task_environment_.FastForwardUntilNoTasksRemain();
- interceptor_->FinishFrame();
EXPECT_EQ(WebSocketInterceptor::kShouldWait,
interceptor_->Intercept(42, MakeCallback()));
}
@@ -98,10 +97,7 @@ TEST_F(WebSocketInterceptorTest, OfflineCallbackInvokedWhenBackOnline) {
EXPECT_EQ(WebSocketInterceptor::kShouldWait,
interceptor_->Intercept(42, MakeCallback()));
- // EXPECT_CALL(mock_callback_, Callback()).Times(1);
- EXPECT_CALL(mock_callback_, Callback()).Times(1).WillOnce([&] {
- interceptor_->FinishFrame();
- });
+ EXPECT_CALL(mock_callback_, Callback()).Times(1);
ThrottlingController::SetConditions(*kThrottlingProfileId, nullptr);
interceptor_->Intercept(42, MakeCallback());
}
@@ -114,9 +110,7 @@ TEST_F(WebSocketInterceptorTest, SlowAfterOffline) {
EXPECT_EQ(WebSocketInterceptor::kShouldWait,
interceptor_->Intercept(42, MakeCallback()));
- EXPECT_CALL(mock_callback_, Callback()).Times(1).WillOnce([&] {
- interceptor_->FinishFrame();
- });
+ EXPECT_CALL(mock_callback_, Callback()).Times(1);
ThrottlingController::SetConditions(
*kThrottlingProfileId,
std::make_unique<NetworkConditions>(/*offline=*/false, /*latency=*/0,
diff --git a/chromium/services/network/websocket_throttler.h b/chromium/services/network/websocket_throttler.h
index 679d8db5f70..d71cb661725 100644
--- a/chromium/services/network/websocket_throttler.h
+++ b/chromium/services/network/websocket_throttler.h
@@ -47,6 +47,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketPerProcessThrottler final {
};
WebSocketPerProcessThrottler();
+
+ WebSocketPerProcessThrottler(const WebSocketPerProcessThrottler&) = delete;
+ WebSocketPerProcessThrottler& operator=(const WebSocketPerProcessThrottler&) =
+ delete;
+
~WebSocketPerProcessThrottler();
// Returns if there are too many pending connections.
@@ -100,8 +105,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketPerProcessThrottler final {
static constexpr int kMaxPendingWebSocketConnections = 255;
base::WeakPtrFactory<WebSocketPerProcessThrottler> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WebSocketPerProcessThrottler);
};
// This class is for throttling WebSocket connections. WebSocketThrottler is
diff --git a/chromium/services/preferences/public/cpp/dictionary_value_update.cc b/chromium/services/preferences/public/cpp/dictionary_value_update.cc
index 62fca1da4c2..b3d63787a97 100644
--- a/chromium/services/preferences/public/cpp/dictionary_value_update.cc
+++ b/chromium/services/preferences/public/cpp/dictionary_value_update.cc
@@ -42,7 +42,7 @@ void DictionaryValueUpdate::Clear() {
return;
RecordSplitPath(std::vector<base::StringPiece>());
- value_->Clear();
+ value_->DictClear();
}
void DictionaryValueUpdate::Set(base::StringPiece path,
@@ -135,7 +135,12 @@ DictionaryValueUpdate::SetDictionaryWithoutPathExpansion(
bool DictionaryValueUpdate::GetBoolean(base::StringPiece path,
bool* out_value) const {
- return value_->GetBoolean(path, out_value);
+ absl::optional<bool> value = value_->FindBoolPath(path);
+ if (!value.has_value())
+ return false;
+ if (out_value)
+ *out_value = value.value();
+ return true;
}
bool DictionaryValueUpdate::GetInteger(base::StringPiece path,
@@ -145,7 +150,11 @@ bool DictionaryValueUpdate::GetInteger(base::StringPiece path,
bool DictionaryValueUpdate::GetDouble(base::StringPiece path,
double* out_value) const {
- return value_->GetDouble(path, out_value);
+ if (absl::optional<double> value = value_->FindDoubleKey(path)) {
+ *out_value = *value;
+ return true;
+ }
+ return false;
}
bool DictionaryValueUpdate::GetString(base::StringPiece path,
diff --git a/chromium/services/preferences/public/cpp/dictionary_value_update.h b/chromium/services/preferences/public/cpp/dictionary_value_update.h
index 39278faa484..5d96be85f51 100644
--- a/chromium/services/preferences/public/cpp/dictionary_value_update.h
+++ b/chromium/services/preferences/public/cpp/dictionary_value_update.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
#include "base/strings/string_piece.h"
#include "services/preferences/public/cpp/scoped_pref_update.h"
@@ -156,7 +157,7 @@ class DictionaryValueUpdate {
const std::vector<base::StringPiece>& path);
UpdateCallback report_update_;
- base::DictionaryValue* const value_;
+ const raw_ptr<base::DictionaryValue> value_;
const std::vector<std::string> path_;
};
diff --git a/chromium/services/preferences/public/cpp/scoped_pref_update.h b/chromium/services/preferences/public/cpp/scoped_pref_update.h
index b44c7102d84..7da5c34f821 100644
--- a/chromium/services/preferences/public/cpp/scoped_pref_update.h
+++ b/chromium/services/preferences/public/cpp/scoped_pref_update.h
@@ -10,7 +10,7 @@
#include <string>
#include <vector>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/strings/string_piece.h"
class PrefService;
@@ -62,7 +62,7 @@ class ScopedDictionaryPrefUpdate {
void RecordPath(const std::vector<std::string>& path);
// Weak pointer.
- PrefService* const service_;
+ const raw_ptr<PrefService> service_;
// Path of the preference being updated.
const std::string path_;
diff --git a/chromium/services/preferences/public/cpp/tracked/mock_validation_delegate.h b/chromium/services/preferences/public/cpp/tracked/mock_validation_delegate.h
index c3f294ccfc6..a05a0288b0b 100644
--- a/chromium/services/preferences/public/cpp/tracked/mock_validation_delegate.h
+++ b/chromium/services/preferences/public/cpp/tracked/mock_validation_delegate.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/values.h"
#include "services/preferences/public/mojom/preferences.mojom.h"
#include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom.h"
@@ -48,6 +47,10 @@ class MockValidationDelegateRecord
MockValidationDelegateRecord();
+ MockValidationDelegateRecord(const MockValidationDelegateRecord&) = delete;
+ MockValidationDelegateRecord& operator=(const MockValidationDelegateRecord&) =
+ delete;
+
// Returns the number of recorded validations.
size_t recorded_validations_count() const { return validations_.size(); }
@@ -80,8 +83,6 @@ class MockValidationDelegateRecord
prefs::mojom::TrackedPreferenceMetadata::PrefTrackingStrategy strategy);
std::vector<ValidationEvent> validations_;
-
- DISALLOW_COPY_AND_ASSIGN(MockValidationDelegateRecord);
};
class MockValidationDelegate
diff --git a/chromium/services/preferences/tracked/dictionary_hash_store_contents.cc b/chromium/services/preferences/tracked/dictionary_hash_store_contents.cc
index 68de82a40ca..74315fd2bfe 100644
--- a/chromium/services/preferences/tracked/dictionary_hash_store_contents.cc
+++ b/chromium/services/preferences/tracked/dictionary_hash_store_contents.cc
@@ -6,7 +6,6 @@
#include "base/callback.h"
#include "base/check.h"
-#include "base/macros.h"
#include "base/notreached.h"
#include "base/values.h"
#include "components/pref_registry/pref_registry_syncable.h"
diff --git a/chromium/services/preferences/tracked/dictionary_hash_store_contents.h b/chromium/services/preferences/tracked/dictionary_hash_store_contents.h
index 16fe628ad81..4e1c89e3e11 100644
--- a/chromium/services/preferences/tracked/dictionary_hash_store_contents.h
+++ b/chromium/services/preferences/tracked/dictionary_hash_store_contents.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_PREFERENCES_TRACKED_DICTIONARY_HASH_STORE_CONTENTS_H_
#define SERVICES_PREFERENCES_TRACKED_DICTIONARY_HASH_STORE_CONTENTS_H_
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "services/preferences/tracked/hash_store_contents.h"
namespace base {
@@ -27,6 +27,10 @@ class DictionaryHashStoreContents : public HashStoreContents {
// |storage|.
explicit DictionaryHashStoreContents(base::DictionaryValue* storage);
+ DictionaryHashStoreContents(const DictionaryHashStoreContents&) = delete;
+ DictionaryHashStoreContents& operator=(const DictionaryHashStoreContents&) =
+ delete;
+
// Registers required preferences.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
@@ -50,13 +54,11 @@ class DictionaryHashStoreContents : public HashStoreContents {
void SetSuperMac(const std::string& super_mac) override;
private:
- base::DictionaryValue* storage_;
+ raw_ptr<base::DictionaryValue> storage_;
// Helper function to get a mutable version of the macs from |storage_|,
// creating it if needed and |create_if_null| is true.
base::DictionaryValue* GetMutableContents(bool create_if_null);
-
- DISALLOW_COPY_AND_ASSIGN(DictionaryHashStoreContents);
};
#endif // SERVICES_PREFERENCES_TRACKED_DICTIONARY_HASH_STORE_CONTENTS_H_
diff --git a/chromium/services/preferences/tracked/pref_hash_calculator.h b/chromium/services/preferences/tracked/pref_hash_calculator.h
index bebfc55592a..f9d92c20ed5 100644
--- a/chromium/services/preferences/tracked/pref_hash_calculator.h
+++ b/chromium/services/preferences/tracked/pref_hash_calculator.h
@@ -7,8 +7,6 @@
#include <string>
-#include "base/macros.h"
-
namespace base {
class Value;
} // namespace base
diff --git a/chromium/services/preferences/tracked/pref_hash_calculator_unittest.cc b/chromium/services/preferences/tracked/pref_hash_calculator_unittest.cc
index 406395fc75f..eb04e684530 100644
--- a/chromium/services/preferences/tracked/pref_hash_calculator_unittest.cc
+++ b/chromium/services/preferences/tracked/pref_hash_calculator_unittest.cc
@@ -8,7 +8,6 @@
#include <string>
#include <utility>
-#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/services/preferences/tracked/pref_hash_filter.h b/chromium/services/preferences/tracked/pref_hash_filter.h
index fa4d4e52a69..7c8baa2921b 100644
--- a/chromium/services/preferences/tracked/pref_hash_filter.h
+++ b/chromium/services/preferences/tracked/pref_hash_filter.h
@@ -15,7 +15,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc b/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc
index c6d3b3ba4b4..9f9bca38ad5 100644
--- a/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc
+++ b/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/cxx17_backports.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
@@ -190,7 +191,7 @@ class MockPrefHashStore : public PrefHashStore {
bool StampSuperMac() override;
private:
- MockPrefHashStore* outer_;
+ raw_ptr<MockPrefHashStore> outer_;
};
// Records a call to this mock's CheckValue/CheckSplitValue methods.
@@ -368,6 +369,9 @@ class MockHashStoreContents : public HashStoreContents {
public:
MockHashStoreContents() {}
+ MockHashStoreContents(const MockHashStoreContents&) = delete;
+ MockHashStoreContents& operator=(const MockHashStoreContents&) = delete;
+
// Returns the number of hashes stored.
size_t stored_hashes_count() const { return dictionary_.DictSize(); }
@@ -426,9 +430,7 @@ class MockHashStoreContents : public HashStoreContents {
// which can be executed during shutdown. To be able to capture the behavior
// of the copy, we make it forward calls to the mock it was created from.
// Once set, |origin_mock_| must outlive this instance.
- MockHashStoreContents* origin_mock_;
-
- DISALLOW_COPY_AND_ASSIGN(MockHashStoreContents);
+ raw_ptr<MockHashStoreContents> origin_mock_;
};
std::string MockHashStoreContents::GetStoredMac(const std::string& path) const {
@@ -551,6 +553,9 @@ class PrefHashFilterTest : public testing::TestWithParam<EnforcementLevel>,
validation_delegate_receiver_(&mock_validation_delegate_),
reset_recorded_(false) {}
+ PrefHashFilterTest(const PrefHashFilterTest&) = delete;
+ PrefHashFilterTest& operator=(const PrefHashFilterTest&) = delete;
+
void SetUp() override {
Reset();
}
@@ -620,9 +625,9 @@ class PrefHashFilterTest : public testing::TestWithParam<EnforcementLevel>,
std::move(pref_store_contents_));
}
- MockPrefHashStore* mock_pref_hash_store_;
- MockPrefHashStore* mock_external_validation_pref_hash_store_;
- MockHashStoreContents* mock_external_validation_hash_store_contents_;
+ raw_ptr<MockPrefHashStore> mock_pref_hash_store_;
+ raw_ptr<MockPrefHashStore> mock_external_validation_pref_hash_store_;
+ raw_ptr<MockHashStoreContents> mock_external_validation_hash_store_contents_;
std::unique_ptr<base::DictionaryValue> pref_store_contents_;
scoped_refptr<MockValidationDelegateRecord> mock_validation_delegate_record_;
std::unique_ptr<PrefHashFilter> pref_hash_filter_;
@@ -652,8 +657,6 @@ class PrefHashFilterTest : public testing::TestWithParam<EnforcementLevel>,
mojo::ReceiverSet<prefs::mojom::ResetOnLoadObserver>
reset_on_load_observer_receivers_;
bool reset_recorded_;
-
- DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
};
TEST_P(PrefHashFilterTest, EmptyAndUnchanged) {
diff --git a/chromium/services/preferences/tracked/pref_hash_store_impl.cc b/chromium/services/preferences/tracked/pref_hash_store_impl.cc
index 63a15eb8eb5..cc01e5a0ce5 100644
--- a/chromium/services/preferences/tracked/pref_hash_store_impl.cc
+++ b/chromium/services/preferences/tracked/pref_hash_store_impl.cc
@@ -8,7 +8,7 @@
#include <utility>
#include "base/check.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
@@ -73,8 +73,8 @@ class PrefHashStoreImpl::PrefHashStoreTransactionImpl
bool StampSuperMac() override;
private:
- PrefHashStoreImpl* outer_;
- HashStoreContents* contents_;
+ raw_ptr<PrefHashStoreImpl> outer_;
+ raw_ptr<HashStoreContents> contents_;
bool super_mac_valid_;
bool super_mac_dirty_;
diff --git a/chromium/services/preferences/tracked/pref_hash_store_impl.h b/chromium/services/preferences/tracked/pref_hash_store_impl.h
index 73dfdd1d3eb..e6bb197e51e 100644
--- a/chromium/services/preferences/tracked/pref_hash_store_impl.h
+++ b/chromium/services/preferences/tracked/pref_hash_store_impl.h
@@ -6,7 +6,6 @@
#define SERVICES_PREFERENCES_TRACKED_PREF_HASH_STORE_IMPL_H_
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "services/preferences/tracked/pref_hash_calculator.h"
#include "services/preferences/tracked/pref_hash_store.h"
diff --git a/chromium/services/preferences/tracked/pref_hash_store_impl_unittest.cc b/chromium/services/preferences/tracked/pref_hash_store_impl_unittest.cc
index a2e9e052997..2dfa7167266 100644
--- a/chromium/services/preferences/tracked/pref_hash_store_impl_unittest.cc
+++ b/chromium/services/preferences/tracked/pref_hash_store_impl_unittest.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "base/macros.h"
#include "base/values.h"
#include "services/preferences/tracked/dictionary_hash_store_contents.h"
#include "services/preferences/tracked/hash_store_contents.h"
@@ -20,6 +19,9 @@ class PrefHashStoreImplTest : public testing::Test {
public:
PrefHashStoreImplTest() : contents_(&pref_store_contents_) {}
+ PrefHashStoreImplTest(const PrefHashStoreImplTest&) = delete;
+ PrefHashStoreImplTest& operator=(const PrefHashStoreImplTest&) = delete;
+
protected:
HashStoreContents* GetHashStoreContents() { return &contents_; }
@@ -28,8 +30,6 @@ class PrefHashStoreImplTest : public testing::Test {
// Must be declared after |pref_store_contents_| as it needs to be outlived
// by it.
DictionaryHashStoreContents contents_;
-
- DISALLOW_COPY_AND_ASSIGN(PrefHashStoreImplTest);
};
TEST_F(PrefHashStoreImplTest, ComputeMac) {
diff --git a/chromium/services/preferences/tracked/registry_hash_store_contents_win.h b/chromium/services/preferences/tracked/registry_hash_store_contents_win.h
index 234b80506f5..0bce1e4b7e1 100644
--- a/chromium/services/preferences/tracked/registry_hash_store_contents_win.h
+++ b/chromium/services/preferences/tracked/registry_hash_store_contents_win.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/macros.h"
#include "services/preferences/tracked/hash_store_contents.h"
#include "services/preferences/tracked/temp_scoped_dir_cleaner.h"
diff --git a/chromium/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc b/chromium/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc
index ce17f1061ee..23721de77a3 100644
--- a/chromium/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc
+++ b/chromium/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc
@@ -31,6 +31,12 @@ constexpr char kAtomicPrefPath[] = "path1";
constexpr char kSplitPrefPath[] = "extension";
class RegistryHashStoreContentsWinTest : public testing::Test {
+ public:
+ RegistryHashStoreContentsWinTest(const RegistryHashStoreContentsWinTest&) =
+ delete;
+ RegistryHashStoreContentsWinTest& operator=(
+ const RegistryHashStoreContentsWinTest&) = delete;
+
protected:
RegistryHashStoreContentsWinTest() {}
@@ -46,8 +52,6 @@ class RegistryHashStoreContentsWinTest : public testing::Test {
private:
registry_util::RegistryOverrideManager registry_override_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(RegistryHashStoreContentsWinTest);
};
} // namespace
diff --git a/chromium/services/preferences/tracked/tracked_atomic_preference.h b/chromium/services/preferences/tracked/tracked_atomic_preference.h
index 3f3477e9dd9..f9f4aeb72d6 100644
--- a/chromium/services/preferences/tracked/tracked_atomic_preference.h
+++ b/chromium/services/preferences/tracked/tracked_atomic_preference.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/compiler_specific.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "services/preferences/tracked/pref_hash_filter.h"
#include "services/preferences/tracked/tracked_preference.h"
#include "services/preferences/tracked/tracked_preference_helper.h"
@@ -35,6 +35,9 @@ class TrackedAtomicPreference : public TrackedPreference {
prefs::mojom::TrackedPreferenceMetadata::ValueType value_type,
prefs::mojom::TrackedPreferenceValidationDelegate* delegate);
+ TrackedAtomicPreference(const TrackedAtomicPreference&) = delete;
+ TrackedAtomicPreference& operator=(const TrackedAtomicPreference&) = delete;
+
// TrackedPreference implementation.
TrackedPreferenceType GetType() const override;
void OnNewValue(const base::Value* value,
@@ -47,9 +50,7 @@ class TrackedAtomicPreference : public TrackedPreference {
private:
const std::string pref_path_;
const TrackedPreferenceHelper helper_;
- prefs::mojom::TrackedPreferenceValidationDelegate* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedAtomicPreference);
+ raw_ptr<prefs::mojom::TrackedPreferenceValidationDelegate> delegate_;
};
#endif // SERVICES_PREFERENCES_TRACKED_TRACKED_ATOMIC_PREFERENCE_H_
diff --git a/chromium/services/preferences/tracked/tracked_persistent_pref_store_factory.h b/chromium/services/preferences/tracked/tracked_persistent_pref_store_factory.h
index a0214c87bb4..77389ccca9e 100644
--- a/chromium/services/preferences/tracked/tracked_persistent_pref_store_factory.h
+++ b/chromium/services/preferences/tracked/tracked_persistent_pref_store_factory.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_PREFERENCES_TRACKED_TRACKED_PERSISTENT_PREF_STORE_FACTORY_H_
#define SERVICES_PREFERENCES_TRACKED_TRACKED_PERSISTENT_PREF_STORE_FACTORY_H_
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "services/preferences/public/mojom/preferences.mojom.h"
namespace base {
diff --git a/chromium/services/preferences/tracked/tracked_preference_helper.h b/chromium/services/preferences/tracked/tracked_preference_helper.h
index b62d6d19326..13da30eb1fd 100644
--- a/chromium/services/preferences/tracked/tracked_preference_helper.h
+++ b/chromium/services/preferences/tracked/tracked_preference_helper.h
@@ -9,7 +9,6 @@
#include <string>
-#include "base/macros.h"
#include "services/preferences/tracked/pref_hash_filter.h"
#include "services/preferences/tracked/pref_hash_store_transaction.h"
@@ -34,6 +33,9 @@ class TrackedPreferenceHelper {
enforcement_level,
prefs::mojom::TrackedPreferenceMetadata::ValueType value_type);
+ TrackedPreferenceHelper(const TrackedPreferenceHelper&) = delete;
+ TrackedPreferenceHelper& operator=(const TrackedPreferenceHelper&) = delete;
+
// Returns a ResetAction stating whether a reset is desired (DO_RESET) or not
// (DONT_RESET) based on observing |value_state|. Can also return WANTED_RESET
// if a reset would have been desired but the current |enforcement_level|
@@ -64,8 +66,6 @@ class TrackedPreferenceHelper {
const bool enforce_;
const bool personal_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedPreferenceHelper);
};
#endif // SERVICES_PREFERENCES_TRACKED_TRACKED_PREFERENCE_HELPER_H_
diff --git a/chromium/services/preferences/tracked/tracked_preferences_migration.cc b/chromium/services/preferences/tracked/tracked_preferences_migration.cc
index 3342daf9890..15c276bc8f4 100644
--- a/chromium/services/preferences/tracked/tracked_preferences_migration.cc
+++ b/chromium/services/preferences/tracked/tracked_preferences_migration.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram.h"
#include "base/values.h"
@@ -41,6 +40,10 @@ class TrackedPreferencesMigrator
InterceptablePrefFilter* unprotected_pref_filter,
InterceptablePrefFilter* protected_pref_filter);
+ TrackedPreferencesMigrator(const TrackedPreferencesMigrator&) = delete;
+ TrackedPreferencesMigrator& operator=(const TrackedPreferencesMigrator&) =
+ delete;
+
// Stores the data coming in from the filter identified by |id| into this
// class and then calls MigrateIfReady();
void InterceptFilterOnLoad(
@@ -80,8 +83,6 @@ class TrackedPreferencesMigrator
std::unique_ptr<base::DictionaryValue> unprotected_prefs_;
std::unique_ptr<base::DictionaryValue> protected_prefs_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator);
};
// Invokes |store_cleaner| for every |keys_to_clean|.
diff --git a/chromium/services/preferences/tracked/tracked_preferences_migration_unittest.cc b/chromium/services/preferences/tracked/tracked_preferences_migration_unittest.cc
index 7d93724e463..8b39ac1f97e 100644
--- a/chromium/services/preferences/tracked/tracked_preferences_migration_unittest.cc
+++ b/chromium/services/preferences/tracked/tracked_preferences_migration_unittest.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/macros.h"
#include "base/strings/string_split.h"
#include "base/values.h"
#include "components/prefs/testing_pref_service.h"
@@ -86,6 +85,11 @@ class TrackedPreferencesMigrationTest : public testing::Test {
unprotected_store_migration_complete_(false),
protected_store_migration_complete_(false) {}
+ TrackedPreferencesMigrationTest(const TrackedPreferencesMigrationTest&) =
+ delete;
+ TrackedPreferencesMigrationTest& operator=(
+ const TrackedPreferencesMigrationTest&) = delete;
+
void SetUp() override { Reset(); }
void Reset() {
@@ -376,8 +380,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
bool protected_store_migration_complete_;
TestingPrefServiceSimple local_state_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrationTest);
};
// static
diff --git a/chromium/services/preferences/tracked/tracked_split_preference.h b/chromium/services/preferences/tracked/tracked_split_preference.h
index 793bf47e424..1a620650b75 100644
--- a/chromium/services/preferences/tracked/tracked_split_preference.h
+++ b/chromium/services/preferences/tracked/tracked_split_preference.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/compiler_specific.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "services/preferences/tracked/pref_hash_filter.h"
#include "services/preferences/tracked/tracked_preference.h"
#include "services/preferences/tracked/tracked_preference_helper.h"
@@ -36,6 +36,9 @@ class TrackedSplitPreference : public TrackedPreference {
prefs::mojom::TrackedPreferenceMetadata::ValueType value_type,
prefs::mojom::TrackedPreferenceValidationDelegate* delegate);
+ TrackedSplitPreference(const TrackedSplitPreference&) = delete;
+ TrackedSplitPreference& operator=(const TrackedSplitPreference&) = delete;
+
// TrackedPreference implementation.
TrackedPreferenceType GetType() const override;
void OnNewValue(const base::Value* value,
@@ -48,9 +51,7 @@ class TrackedSplitPreference : public TrackedPreference {
private:
const std::string pref_path_;
const TrackedPreferenceHelper helper_;
- prefs::mojom::TrackedPreferenceValidationDelegate* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(TrackedSplitPreference);
+ raw_ptr<prefs::mojom::TrackedPreferenceValidationDelegate> delegate_;
};
#endif // SERVICES_PREFERENCES_TRACKED_TRACKED_SPLIT_PREFERENCE_H_
diff --git a/chromium/services/proxy_resolver/BUILD.gn b/chromium/services/proxy_resolver/BUILD.gn
index 3f1bdda46aa..f3a6d017df5 100644
--- a/chromium/services/proxy_resolver/BUILD.gn
+++ b/chromium/services/proxy_resolver/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
import("//v8/gni/v8.gni")
source_set("lib") {
@@ -26,6 +27,7 @@ source_set("lib") {
configs += [
"//build/config/compiler:wexit_time_destructors",
"//v8:external_startup_data",
+ "//tools/v8_context_snapshot:use_v8_context_snapshot",
]
deps = [
@@ -75,7 +77,12 @@ source_set("tests") {
}
if (is_android) {
- deps += [ "//v8:v8_external_startup_data_assets" ]
+ if (use_v8_context_snapshot) {
+ deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ]
+ }
+ if (!use_v8_context_snapshot || include_both_v8_snapshots) {
+ deps += [ "//v8:v8_external_startup_data_assets" ]
+ }
}
configs += [ "//v8:external_startup_data" ]
diff --git a/chromium/services/proxy_resolver/host_resolver_mojo.cc b/chromium/services/proxy_resolver/host_resolver_mojo.cc
index 7ba8a42c208..e9b3bfaaeec 100644
--- a/chromium/services/proxy_resolver/host_resolver_mojo.cc
+++ b/chromium/services/proxy_resolver/host_resolver_mojo.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/completion_once_callback.h"
@@ -111,7 +112,7 @@ class HostResolverMojo::RequestImpl : public ProxyHostResolver::Request,
net::CompletionOnceCallback callback_;
base::WeakPtr<ProxyHostResolverCache> host_cache_;
- Impl* const impl_;
+ const raw_ptr<Impl> impl_;
std::vector<net::IPAddress> results_;
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/services/proxy_resolver/host_resolver_mojo.h b/chromium/services/proxy_resolver/host_resolver_mojo.h
index a5052e3a6de..6822ad21c8c 100644
--- a/chromium/services/proxy_resolver/host_resolver_mojo.h
+++ b/chromium/services/proxy_resolver/host_resolver_mojo.h
@@ -8,7 +8,7 @@
#include <memory>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "net/proxy_resolution/proxy_resolve_dns_operation.h"
@@ -54,7 +54,7 @@ class HostResolverMojo : public ProxyHostResolver {
class Job;
class RequestImpl;
- Impl* const impl_;
+ const raw_ptr<Impl> impl_;
ProxyHostResolverCache host_cache_;
base::WeakPtrFactory<ProxyHostResolverCache> host_cache_weak_factory_{
diff --git a/chromium/services/proxy_resolver/mock_proxy_host_resolver.cc b/chromium/services/proxy_resolver/mock_proxy_host_resolver.cc
index 1bf2ea84b78..cfa0149c06d 100644
--- a/chromium/services/proxy_resolver/mock_proxy_host_resolver.cc
+++ b/chromium/services/proxy_resolver/mock_proxy_host_resolver.cc
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/check.h"
#include "base/location.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/completion_once_callback.h"
@@ -121,7 +122,7 @@ class HangingProxyHostResolver::RequestImpl : public Request {
}
private:
- HangingProxyHostResolver* resolver_;
+ raw_ptr<HangingProxyHostResolver> resolver_;
};
HangingProxyHostResolver::HangingProxyHostResolver(
diff --git a/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h b/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h
index c2f8ca2cf84..7e3799270d3 100644
--- a/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h
+++ b/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h
@@ -10,6 +10,7 @@
#include <utility>
#include "base/check.h"
+#include "base/memory/raw_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
#include "net/base/address_family.h"
@@ -73,7 +74,7 @@ class MojoProxyResolverV8TracingBindings
}
base::ThreadChecker thread_checker_;
- Client* const client_;
+ const raw_ptr<Client> client_;
HostResolverMojo host_resolver_;
};
diff --git a/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc b/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc
index c53e214f876..6f3bedf76dd 100644
--- a/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc
+++ b/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc
@@ -8,7 +8,6 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,6 +17,11 @@ class MojoProxyResolverV8TracingBindingsTest : public testing::Test {
public:
MojoProxyResolverV8TracingBindingsTest() = default;
+ MojoProxyResolverV8TracingBindingsTest(
+ const MojoProxyResolverV8TracingBindingsTest&) = delete;
+ MojoProxyResolverV8TracingBindingsTest& operator=(
+ const MojoProxyResolverV8TracingBindingsTest&) = delete;
+
void Alert(const std::string& message) { alerts_.push_back(message); }
void OnError(int32_t line_number, const std::string& message) {
@@ -36,9 +40,6 @@ class MojoProxyResolverV8TracingBindingsTest : public testing::Test {
std::vector<std::string> alerts_;
std::vector<std::pair<int, std::string>> errors_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MojoProxyResolverV8TracingBindingsTest);
};
TEST_F(MojoProxyResolverV8TracingBindingsTest, Basic) {
diff --git a/chromium/services/proxy_resolver/proxy_resolver_factory_impl.cc b/chromium/services/proxy_resolver/proxy_resolver_factory_impl.cc
index bc3411a362a..fec5b6a6f0d 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_factory_impl.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_factory_impl.cc
@@ -8,7 +8,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/net_errors.h"
@@ -36,10 +36,10 @@ class ProxyResolverFactoryImpl::Job {
void OnDisconnect();
void OnProxyResolverCreated(int error);
- ProxyResolverFactoryImpl* const parent_;
+ const raw_ptr<ProxyResolverFactoryImpl> parent_;
std::unique_ptr<ProxyResolverV8Tracing> proxy_resolver_impl_;
mojo::PendingReceiver<mojom::ProxyResolver> proxy_receiver_;
- ProxyResolverV8TracingFactory* factory_;
+ raw_ptr<ProxyResolverV8TracingFactory> factory_;
std::unique_ptr<net::ProxyResolverFactory::Request> request_;
mojo::Remote<mojom::ProxyResolverFactoryRequestClient> remote_client_;
};
diff --git a/chromium/services/proxy_resolver/proxy_resolver_factory_impl.h b/chromium/services/proxy_resolver/proxy_resolver_factory_impl.h
index 420711a4f98..05ad558901d 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_factory_impl.h
+++ b/chromium/services/proxy_resolver/proxy_resolver_factory_impl.h
@@ -10,7 +10,6 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
diff --git a/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc b/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc
index 53a706eb2a1..0a2deadcdde 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
@@ -62,7 +63,7 @@ enum Event {
class TestProxyResolverFactory : public ProxyResolverV8TracingFactory {
public:
struct PendingRequest {
- std::unique_ptr<ProxyResolverV8Tracing>* resolver;
+ raw_ptr<std::unique_ptr<ProxyResolverV8Tracing>> resolver;
net::CompletionOnceCallback callback;
};
@@ -96,7 +97,7 @@ class TestProxyResolverFactory : public ProxyResolverV8TracingFactory {
PendingRequest* pending_request() { return pending_request_.get(); }
private:
- net::EventWaiter<Event>* waiter_;
+ raw_ptr<net::EventWaiter<Event>> waiter_;
size_t requests_handled_ = 0;
std::unique_ptr<PendingRequest> pending_request_;
};
@@ -162,7 +163,7 @@ class ProxyResolverFactoryImplTest
base::test::TaskEnvironment task_environment_;
std::unique_ptr<TestProxyResolverFactoryImpl> mock_factory_impl_;
- TestProxyResolverFactory* mock_factory_;
+ raw_ptr<TestProxyResolverFactory> mock_factory_;
mojo::Remote<mojom::ProxyResolverFactory> factory_;
int instances_destroyed_ = 0;
diff --git a/chromium/services/proxy_resolver/proxy_resolver_impl.cc b/chromium/services/proxy_resolver/proxy_resolver_impl.cc
index 25dafdcf167..60d53741855 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_impl.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_impl.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/net_errors.h"
#include "net/base/network_isolation_key.h"
@@ -39,7 +39,7 @@ class ProxyResolverImpl::Job {
void GetProxyDone(int error);
- ProxyResolverImpl* resolver_;
+ raw_ptr<ProxyResolverImpl> resolver_;
mojo::Remote<mojom::ProxyResolverRequestClient> client_;
net::ProxyInfo result_;
diff --git a/chromium/services/proxy_resolver/proxy_resolver_impl.h b/chromium/services/proxy_resolver/proxy_resolver_impl.h
index 5d4ea769605..b94cda55488 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_impl.h
+++ b/chromium/services/proxy_resolver/proxy_resolver_impl.h
@@ -8,7 +8,6 @@
#include <map>
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
diff --git a/chromium/services/proxy_resolver/proxy_resolver_impl_unittest.cc b/chromium/services/proxy_resolver/proxy_resolver_impl_unittest.cc
index ed1ab6f5deb..c019db53686 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_impl_unittest.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_impl_unittest.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -118,7 +119,7 @@ class MockProxyResolverV8Tracing : public ProxyResolverV8Tracing {
struct Job {
GURL url;
net::NetworkIsolationKey network_isolation_key;
- net::ProxyInfo* results;
+ raw_ptr<net::ProxyInfo> results;
bool cancelled = false;
void Complete(int result) {
@@ -154,8 +155,8 @@ class MockProxyResolverV8Tracing : public ProxyResolverV8Tracing {
}
private:
- Job* job_;
- MockProxyResolverV8Tracing* resolver_;
+ raw_ptr<Job> job_;
+ raw_ptr<MockProxyResolverV8Tracing> resolver_;
};
MockProxyResolverV8Tracing() {}
@@ -223,10 +224,10 @@ class ProxyResolverImplTest : public testing::Test {
protected:
base::test::TaskEnvironment task_environment_;
- MockProxyResolverV8Tracing* mock_proxy_resolver_;
+ raw_ptr<MockProxyResolverV8Tracing> mock_proxy_resolver_;
std::unique_ptr<ProxyResolverImpl> resolver_impl_;
- mojom::ProxyResolver* resolver_;
+ raw_ptr<mojom::ProxyResolver> resolver_;
};
TEST_F(ProxyResolverImplTest, GetProxyForUrl) {
diff --git a/chromium/services/proxy_resolver/proxy_resolver_v8.cc b/chromium/services/proxy_resolver/proxy_resolver_v8.cc
index 5d514c10327..573f2f5e803 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_v8.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_v8.cc
@@ -15,6 +15,7 @@
#include "base/cxx17_backports.h"
#include "base/debug/leak_annotations.h"
#include "base/lazy_instance.h"
+#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
@@ -99,6 +100,11 @@ class V8ExternalStringFromScriptData
const scoped_refptr<net::PacFileData>& script_data)
: script_data_(script_data) {}
+ V8ExternalStringFromScriptData(const V8ExternalStringFromScriptData&) =
+ delete;
+ V8ExternalStringFromScriptData& operator=(
+ const V8ExternalStringFromScriptData&) = delete;
+
const uint16_t* data() const override {
return reinterpret_cast<const uint16_t*>(script_data_->utf16().data());
}
@@ -107,7 +113,6 @@ class V8ExternalStringFromScriptData
private:
const scoped_refptr<net::PacFileData> script_data_;
- DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData);
};
// External string wrapper so V8 can access a string literal.
@@ -121,6 +126,9 @@ class V8ExternalASCIILiteral
DCHECK(base::IsStringASCII(ascii));
}
+ V8ExternalASCIILiteral(const V8ExternalASCIILiteral&) = delete;
+ V8ExternalASCIILiteral& operator=(const V8ExternalASCIILiteral&) = delete;
+
const char* data() const override { return ascii_; }
size_t length() const override { return length_; }
@@ -128,7 +136,6 @@ class V8ExternalASCIILiteral
private:
const char* ascii_;
size_t length_;
- DISALLOW_COPY_AND_ASSIGN(V8ExternalASCIILiteral);
};
// When creating a v8::String from a C++ string we have two choices: create
@@ -365,6 +372,9 @@ class SharedIsolateFactory {
public:
SharedIsolateFactory() : has_initialized_v8_(false) {}
+ SharedIsolateFactory(const SharedIsolateFactory&) = delete;
+ SharedIsolateFactory& operator=(const SharedIsolateFactory&) = delete;
+
// Lazily creates a v8::Isolate, or returns the already created instance.
v8::Isolate* GetSharedIsolate() {
base::AutoLock lock(lock_);
@@ -372,9 +382,14 @@ class SharedIsolateFactory {
if (!holder_) {
// Do one-time initialization for V8.
if (!has_initialized_v8_) {
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+#if defined(USE_V8_CONTEXT_SNAPSHOT)
+ gin::V8Initializer::LoadV8Snapshot(
+ gin::V8SnapshotFileType::kWithAdditionalContext);
+#else
gin::V8Initializer::LoadV8Snapshot();
#endif
+#endif
// The performance of the proxy resolver is limited by DNS resolution,
// and not V8, so tune down V8 to use as little memory as possible.
@@ -415,8 +430,6 @@ class SharedIsolateFactory {
base::Lock lock_;
std::unique_ptr<gin::IsolateHolder> holder_;
bool has_initialized_v8_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedIsolateFactory);
};
base::LazyInstance<SharedIsolateFactory>::Leaky g_isolate_factory =
@@ -849,7 +862,7 @@ class ProxyResolverV8::Context {
mutable base::Lock lock_;
ProxyResolverV8::JSBindings* js_bindings_;
- v8::Isolate* isolate_;
+ raw_ptr<v8::Isolate> isolate_;
v8::Persistent<v8::External> v8_this_;
v8::Persistent<v8::Context> v8_context_;
};
diff --git a/chromium/services/proxy_resolver/proxy_resolver_v8.h b/chromium/services/proxy_resolver/proxy_resolver_v8.h
index a575e1fcfb9..7984cf1602c 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_v8.h
+++ b/chromium/services/proxy_resolver/proxy_resolver_v8.h
@@ -11,7 +11,6 @@
#include <string>
#include "base/compiler_specific.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/proxy_resolution/proxy_resolve_dns_operation.h"
@@ -57,6 +56,9 @@ class ProxyResolverV8 {
JSBindings* bindings,
std::unique_ptr<ProxyResolverV8>* resolver);
+ ProxyResolverV8(const ProxyResolverV8&) = delete;
+ ProxyResolverV8& operator=(const ProxyResolverV8&) = delete;
+
~ProxyResolverV8();
int GetProxyForURL(const GURL& url,
@@ -75,8 +77,6 @@ class ProxyResolverV8 {
explicit ProxyResolverV8(std::unique_ptr<Context> context);
std::unique_ptr<Context> context_;
-
- DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8);
};
} // namespace proxy_resolver
diff --git a/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.cc b/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.cc
index 940b3b75eaa..c118c9fe013 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.cc
@@ -12,11 +12,11 @@
#include <vector>
#include "base/bind.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
+#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/atomic_flag.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_restrictions.h"
@@ -96,9 +96,9 @@ class Job : public base::RefCountedThreadSafe<Job>,
worker_task_runner(worker_task_runner),
num_outstanding_callbacks(num_outstanding_callbacks) {}
- ProxyResolverV8* v8_resolver;
+ raw_ptr<ProxyResolverV8> v8_resolver;
scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner;
- int* num_outstanding_callbacks;
+ raw_ptr<int> num_outstanding_callbacks;
};
// |params| is non-owned. It contains the parameters for this Job, and must
// outlive it.
@@ -218,7 +218,7 @@ class Job : public base::RefCountedThreadSafe<Job>,
// The Parameters for this Job.
// Initialized on origin thread and then accessed from both threads.
- const Params* const params_;
+ const raw_ptr<const Params> params_;
std::unique_ptr<ProxyResolverV8Tracing::Bindings> bindings_;
@@ -255,13 +255,14 @@ class Job : public base::RefCountedThreadSafe<Job>,
// -------------------------------------------------------
scoped_refptr<net::PacFileData> script_data_;
- std::unique_ptr<ProxyResolverV8>* resolver_out_;
+ raw_ptr<std::unique_ptr<ProxyResolverV8>> resolver_out_;
// -------------------------------------------------------
// State specific to GET_PROXY_FOR_URL.
// -------------------------------------------------------
- net::ProxyInfo* user_results_; // Owned by caller, lives on origin thread.
+ raw_ptr<net::ProxyInfo>
+ user_results_; // Owned by caller, lives on origin thread.
GURL url_;
net::NetworkIsolationKey network_isolation_key_;
net::ProxyInfo results_;
@@ -860,7 +861,7 @@ void Job::SaveDnsToLocalCache(const std::string& host,
std::string Job::MakeDnsCacheKey(const std::string& host,
net::ProxyResolveDnsOperation op) {
- return base::StringPrintf("%d:%s", op, host.c_str());
+ return base::StringPrintf("%d:%s", static_cast<int>(op), host.c_str());
}
void Job::HandleAlertOrError(bool is_alert,
@@ -1083,12 +1084,12 @@ class ProxyResolverV8TracingFactoryImpl::CreateJob
thread_.reset();
}
- ProxyResolverV8TracingFactoryImpl* factory_;
+ raw_ptr<ProxyResolverV8TracingFactoryImpl> factory_;
std::unique_ptr<base::Thread> thread_;
std::unique_ptr<Job::Params> job_params_;
scoped_refptr<Job> create_resolver_job_;
std::unique_ptr<ProxyResolverV8> v8_resolver_;
- std::unique_ptr<ProxyResolverV8Tracing>* resolver_out_;
+ raw_ptr<std::unique_ptr<ProxyResolverV8Tracing>> resolver_out_;
net::CompletionOnceCallback callback_;
int num_outstanding_callbacks_;
};
diff --git a/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.h b/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.h
index 71f4e7ae4a6..2e14cf5d36c 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.h
+++ b/chromium/services/proxy_resolver/proxy_resolver_v8_tracing.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/base/completion_once_callback.h"
#include "net/proxy_resolution/proxy_resolver.h"
diff --git a/chromium/services/proxy_resolver/proxy_resolver_v8_tracing_unittest.cc b/chromium/services/proxy_resolver/proxy_resolver_v8_tracing_unittest.cc
index ad6b1e1d669..44f31140eba 100644
--- a/chromium/services/proxy_resolver/proxy_resolver_v8_tracing_unittest.cc
+++ b/chromium/services/proxy_resolver/proxy_resolver_v8_tracing_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
@@ -133,7 +134,7 @@ class MockBindings {
}
private:
- MockBindings* bindings_;
+ raw_ptr<MockBindings> bindings_;
base::ThreadChecker thread_checker_;
};
@@ -143,7 +144,7 @@ class MockBindings {
std::vector<std::string> alerts_;
std::vector<std::pair<int, std::string>> errors_;
- ProxyHostResolver* const host_resolver_;
+ const raw_ptr<ProxyHostResolver> host_resolver_;
base::OnceClosure error_callback_;
net::EventWaiter<Event> waiter_;
};
diff --git a/chromium/services/proxy_resolver_win/BUILD.gn b/chromium/services/proxy_resolver_win/BUILD.gn
index d0adcc215a9..7751515b1b5 100644
--- a/chromium/services/proxy_resolver_win/BUILD.gn
+++ b/chromium/services/proxy_resolver_win/BUILD.gn
@@ -6,11 +6,11 @@ assert(is_win)
component("proxy_resolver_win") {
sources = [
- # TODO(https://crbug.com/1032820): Implement Proxy Resolver
- # "windows_system_proxy_resolver_impl.cc",
- # "windows_system_proxy_resolver_impl.h",
- "winhttp_api_wrapper.cc",
+ "windows_system_proxy_resolver_impl.cc",
+ "windows_system_proxy_resolver_impl.h",
"winhttp_api_wrapper.h",
+ "winhttp_api_wrapper_impl.cc",
+ "winhttp_api_wrapper_impl.h",
"winhttp_proxy_resolver_functions.cc",
"winhttp_proxy_resolver_functions.h",
]
@@ -19,11 +19,30 @@ component("proxy_resolver_win") {
deps = [
"//base",
+ "//mojo/public/cpp/bindings",
"//url",
]
public_deps = [
"//net",
- "//net:constants",
+ "//services/proxy_resolver_win/public/mojom",
+ ]
+
+ defines = [ "IS_PROXY_RESOLVER_WIN_IMPL" ]
+}
+
+source_set("tests") {
+ testonly = true
+
+ sources = [ "windows_system_proxy_resolver_impl_unittest.cc" ]
+
+ deps = [
+ ":proxy_resolver_win",
+ "//base",
+ "//base/test:test_support",
+ "//net:test_support",
+ "//services/proxy_resolver_win/public/mojom",
+ "//testing/gmock",
+ "//testing/gtest",
]
}
diff --git a/chromium/services/proxy_resolver_win/public/cpp/OWNERS b/chromium/services/proxy_resolver_win/public/cpp/OWNERS
new file mode 100644
index 00000000000..d5fefd82012
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/public/cpp/OWNERS
@@ -0,0 +1,2 @@
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.cc b/chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.cc
new file mode 100644
index 00000000000..36fcc522046
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.cc
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.h"
+
+namespace mojo {
+
+// static
+proxy_resolver_win::mojom::WinHttpStatus
+EnumTraits<proxy_resolver_win::mojom::WinHttpStatus,
+ net::WinHttpStatus>::ToMojom(net::WinHttpStatus input) {
+ switch (input) {
+ case net::WinHttpStatus::kOk:
+ return proxy_resolver_win::mojom::WinHttpStatus::kOk;
+ case net::WinHttpStatus::kAborted:
+ return proxy_resolver_win::mojom::WinHttpStatus::kAborted;
+ case net::WinHttpStatus::kFunctionsNotLoaded:
+ return proxy_resolver_win::mojom::WinHttpStatus::kFunctionsNotLoaded;
+ case net::WinHttpStatus::kWinHttpOpenFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::kWinHttpOpenFailed;
+ case net::WinHttpStatus::kWinHttpSetTimeoutsFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpSetTimeoutsFailed;
+ case net::WinHttpStatus::kWinHttpSetStatusCallbackFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpSetStatusCallbackFailed;
+ case net::WinHttpStatus::kWinHttpGetIEProxyConfigForCurrentUserFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpGetIEProxyConfigForCurrentUserFailed;
+ case net::WinHttpStatus::kWinHttpCreateProxyResolverFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpCreateProxyResolverFailed;
+ case net::WinHttpStatus::kWinHttpGetProxyForURLExFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpGetProxyForURLExFailed;
+ case net::WinHttpStatus::kStatusCallbackFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::kStatusCallbackFailed;
+ case net::WinHttpStatus::kWinHttpGetProxyResultFailed:
+ return proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpGetProxyResultFailed;
+ case net::WinHttpStatus::kEmptyProxyList:
+ return proxy_resolver_win::mojom::WinHttpStatus::kEmptyProxyList;
+ }
+
+ return proxy_resolver_win::mojom::WinHttpStatus::kOk;
+}
+
+// static
+bool EnumTraits<proxy_resolver_win::mojom::WinHttpStatus, net::WinHttpStatus>::
+ FromMojom(proxy_resolver_win::mojom::WinHttpStatus input,
+ net::WinHttpStatus* output) {
+ switch (input) {
+ case proxy_resolver_win::mojom::WinHttpStatus::kOk:
+ *output = net::WinHttpStatus::kOk;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kAborted:
+ *output = net::WinHttpStatus::kAborted;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kFunctionsNotLoaded:
+ *output = net::WinHttpStatus::kFunctionsNotLoaded;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kWinHttpOpenFailed:
+ *output = net::WinHttpStatus::kWinHttpOpenFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kWinHttpSetTimeoutsFailed:
+ *output = net::WinHttpStatus::kWinHttpSetTimeoutsFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpSetStatusCallbackFailed:
+ *output = net::WinHttpStatus::kWinHttpSetStatusCallbackFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpGetIEProxyConfigForCurrentUserFailed:
+ *output =
+ net::WinHttpStatus::kWinHttpGetIEProxyConfigForCurrentUserFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpCreateProxyResolverFailed:
+ *output = net::WinHttpStatus::kWinHttpCreateProxyResolverFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::
+ kWinHttpGetProxyForURLExFailed:
+ *output = net::WinHttpStatus::kWinHttpGetProxyForURLExFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kStatusCallbackFailed:
+ *output = net::WinHttpStatus::kStatusCallbackFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kWinHttpGetProxyResultFailed:
+ *output = net::WinHttpStatus::kWinHttpGetProxyResultFailed;
+ return true;
+ case proxy_resolver_win::mojom::WinHttpStatus::kEmptyProxyList:
+ *output = net::WinHttpStatus::kEmptyProxyList;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace mojo
diff --git a/chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.h b/chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.h
new file mode 100644
index 00000000000..7bb36993ce9
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.h
@@ -0,0 +1,26 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_PROXY_RESOLVER_WIN_PUBLIC_CPP_PROXY_RESOLVER_WIN_MOJOM_TRAITS_H_
+#define SERVICES_PROXY_RESOLVER_WIN_PUBLIC_CPP_PROXY_RESOLVER_WIN_MOJOM_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "net/proxy_resolution/win/winhttp_status.h"
+#include "services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<proxy_resolver_win::mojom::WinHttpStatus,
+ net::WinHttpStatus> {
+ static proxy_resolver_win::mojom::WinHttpStatus ToMojom(
+ net::WinHttpStatus input);
+
+ static bool FromMojom(proxy_resolver_win::mojom::WinHttpStatus input,
+ net::WinHttpStatus* output);
+};
+
+} // namespace mojo
+
+#endif // SERVICES_PROXY_RESOLVER_WIN_PUBLIC_CPP_PROXY_RESOLVER_WIN_MOJOM_TRAITS_H_
diff --git a/chromium/services/proxy_resolver_win/public/mojom/BUILD.gn b/chromium/services/proxy_resolver_win/public/mojom/BUILD.gn
new file mode 100644
index 00000000000..4ed77170169
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/public/mojom/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(is_win)
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+ sources = [ "proxy_resolver_win.mojom" ]
+ deps = [
+ "//services/network/public/mojom:mojom_proxy_config",
+ "//url/mojom:url_mojom_gurl",
+ ]
+ public_deps = [ "//sandbox/policy/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 = "proxy_resolver_win.mojom.WinHttpStatus"
+ cpp = "::net::WinHttpStatus"
+ },
+ ]
+ traits_headers = [ "//services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.h" ]
+ traits_sources = [ "//services/proxy_resolver_win/public/cpp/proxy_resolver_win_mojom_traits.cc" ]
+ },
+ ]
+}
diff --git a/chromium/services/proxy_resolver_win/public/mojom/OWNERS b/chromium/services/proxy_resolver_win/public/mojom/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/public/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom b/chromium/services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom
new file mode 100644
index 00000000000..1b292430c19
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module proxy_resolver_win.mojom;
+
+import "sandbox/policy/mojom/sandbox.mojom";
+import "services/network/public/mojom/proxy_config.mojom";
+import "url/mojom/url.mojom";
+
+// Keep in sync with net::WinHttpStatus. See /net code for details.
+enum WinHttpStatus {
+ kOk,
+ kAborted,
+ kFunctionsNotLoaded,
+ kWinHttpOpenFailed,
+ kWinHttpSetTimeoutsFailed,
+ kWinHttpSetStatusCallbackFailed,
+ kWinHttpGetIEProxyConfigForCurrentUserFailed,
+ kWinHttpCreateProxyResolverFailed,
+ kWinHttpGetProxyForURLExFailed,
+ kStatusCallbackFailed,
+ kWinHttpGetProxyResultFailed,
+ kEmptyProxyList,
+};
+
+// This defines a simple interface for asynchronously resolving a proxy using
+// WinHttp APIs.
+[ServiceSandbox=sandbox.mojom.Sandbox.kWindowsSystemProxyResolver]
+interface WindowsSystemProxyResolver {
+ // Only a `url` is needed to resolve a proxy. All OS proxy configurations will
+ // be read when this is called. This assumes that there are no Chrome-specific
+ // proxy configurations. The result, successful or otherwise, will be provided
+ // in the callback.
+ // The `proxy_list` is the set of proxies that can be used for a given URL
+ // provided by WinHttp. If there was an error, `proxy_list` will be empty. The
+ // `winhttp_status` contains any relevant error and will be OK if the call
+ // succeeded. If `winhttp_status` is not OK, there may also be a corresponding
+ // `windows_error` for a failed WinHttp API call.
+ GetProxyForUrl(url.mojom.Url url) => (network.mojom.ProxyList proxy_list,
+ WinHttpStatus winhttp_status,
+ int32 windows_error);
+};
diff --git a/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.cc b/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.cc
index fdebd438b60..336d3559367 100644
--- a/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.cc
+++ b/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.cc
@@ -5,19 +5,22 @@
#include "services/proxy_resolver_win/windows_system_proxy_resolver_impl.h"
#include <cwchar>
-#include <string>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
+#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "net/base/host_port_pair.h"
-#include "net/base/net_errors.h"
#include "net/base/proxy_server.h"
-#include "services/proxy_resolver_win/windows_system_proxy_resolution_request.h"
-#include "services/proxy_resolver_win/winhttp_api_wrapper.h"
+#include "net/proxy_resolution/proxy_list.h"
+#include "services/proxy_resolver_win/winhttp_api_wrapper_impl.h"
+#include "services/proxy_resolver_win/winhttp_proxy_resolver_functions.h"
+#include "url/gurl.h"
#include "url/url_canon.h"
namespace proxy_resolver_win {
@@ -26,23 +29,23 @@ namespace {
bool GetProxyServerFromWinHttpResultEntry(
const WINHTTP_PROXY_RESULT_ENTRY& result_entry,
- ProxyServer* out_proxy_server) {
+ net::ProxyServer* out_proxy_server) {
// TODO(https://crbug.com/1032820): Include net logs for proxy bypass
if (!result_entry.fProxy) {
- *out_proxy_server = ProxyServer::Direct();
+ *out_proxy_server = net::ProxyServer::Direct();
return true;
}
- ProxyServer::Scheme scheme = ProxyServer::Scheme::SCHEME_INVALID;
+ net::ProxyServer::Scheme scheme = net::ProxyServer::Scheme::SCHEME_INVALID;
switch (result_entry.ProxyScheme) {
case (INTERNET_SCHEME_HTTP):
- scheme = ProxyServer::Scheme::SCHEME_HTTP;
+ scheme = net::ProxyServer::Scheme::SCHEME_HTTP;
break;
case (INTERNET_SCHEME_HTTPS):
- scheme = ProxyServer::Scheme::SCHEME_HTTPS;
+ scheme = net::ProxyServer::Scheme::SCHEME_HTTPS;
break;
case (INTERNET_SCHEME_SOCKS):
- scheme = ProxyServer::Scheme::SCHEME_SOCKS4;
+ scheme = net::ProxyServer::Scheme::SCHEME_SOCKS4;
break;
default:
LOG(WARNING) << "Of the possible proxy schemes returned by WinHttp, "
@@ -52,7 +55,7 @@ bool GetProxyServerFromWinHttpResultEntry(
break;
}
- if (scheme == ProxyServer::Scheme::SCHEME_INVALID)
+ if (scheme == net::ProxyServer::Scheme::SCHEME_INVALID)
return false;
// Chrome expects a specific port from WinHttp. The WinHttp documentation on
@@ -63,8 +66,8 @@ bool GetProxyServerFromWinHttpResultEntry(
return false;
}
- // Since there is a proxy in the result (i.e. |fProxy| is TRUE), the
- // |pwszProxy| is guaranteed to be non-null and non-empty.
+ // Since there is a proxy in the result (i.e. `fProxy` is TRUE), the
+ // `pwszProxy` is guaranteed to be non-null and non-empty.
DCHECK(!!result_entry.pwszProxy);
DCHECK(wcslen(result_entry.pwszProxy) > 0);
@@ -74,79 +77,126 @@ bool GetProxyServerFromWinHttpResultEntry(
const int kInitialBufferSize = 256;
url::RawCanonOutputT<char16_t, kInitialBufferSize> punycode_output;
if (!url::IDNToASCII(base::as_u16cstr(host_wide), host_wide.length(),
- &punycode_output))
+ &punycode_output)) {
return false;
+ }
host_wide.assign(base::as_wcstr(punycode_output.data()),
punycode_output.length());
}
- // At this point the string in |host_wide| is ASCII.
+ // At this point the string in `host_wide` is ASCII.
std::string host;
if (!base::WideToUTF8(host_wide.data(), host_wide.length(), &host))
return false;
- HostPortPair host_and_port(host, result_entry.ProxyPort);
- *out_proxy_server = ProxyServer(scheme, host_and_port);
+ net::HostPortPair host_and_port(host, result_entry.ProxyPort);
+ *out_proxy_server = net::ProxyServer(scheme, host_and_port);
return true;
}
} // namespace
-// static
-scoped_refptr<WindowsSystemProxyResolverImpl>
-WindowsSystemProxyResolverImpl::CreateWindowsSystemProxyResolver() {
- scoped_refptr<WindowsSystemProxyResolverImpl> resolver =
- base::WrapRefCounted(new WindowsSystemProxyResolverImpl(
- std::make_unique<WinHttpAPIWrapper>()));
- if (resolver->Initialize()) {
- return resolver;
+// Encapsulates an in-flight WinHttp proxy resolution request. This also owns
+// the GetProxyForUrlCallback and will attempt to supply that callback with the
+// proxy result once WinHttp returns.
+class WindowsSystemProxyResolverImpl::Request {
+ public:
+ Request(WindowsSystemProxyResolverImpl* parent,
+ GetProxyForUrlCallback callback);
+ Request(const Request&) = delete;
+ Request& operator=(const Request&) = delete;
+ ~Request();
+
+ // Sets up and kicks off proxy resolution using WinHttp.
+ bool Start(const GURL& url);
+
+ base::SequencedTaskRunner* sequenced_task_runner() {
+ return sequenced_task_runner_.get();
}
- return nullptr;
-}
-WindowsSystemProxyResolverImpl::WindowsSystemProxyResolverImpl(
- std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper)
- : winhttp_api_wrapper_(std::move(winhttp_api_wrapper)),
- sequenced_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
-WindowsSystemProxyResolverImpl::~WindowsSystemProxyResolverImpl() = default;
+ // Called from WinHttpStatusCallback on the right sequence. This will make
+ // decisions about what to do from the results of the proxy resolution call.
+ void DoWinHttpStatusCallback(HINTERNET resolver_handle,
+ DWORD status,
+ int windows_error);
-bool WindowsSystemProxyResolverImpl::Initialize() {
- if (!winhttp_api_wrapper_->CallWinHttpOpen())
- return false;
+ private:
+ // On a successful call to WinHttpGetProxyForUrlEx(), this translates WinHttp
+ // results into Chromium-friendly structures and reports the result.
+ void GetProxyResultForCallback();
- // Since this session handle will never be used for WinHTTP connections,
- // these timeouts don't really mean much individually. However, WinHTTP's
- // out of process PAC resolution will use a combined (sum of all timeouts)
- // value to wait for an RPC reply.
- if (!winhttp_api_wrapper_->CallWinHttpSetTimeouts(10000, 10000, 5000, 5000))
- return false;
+ // Notifies `callback_` of the proxy result.
+ void ReportResult(const net::ProxyList& proxy_list,
+ net::WinHttpStatus winhttp_status,
+ int windows_error);
- // This sets the entry point for every callback in the WinHttp session created
- // above.
- if (!winhttp_api_wrapper_->CallWinHttpSetStatusCallback(
- &WindowsSystemProxyResolverImpl::WinHttpStatusCallback))
- return false;
+ WinHttpAPIWrapper* winhttp_api_wrapper() {
+ return parent_->winhttp_api_wrapper_.get();
+ }
- return true;
+ // The WindowsSystemProxyResolverImpl manages the lifetime of this object. The
+ // Request cannot outlive the WindowsSystemProxyResolverImpl. Thus, it is safe
+ // to hold on to a raw pointer.
+ const raw_ptr<WindowsSystemProxyResolverImpl> parent_;
+ GetProxyForUrlCallback callback_;
+ HINTERNET resolver_handle_;
+ scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+WindowsSystemProxyResolverImpl::Request::Request(
+ WindowsSystemProxyResolverImpl* parent,
+ GetProxyForUrlCallback callback)
+ : parent_(parent),
+ callback_(std::move(callback)),
+ resolver_handle_(nullptr),
+ sequenced_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+
+WindowsSystemProxyResolverImpl::Request::~Request() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // If the `resolver_handle_` is not null, then there may be an in-flight
+ // WinHttp call. This could conceivably happen in some shutdown scenarios. In
+ // this case, close the handle to cancel the operation.
+ if (resolver_handle_) {
+ winhttp_api_wrapper()->CallWinHttpCloseHandle(resolver_handle_);
+ resolver_handle_ = nullptr;
+ }
}
-bool WindowsSystemProxyResolverImpl::GetProxyForUrl(
- WindowsSystemProxyResolutionRequest* callback_target,
- const std::string& url) {
+bool WindowsSystemProxyResolverImpl::Request::Start(const GURL& url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(https://crbug.com/1032820): Use better/distinct net errors.
+ net::WinHttpStatus winhttp_status = parent_->EnsureInitialized();
+ if (winhttp_status != net::WinHttpStatus::kOk) {
+ const int error = GetLastError();
+ ReportResult(net::ProxyList(), winhttp_status, error);
+ return false;
+ }
+
// Fetch the current system proxy settings. These are per current network
// interface and per current user.
ScopedIEConfig scoped_ie_config;
- if (!winhttp_api_wrapper_->CallWinHttpGetIEProxyConfigForCurrentUser(
- scoped_ie_config.config()))
+ if (!winhttp_api_wrapper()->CallWinHttpGetIEProxyConfigForCurrentUser(
+ scoped_ie_config.config())) {
+ const int error = GetLastError();
+ ReportResult(
+ net::ProxyList(),
+ net::WinHttpStatus::kWinHttpGetIEProxyConfigForCurrentUserFailed,
+ error);
return false;
+ }
// This will create a handle specifically for WinHttpGetProxyForUrlEx().
- HINTERNET resolver_handle = nullptr;
- if (!winhttp_api_wrapper_->CallWinHttpCreateProxyResolver(&resolver_handle))
+ if (!winhttp_api_wrapper()->CallWinHttpCreateProxyResolver(
+ &resolver_handle_)) {
+ const int error = GetLastError();
+ ReportResult(net::ProxyList(),
+ net::WinHttpStatus::kWinHttpCreateProxyResolverFailed, error);
return false;
+ }
// WinHttp will do all necessary proxy resolution fallback for this request.
// If automatic settings aren't configured or fail, it'll use any manually
@@ -154,7 +204,7 @@ bool WindowsSystemProxyResolverImpl::GetProxyForUrl(
// tells the APIs to pick up manually configured proxies.
//
// Separately, Windows allows different proxy settings for different network
- // interfaces. The WINHTTP_AUTOPROXY_OPTIONS flag tells WinHttp to
+ // interfaces. The WINHTTP_AUTOPROXY_ALLOW_CM flag tells WinHttp to
// differentiate between these settings and to get the proxy that's most
// specific to the current interface.
WINHTTP_AUTOPROXY_OPTIONS autoproxy_options = {0};
@@ -186,185 +236,219 @@ bool WindowsSystemProxyResolverImpl::GetProxyForUrl(
// Now that everything is set-up, ask WinHTTP to get the actual proxy list.
const DWORD_PTR context = reinterpret_cast<DWORD_PTR>(this);
- if (!winhttp_api_wrapper_->CallWinHttpGetProxyForUrlEx(
- resolver_handle, url, &autoproxy_options, context)) {
- winhttp_api_wrapper_->CallWinHttpCloseHandle(resolver_handle);
+ if (!winhttp_api_wrapper()->CallWinHttpGetProxyForUrlEx(
+ resolver_handle_, url.spec(), &autoproxy_options, context)) {
+ const int error = GetLastError();
+ winhttp_api_wrapper()->CallWinHttpCloseHandle(resolver_handle_);
+ resolver_handle_ = nullptr;
+ ReportResult(net::ProxyList(),
+ net::WinHttpStatus::kWinHttpGetProxyForURLExFailed, error);
return false;
}
- // Saves of the object which will receive the callback once the operation
- // completes.
- AddPendingCallbackTarget(callback_target, resolver_handle);
-
- // On a successful call to WinHttpGetProxyForUrlEx(), the callback set by
- // CallWinHttpSetStatusCallback() is guaranteed to be called exactly once.
- // That may happen at any time on any thread. In order to make sure this
- // object does not destruct before that callback occurs, it must AddRef()
- // itself. This reference will be Release()'d in the callback.
- base::RefCountedThreadSafe<WindowsSystemProxyResolverImpl>::AddRef();
-
return true;
}
-void WindowsSystemProxyResolverImpl::AddPendingCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target,
- HINTERNET resolver_handle) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- pending_callback_target_map_[callback_target] = resolver_handle;
-}
-
-void WindowsSystemProxyResolverImpl::RemovePendingCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- pending_callback_target_map_.erase(callback_target);
-}
-
-bool WindowsSystemProxyResolverImpl::HasPendingCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return (pending_callback_target_map_.find(callback_target) !=
- pending_callback_target_map_.end());
-}
-
-WindowsSystemProxyResolutionRequest*
-WindowsSystemProxyResolverImpl::LookupCallbackTargetFromResolverHandle(
- HINTERNET resolver_handle) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- WindowsSystemProxyResolutionRequest* pending_callback_target = nullptr;
- for (auto target : pending_callback_target_map_) {
- if (target.second == resolver_handle) {
- pending_callback_target = target.first;
- break;
- }
- }
- return pending_callback_target;
-}
-
-// static
-void CALLBACK
-WindowsSystemProxyResolverImpl::WinHttpStatusCallback(HINTERNET resolver_handle,
- DWORD_PTR context,
- DWORD status,
- void* info,
- DWORD info_len) {
- DCHECK(resolver_handle);
- DCHECK(context);
- WindowsSystemProxyResolverImpl* windows_system_proxy_resolver =
- reinterpret_cast<WindowsSystemProxyResolverImpl*>(context);
-
- // Make a copy of any error information in |info| so it can be accessed from
- // the subsequently posted task. The |info| pointer's lifetime is managed by
- // WinHTTP and hence is not valid once this frame returns.
- int windows_error = S_OK;
- if (info && status == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) {
- WINHTTP_ASYNC_RESULT* result = static_cast<WINHTTP_ASYNC_RESULT*>(info);
- windows_error = result->dwError;
- }
-
- // It is possible for PostTask() to fail (ex: during shutdown). In that case,
- // the WindowsSystemProxyResolverImpl in |context| will leak. This is expected
- // to be either unusual or to occur during shutdown, where a leak doesn't
- // matter. Since calling the |context| on the wrong thread may be problematic,
- // it will be allowed to leak here if PostTask() fails.
- windows_system_proxy_resolver->sequenced_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WindowsSystemProxyResolverImpl::DoWinHttpStatusCallback,
- windows_system_proxy_resolver, resolver_handle, status,
- windows_error));
-}
-
-void WindowsSystemProxyResolverImpl::DoWinHttpStatusCallback(
+void WindowsSystemProxyResolverImpl::Request::DoWinHttpStatusCallback(
HINTERNET resolver_handle,
DWORD status,
int windows_error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // The |resolver_handle| should correspond to a HINTERNET resolver_handle in
- // |pending_callback_target_map_| unless the associated attempt to get a proxy
- // for an URL has been cancelled.
- WindowsSystemProxyResolutionRequest* pending_callback_target =
- LookupCallbackTargetFromResolverHandle(resolver_handle);
+ // The `resolver_handle` should correspond to `resolver_handle_`.
+ DCHECK_EQ(resolver_handle_, resolver_handle);
// There is no work to do if this request has been cancelled.
- if (pending_callback_target) {
+ if (callback_) {
switch (status) {
case WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE:
- GetProxyResultForCallbackTarget(pending_callback_target,
- resolver_handle);
+ GetProxyResultForCallback();
break;
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
- HandleErrorForCallbackTarget(pending_callback_target, windows_error);
+ // TODO(https://crbug.com/1032820): Use a better/distinct net error.
+ ReportResult(net::ProxyList(),
+ net::WinHttpStatus::kStatusCallbackFailed, windows_error);
break;
default:
LOG(WARNING) << "DoWinHttpStatusCallback() expects only callbacks for "
"WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE and "
"WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, not: "
<< status;
- HandleErrorForCallbackTarget(pending_callback_target, E_UNEXPECTED);
+ ReportResult(net::ProxyList(),
+ net::WinHttpStatus::kStatusCallbackFailed, status);
break;
}
-
- // No matter what happened above, the |pending_callback_target| should no
- // longer be in the |pending_callback_target_map_|. Either the callback was
- // handled or it was cancelled. This pointer will be explicitly cleared to
- // make it obvious that it can no longer be used safely.
- DCHECK(!HasPendingCallbackTarget(pending_callback_target));
- pending_callback_target = nullptr;
}
- // The HINTERNET |resolver_handle| for this attempt at getting a proxy is no
+ // The HINTERNET `resolver_handle_` for this attempt at getting a proxy is no
// longer needed.
- winhttp_api_wrapper_->CallWinHttpCloseHandle(resolver_handle);
+ winhttp_api_wrapper()->CallWinHttpCloseHandle(resolver_handle_);
+ resolver_handle_ = nullptr;
- // The current WindowsSystemProxyResolverImpl object may now be Release()'d on
- // the correct sequence after all work is done, thus balancing out the
- // AddRef() from WinHttpGetProxyForUrlEx().
- base::RefCountedThreadSafe<WindowsSystemProxyResolverImpl>::Release();
+ // At this point, the mojo callback has definitely been called.
+ DCHECK(callback_.is_null());
+
+ // Now, it's finally safe to delete this object.
+ auto it = parent_->requests_.find(this);
+ DCHECK(it != parent_->requests_.end());
+ parent_->requests_.erase(it);
+
+ // DO NOT ADD ANYTHING BELOW THIS LINE, THE OBJECT HAS NOW BEEN DESTROYED.
}
-void WindowsSystemProxyResolverImpl::GetProxyResultForCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target,
- HINTERNET resolver_handle) {
+void WindowsSystemProxyResolverImpl::Request::GetProxyResultForCallback() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(HasPendingCallbackTarget(callback_target));
-
+ // TODO(https://crbug.com/1032820): Use better/distinct net errors.
WINHTTP_PROXY_RESULT proxy_result = {0};
- if (!winhttp_api_wrapper_->CallWinHttpGetProxyResult(resolver_handle,
- &proxy_result)) {
- // TODO(https://crbug.com/1032820): Use a more detailed net error.
- callback_target->AsynchronousProxyResolutionComplete(ProxyList(),
- ERR_FAILED, 0);
+ if (!winhttp_api_wrapper()->CallWinHttpGetProxyResult(resolver_handle_,
+ &proxy_result)) {
+ const int error = GetLastError();
+ ReportResult(net::ProxyList(),
+ net::WinHttpStatus::kWinHttpGetProxyResultFailed, error);
return;
}
// Translate the results for ProxyInfo.
- ProxyList proxy_list;
+ net::ProxyList proxy_list;
for (DWORD i = 0u; i < proxy_result.cEntries; ++i) {
- ProxyServer proxy_server;
+ net::ProxyServer proxy_server;
if (GetProxyServerFromWinHttpResultEntry(proxy_result.pEntries[i],
- &proxy_server))
+ &proxy_server)) {
proxy_list.AddProxyServer(proxy_server);
+ }
}
- // The |proxy_result| must be freed.
- winhttp_api_wrapper_->CallWinHttpFreeProxyResult(&proxy_result);
+ // The `proxy_result` must be freed.
+ winhttp_api_wrapper()->CallWinHttpFreeProxyResult(&proxy_result);
// The consumer of this proxy resolution may not understand an empty proxy
// list. Thus, this case is considered an error.
- int net_error = proxy_list.IsEmpty() ? ERR_FAILED : OK;
- callback_target->AsynchronousProxyResolutionComplete(proxy_list, net_error,
- 0);
+ net::WinHttpStatus winhttp_status = proxy_list.IsEmpty()
+ ? net::WinHttpStatus::kEmptyProxyList
+ : net::WinHttpStatus::kOk;
+ ReportResult(proxy_list, winhttp_status, 0);
}
-void WindowsSystemProxyResolverImpl::HandleErrorForCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target,
+void WindowsSystemProxyResolverImpl::Request::ReportResult(
+ const net::ProxyList& proxy_list,
+ net::WinHttpStatus winhttp_status,
int windows_error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(HasPendingCallbackTarget(callback_target));
+ if (!callback_)
+ return;
+
+ std::move(callback_).Run(proxy_list, winhttp_status, windows_error);
+ callback_.Reset();
+
+ // Even though there are no more mojo calls to make, it is not safe to delete
+ // this object yet. To be absolutely sure that WinHttpStatusCallback() does
+ // not attempt to dereference a freed object, the only times we delete this
+ // object are when we fail to call into WinHttp APIs completely (i.e. we do
+ // not expect a callback) and when the WinHttp callback completes in
+ // DoWinHttpStatusCallback().
+}
+
+WindowsSystemProxyResolverImpl::WindowsSystemProxyResolverImpl(
+ mojo::PendingReceiver<mojom::WindowsSystemProxyResolver> receiver)
+ : receiver_(this, std::move(receiver)) {}
+WindowsSystemProxyResolverImpl::~WindowsSystemProxyResolverImpl() {
+ // The WindowsSystemProxyResolverImpl must outlive every Request it owns.
+ CHECK(requests_.empty());
+}
+
+void WindowsSystemProxyResolverImpl::SetCreateWinHttpAPIWrapperForTesting(
+ std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper_for_testing) {
+ winhttp_api_wrapper_ = std::move(winhttp_api_wrapper_for_testing);
+}
+
+void WindowsSystemProxyResolverImpl::GetProxyForUrl(
+ const GURL& url,
+ GetProxyForUrlCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::unique_ptr<Request> request =
+ std::make_unique<Request>(this, std::move(callback));
+
+ // If the request fails to start, it will internally report that to
+ // `callback`. After that, it's safe to delete this `request`.
+ if (request->Start(url))
+ requests_.insert(std::move(request));
+}
+
+net::WinHttpStatus WindowsSystemProxyResolverImpl::EnsureInitialized() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (initialized_)
+ return net::WinHttpStatus::kOk;
+
+ // TODO(https://crbug.com/1032820): Limit the number of times this can
+ // fail to initialize.
+
+ if (!WinHttpProxyResolverFunctions::GetInstance()
+ .are_all_functions_loaded()) {
+ LOG(ERROR) << "Failed to load functions necessary for "
+ "WindowsSystemProxyResolutionService!";
+ return net::WinHttpStatus::kFunctionsNotLoaded;
+ }
+
+ // The `winhttp_api_wrapper_` is intended to only get set when initialization
+ // is successful. However, it may have been pre-populated via
+ // SetCreateWinHttpAPIWrapperForTesting(). In those cases, use that object
+ // instead of creating a new one.
+ std::unique_ptr<WinHttpAPIWrapper> uninitialized_winhttp_api_wrapper;
+ if (winhttp_api_wrapper_) {
+ uninitialized_winhttp_api_wrapper = std::move(winhttp_api_wrapper_);
+ winhttp_api_wrapper_.reset();
+ } else {
+ uninitialized_winhttp_api_wrapper =
+ std::make_unique<WinHttpAPIWrapperImpl>();
+ }
+
+ if (!uninitialized_winhttp_api_wrapper->CallWinHttpOpen())
+ return net::WinHttpStatus::kWinHttpOpenFailed;
+
+ // Since this session handle will never be used for WinHTTP connections,
+ // these timeouts don't really mean much individually. However, WinHTTP's
+ // out of process PAC resolution will use a combined (sum of all timeouts)
+ // value to wait for an RPC reply.
+ if (!uninitialized_winhttp_api_wrapper->CallWinHttpSetTimeouts(10000, 10000,
+ 5000, 5000)) {
+ return net::WinHttpStatus::kWinHttpSetTimeoutsFailed;
+ }
+
+ // This sets the entry point for every callback in the WinHttp session created
+ // above.
+ if (!uninitialized_winhttp_api_wrapper->CallWinHttpSetStatusCallback(
+ &WindowsSystemProxyResolverImpl::WinHttpStatusCallback)) {
+ return net::WinHttpStatus::kWinHttpSetStatusCallbackFailed;
+ }
+
+ initialized_ = true;
+ winhttp_api_wrapper_ = std::move(uninitialized_winhttp_api_wrapper);
+ return net::WinHttpStatus::kOk;
+}
+
+// static
+void CALLBACK
+WindowsSystemProxyResolverImpl::WinHttpStatusCallback(HINTERNET resolver_handle,
+ DWORD_PTR context,
+ DWORD status,
+ void* info,
+ DWORD info_len) {
+ DCHECK(resolver_handle);
+ DCHECK(context);
+ Request* request = reinterpret_cast<Request*>(context);
+
+ // Make a copy of any error information in `info` so it can be accessed from
+ // the subsequently posted task. The `info` pointer's lifetime is managed by
+ // WinHTTP and hence is not valid once this frame returns.
+ int windows_error = S_OK;
+ if (info && status == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) {
+ WINHTTP_ASYNC_RESULT* result = static_cast<WINHTTP_ASYNC_RESULT*>(info);
+ windows_error = result->dwError;
+ }
- // TODO(https://crbug.com/1032820): Use a more detailed net error.
- callback_target->AsynchronousProxyResolutionComplete(ProxyList(), ERR_FAILED,
- windows_error);
+ request->sequenced_task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&Request::DoWinHttpStatusCallback,
+ base::Unretained(request), resolver_handle,
+ status, windows_error));
}
} // namespace proxy_resolver_win
diff --git a/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.h b/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.h
index b6c63bfd969..5ad683c14da 100644
--- a/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.h
+++ b/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl.h
@@ -9,121 +9,92 @@
#include <winhttp.h>
#include <memory>
+#include <set>
#include <string>
-#include <unordered_map>
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/component_export.h"
+#include "base/containers/unique_ptr_adapters.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/win/windows_types.h"
-#include "net/base/net_export.h"
-#include "net/proxy_resolution/proxy_list.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "net/proxy_resolution/win/winhttp_status.h"
+#include "services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom.h"
+
+class GURL;
namespace proxy_resolver_win {
-class WindowsSystemProxyResolutionRequest;
class WinHttpAPIWrapper;
-// This provides a layer of abstraction between calling code and
-// Windows-specific code. It is shared between the
-// WindowsSystemProxyResolutionService and inflight WinHttp callbacks.
-// Internally, it takes care of all interaction with WinHttp. The only time this
-// object is ever accessed outside of its sequence is during the WinHttp
-// callback. For the sake of that callback, this must be RefCountedThreadSafe.
-class NET_EXPORT WindowsSystemProxyResolverImpl
- : public base::RefCountedThreadSafe<WindowsSystemProxyResolverImpl> {
+// This implements a mojo service to resolve proxies on Windows using only
+// WinHttp APIs. It enables support for features like the Name Resolution Proxy
+// Table (NRPT), DirectAccess, and per-interface proxy configurations. The
+// WindowsSystemProxyResolverImpl attempts to create a HINTERNET session handle
+// for all proxy resolutions, which should last for the lifetime of the process.
+// Once created, incoming proxy resolution requests can be forwarded to WinHttp,
+// which is guaranteed to return exactly once per request. The
+// WindowsSystemProxyResolverImpl is also in charge of managing the lifetime of
+// each of these requests, which will reply via callback once they have
+// received a response from WinHttp.
+class COMPONENT_EXPORT(PROXY_RESOLVER_WIN) WindowsSystemProxyResolverImpl
+ : public mojom::WindowsSystemProxyResolver {
public:
- static scoped_refptr<WindowsSystemProxyResolverImpl>
- CreateWindowsSystemProxyResolver();
+ explicit WindowsSystemProxyResolverImpl(
+ mojo::PendingReceiver<mojom::WindowsSystemProxyResolver> receiver);
WindowsSystemProxyResolverImpl(const WindowsSystemProxyResolverImpl&) =
delete;
WindowsSystemProxyResolverImpl& operator=(
const WindowsSystemProxyResolverImpl&) = delete;
- // This will first fetch the current system proxy settings by calling into
- // WinHttpGetIEProxyConfigForCurrentUser() and then resolve the proxy using
- // those settings as an input into WinHttpGetProxyForUrlEx().
- bool GetProxyForUrl(WindowsSystemProxyResolutionRequest* callback_target,
- const std::string& url) WARN_UNUSED_RESULT;
-
- // After calling GetProxyForUrl(), a |callback_target| is saved internally for
- // when proxy resolution is complete. When a
- // WindowsSystemProxyResolutionRequest wants to avoid receiving a callback,
- // it must remove itself from the list of pending callback targets.
- void RemovePendingCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target);
- bool HasPendingCallbackTarget(WindowsSystemProxyResolutionRequest*
- callback_target) const WARN_UNUSED_RESULT;
+ ~WindowsSystemProxyResolverImpl() override;
- private:
- friend class base::RefCountedThreadSafe<WindowsSystemProxyResolverImpl>;
- friend class WindowsSystemProxyResolverTest;
+ void SetCreateWinHttpAPIWrapperForTesting(
+ std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper_for_testing);
- explicit WindowsSystemProxyResolverImpl(
- std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper);
- ~WindowsSystemProxyResolverImpl();
+ // mojom::WindowsSystemProxyResolver implementation
+ void GetProxyForUrl(const GURL& url,
+ GetProxyForUrlCallback callback) override;
+
+ private:
+ friend class WindowsSystemProxyResolverImplTest;
+ class Request;
// Sets up the WinHttp session that will be used throughout the lifetime of
// this object.
- bool Initialize();
-
- // These will interact with |pending_callback_target_map_|.
- void AddPendingCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target,
- HINTERNET handle);
- WindowsSystemProxyResolutionRequest* LookupCallbackTargetFromResolverHandle(
- HINTERNET resolver_handle) const;
+ net::WinHttpStatus EnsureInitialized();
// This is the callback provided to WinHttp. Once a call to resolve a proxy
- // succeeds or errors out, it'll call into here with |context| being a pointer
- // to a WindowsSystemProxyResolverImpl that has been kept alive. This callback
- // can hit in any thread and will immediately post a task to the right
- // sequence.
+ // succeeds or errors out, it'll call into here with `context` being a pointer
+ // to a Request that has been kept alive. This callback can hit in any thread
+ // and will immediately post a task to the right sequence.
static void CALLBACK WinHttpStatusCallback(HINTERNET resolver_handle,
DWORD_PTR context,
DWORD status,
void* info,
DWORD info_len);
- // Called from WinHttpStatusCallback on the right sequence. This will make
- // decisions about what to do from the results of the proxy resolution call.
- // Note that the WindowsSystemProxyResolutionRequest that asked for this proxy
- // may have decided they no longer need an answer (ex: the request has gone
- // away), so this function has to deal with that situation too.
- void DoWinHttpStatusCallback(HINTERNET resolver_handle,
- DWORD status,
- int windows_error);
-
- // On a successful call to WinHttpGetProxyForUrlEx(), this translates WinHttp
- // results into Chromium-friendly structures before notifying the right
- // WindowsSystemProxyResolutionRequest.
- void GetProxyResultForCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target,
- HINTERNET resolver_handle);
-
- // On a failed call to WinHttpGetProxyForUrlEx(), this will notify the right
- // WindowsSystemProxyResolutionRequest of the error.
- void HandleErrorForCallbackTarget(
- WindowsSystemProxyResolutionRequest* callback_target,
- int windows_error);
-
- // This is a thin wrapper over WinHttp APIs that may be overridden for
- // testing.
+ // Set to true once a WinHttp session has been successfully created and
+ // configured.
+ bool initialized_ = false;
+
+ // This is a thin wrapper over WinHttp APIs.
std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper_;
- // This is the mapping of WindowsSystemProxyResolutionRequest objects that
- // called GetProxyForUrl() to the handle that's being used for their proxy
- // resolution call. Upon receiving a callback from WinHttp (which includes an
- // HINTERNET handle), a reverse lookup here will get the right
- // WindowsSystemProxyResolutionRequest to use.
- std::unordered_map<WindowsSystemProxyResolutionRequest*, HINTERNET>
- pending_callback_target_map_;
+ // Tests may set their own wrapper that will get filled into
+ // `winhttp_api_wrapper_` when needed instead of creating a new
+ // WinHttpAPIWrapper.
+ std::unique_ptr<WinHttpAPIWrapper> winhttp_api_wrapper_for_testing_;
+
+ // This is the set of in-flight WinHttp proxy resolution calls. Each Request
+ // will be kept alive for the duration of that call. After that, the Request
+ // will attempt to respond to the callback and then get deleted.
+ std::set<std::unique_ptr<Request>, base::UniquePtrComparator> requests_;
+
+ mojo::Receiver<mojom::WindowsSystemProxyResolver> receiver_;
SEQUENCE_CHECKER(sequence_checker_);
- scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
};
} // namespace proxy_resolver_win
diff --git a/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl_unittest.cc b/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl_unittest.cc
new file mode 100644
index 00000000000..f7925ccddd0
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/windows_system_proxy_resolver_impl_unittest.cc
@@ -0,0 +1,641 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/proxy_resolver_win/windows_system_proxy_resolver_impl.h"
+
+#include <windows.h>
+#include <winhttp.h>
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/task_environment.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/net_errors.h"
+#include "net/base/proxy_server.h"
+#include "net/base/proxy_string_util.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_list.h"
+#include "net/proxy_resolution/win/windows_system_proxy_resolution_service.h"
+#include "net/test/test_with_task_environment.h"
+#include "services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom.h"
+#include "services/proxy_resolver_win/winhttp_api_wrapper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace proxy_resolver_win {
+
+namespace {
+
+const GURL kUrl("https://example.test:8080/");
+
+// This limit is arbitrary and exists only to make memory management in this
+// test easier.
+constexpr uint32_t kMaxProxyEntryLimit = 10u;
+
+void CopySettingToIEProxyConfigString(const std::wstring& setting,
+ LPWSTR* ie_proxy_config_string) {
+ // The trailing null for the string is provided by GlobalAlloc, which
+ // zero-initializes the memory when using the GPTR flag.
+ *ie_proxy_config_string = static_cast<LPWSTR>(
+ GlobalAlloc(GPTR, sizeof(wchar_t) * (setting.length() + 1)));
+ memcpy(*ie_proxy_config_string, setting.data(),
+ sizeof(wchar_t) * setting.length());
+}
+
+// This class will internally validate behavior that MUST be present in the code
+// in order to successfully use WinHttp APIs.
+class MockWinHttpAPIWrapper final : public WinHttpAPIWrapper {
+ public:
+ MockWinHttpAPIWrapper() {}
+ ~MockWinHttpAPIWrapper() override {
+ if (did_call_get_proxy_result_) {
+ EXPECT_TRUE(did_call_free_proxy_result_);
+ }
+ EXPECT_TRUE(opened_proxy_resolvers_.empty());
+ ResetWinHttpResults();
+ }
+
+ void set_call_winhttp_open_success(bool open_success) {
+ open_success_ = open_success;
+ }
+ bool CallWinHttpOpen() override {
+ did_call_open_ = true;
+ return open_success_;
+ }
+
+ void set_call_winhttp_set_timeouts_success(bool set_timeouts_success) {
+ set_timeouts_success_ = set_timeouts_success;
+ }
+ bool CallWinHttpSetTimeouts(int resolve_timeout,
+ int connect_timeout,
+ int send_timeout,
+ int receive_timeout) override {
+ EXPECT_TRUE(did_call_open_);
+ did_call_set_timeouts_ = true;
+ return set_timeouts_success_;
+ }
+
+ void set_call_winhttp_set_status_callback_success(
+ bool set_status_callback_success) {
+ set_status_callback_success_ = set_status_callback_success;
+ }
+ bool CallWinHttpSetStatusCallback(
+ WINHTTP_STATUS_CALLBACK internet_callback) override {
+ EXPECT_TRUE(did_call_open_);
+ EXPECT_NE(internet_callback, nullptr);
+ EXPECT_EQ(callback_, nullptr);
+ callback_ = internet_callback;
+ did_call_set_status_callback_ = true;
+ return set_status_callback_success_;
+ }
+
+ void set_call_winhttp_get_ie_proxy_config_success(
+ bool get_ie_proxy_config_success) {
+ get_ie_proxy_config_success_ = get_ie_proxy_config_success;
+ }
+ void set_ie_proxy_config(bool is_autoproxy_enabled,
+ const std::wstring& pac_url,
+ const std::wstring& proxy,
+ const std::wstring& proxy_bypass) {
+ is_autoproxy_enabled_ = is_autoproxy_enabled;
+ pac_url_ = pac_url;
+ proxy_ = proxy;
+ proxy_bypass_ = proxy_bypass;
+ }
+ bool CallWinHttpGetIEProxyConfigForCurrentUser(
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_proxy_config) override {
+ did_call_get_ie_proxy_config_ = true;
+ ie_proxy_config->fAutoDetect = is_autoproxy_enabled_ ? TRUE : FALSE;
+ if (!pac_url_.empty()) {
+ CopySettingToIEProxyConfigString(pac_url_,
+ &ie_proxy_config->lpszAutoConfigUrl);
+ }
+ if (!proxy_.empty()) {
+ CopySettingToIEProxyConfigString(proxy_, &ie_proxy_config->lpszProxy);
+ }
+ if (!proxy_bypass_.empty()) {
+ CopySettingToIEProxyConfigString(proxy_bypass_,
+ &ie_proxy_config->lpszProxyBypass);
+ }
+ return get_ie_proxy_config_success_;
+ }
+
+ void set_call_winhttp_create_proxy_resolver_success(
+ bool create_proxy_resolver_success) {
+ create_proxy_resolver_success_ = create_proxy_resolver_success;
+ }
+ bool CallWinHttpCreateProxyResolver(HINTERNET* out_resolver_handle) override {
+ EXPECT_TRUE(did_call_set_status_callback_);
+ EXPECT_NE(out_resolver_handle, nullptr);
+ if (!out_resolver_handle)
+ return false;
+
+ did_call_create_proxy_resolver_ = true;
+ if (!create_proxy_resolver_success_)
+ return false;
+
+ // The caller will be using this handle as an identifier later, so make this
+ // unique.
+ *out_resolver_handle =
+ reinterpret_cast<HINTERNET>(proxy_resolver_identifier_++);
+ EXPECT_EQ(opened_proxy_resolvers_.count(*out_resolver_handle), 0u);
+ opened_proxy_resolvers_.emplace(*out_resolver_handle);
+
+ return true;
+ }
+
+ void set_call_winhttp_get_proxy_for_url_success(
+ bool get_proxy_for_url_success) {
+ get_proxy_for_url_success_ = get_proxy_for_url_success;
+ }
+ bool CallWinHttpGetProxyForUrlEx(HINTERNET resolver_handle,
+ const std::string& url,
+ WINHTTP_AUTOPROXY_OPTIONS* autoproxy_options,
+ DWORD_PTR context) override {
+ // This API must be called only after the session has been correctly set up.
+ EXPECT_TRUE(did_call_open_);
+ EXPECT_TRUE(did_call_set_timeouts_);
+ EXPECT_TRUE(did_call_set_status_callback_);
+ EXPECT_NE(callback_, nullptr);
+ EXPECT_TRUE(did_call_get_ie_proxy_config_);
+ EXPECT_TRUE(did_call_create_proxy_resolver_);
+ EXPECT_TRUE(!did_call_get_proxy_result_);
+ EXPECT_TRUE(!did_call_free_proxy_result_);
+
+ // This API must always receive valid inputs.
+ EXPECT_TRUE(!url.empty());
+ EXPECT_TRUE(autoproxy_options);
+ EXPECT_FALSE(autoproxy_options->fAutoLogonIfChallenged);
+ EXPECT_TRUE(autoproxy_options->dwFlags & WINHTTP_AUTOPROXY_ALLOW_STATIC);
+ EXPECT_TRUE(autoproxy_options->dwFlags & WINHTTP_AUTOPROXY_ALLOW_CM);
+ if (autoproxy_options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL) {
+ EXPECT_TRUE(autoproxy_options->lpszAutoConfigUrl);
+ } else {
+ EXPECT_TRUE(!autoproxy_options->lpszAutoConfigUrl);
+ }
+ if (autoproxy_options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) {
+ EXPECT_TRUE(autoproxy_options->dwAutoDetectFlags &
+ WINHTTP_AUTO_DETECT_TYPE_DNS_A);
+ EXPECT_TRUE(autoproxy_options->dwAutoDetectFlags &
+ WINHTTP_AUTO_DETECT_TYPE_DHCP);
+ } else {
+ EXPECT_TRUE(!autoproxy_options->dwAutoDetectFlags);
+ }
+
+ EXPECT_NE(resolver_handle, nullptr);
+ EXPECT_EQ(opened_proxy_resolvers_.count(resolver_handle), 1u);
+ EXPECT_NE(context, 0u);
+ if (!resolver_handle || !context || !callback_)
+ return false;
+
+ did_call_get_proxy_for_url_ = true;
+ if (!get_proxy_for_url_success_)
+ return false;
+
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MockWinHttpAPIWrapper::RunCallback,
+ base::Unretained(this), resolver_handle, context));
+ return true;
+ }
+
+ void set_call_winhttp_get_proxy_result_success(
+ bool get_proxy_result_success) {
+ get_proxy_result_success_ = get_proxy_result_success;
+ }
+ void SetCallbackStatusAndInfo(DWORD callback_status, DWORD info_error) {
+ callback_status_ = callback_status;
+ callback_info_ = std::make_unique<WINHTTP_ASYNC_RESULT>();
+ callback_info_->dwError = info_error;
+ }
+ void AddBypassToProxyResults() {
+ ASSERT_LT(proxy_result_.cEntries, kMaxProxyEntryLimit - 1);
+ AllocateProxyResultEntriesIfNeeded();
+ proxy_result_.pEntries[proxy_result_.cEntries].fBypass = TRUE;
+ proxy_result_.cEntries++;
+ }
+ void AddDirectToProxyResults() {
+ ASSERT_LT(proxy_result_.cEntries, kMaxProxyEntryLimit - 1);
+ AllocateProxyResultEntriesIfNeeded();
+ proxy_result_.cEntries++;
+ }
+ void AddToProxyResults(INTERNET_SCHEME scheme,
+ std::wstring proxy_host,
+ INTERNET_PORT port) {
+ ASSERT_LT(proxy_result_.cEntries, kMaxProxyEntryLimit - 1);
+ AllocateProxyResultEntriesIfNeeded();
+
+ proxy_list_.push_back(std::move(proxy_host));
+ wchar_t* proxy_host_raw = const_cast<wchar_t*>(proxy_list_.back().data());
+
+ proxy_result_.pEntries[proxy_result_.cEntries].fProxy = TRUE;
+ proxy_result_.pEntries[proxy_result_.cEntries].ProxyScheme = scheme;
+ proxy_result_.pEntries[proxy_result_.cEntries].pwszProxy = proxy_host_raw;
+ proxy_result_.pEntries[proxy_result_.cEntries].ProxyPort = port;
+
+ proxy_result_.cEntries++;
+ }
+ bool CallWinHttpGetProxyResult(HINTERNET resolver_handle,
+ WINHTTP_PROXY_RESULT* proxy_result) override {
+ EXPECT_TRUE(did_call_get_proxy_for_url_);
+ EXPECT_NE(resolver_handle, nullptr);
+ EXPECT_EQ(opened_proxy_resolvers_.count(resolver_handle), 1u);
+ if (!get_proxy_result_success_)
+ return false;
+
+ EXPECT_NE(proxy_result, nullptr);
+ proxy_result->cEntries = proxy_result_.cEntries;
+ proxy_result->pEntries = proxy_result_.pEntries;
+
+ did_call_get_proxy_result_ = true;
+ return get_proxy_result_success_;
+ }
+
+ void CallWinHttpFreeProxyResult(WINHTTP_PROXY_RESULT* proxy_result) override {
+ EXPECT_TRUE(did_call_get_proxy_result_);
+ EXPECT_NE(proxy_result, nullptr);
+ did_call_free_proxy_result_ = true;
+ }
+
+ void CallWinHttpCloseHandle(HINTERNET internet_handle) override {
+ EXPECT_EQ(opened_proxy_resolvers_.count(internet_handle), 1u);
+ opened_proxy_resolvers_.erase(internet_handle);
+ }
+
+ void ResetWinHttpResults() {
+ if (proxy_result_.pEntries) {
+ delete[] proxy_result_.pEntries;
+ proxy_result_.pEntries = nullptr;
+ proxy_result_ = {0};
+ }
+ proxy_list_.clear();
+ }
+
+ base::WeakPtr<MockWinHttpAPIWrapper> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ private:
+ void RunCallback(HINTERNET resolver_handle, DWORD_PTR context) {
+ EXPECT_NE(callback_, nullptr);
+ EXPECT_NE(resolver_handle, nullptr);
+ EXPECT_EQ(opened_proxy_resolvers_.count(resolver_handle), 1u);
+ EXPECT_NE(context, 0u);
+ callback_(resolver_handle, context, callback_status_, callback_info_.get(),
+ sizeof(callback_info_.get()));
+
+ // As soon as the callback resolves, WinHttp may choose to delete the memory
+ // contained by `callback_info_`. This is simulated here.
+ callback_info_.reset();
+ }
+
+ void AllocateProxyResultEntriesIfNeeded() {
+ if (proxy_result_.cEntries != 0)
+ return;
+
+ proxy_result_.pEntries =
+ new WINHTTP_PROXY_RESULT_ENTRY[kMaxProxyEntryLimit];
+ std::memset(proxy_result_.pEntries, 0,
+ kMaxProxyEntryLimit * sizeof(WINHTTP_PROXY_RESULT_ENTRY));
+
+ // The memory of the strings above will be backed by a vector of strings.
+ proxy_list_.reserve(kMaxProxyEntryLimit);
+ }
+
+ // Data configurable by tests to simulate errors and results from WinHttp.
+ bool open_success_ = true;
+ bool set_timeouts_success_ = true;
+ bool set_status_callback_success_ = true;
+ bool get_ie_proxy_config_success_ = true;
+ bool create_proxy_resolver_success_ = true;
+ bool get_proxy_for_url_success_ = true;
+ bool get_proxy_result_success_ = true;
+ DWORD callback_status_ = WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE;
+ std::unique_ptr<WINHTTP_ASYNC_RESULT> callback_info_;
+ bool is_autoproxy_enabled_ = false;
+ std::wstring pac_url_;
+ std::wstring proxy_;
+ std::wstring proxy_bypass_;
+ WINHTTP_PROXY_RESULT proxy_result_ = {0};
+ std::vector<std::wstring> proxy_list_;
+
+ // Data used internally in the mock to function and validate its own behavior.
+ bool did_call_open_ = false;
+ bool did_call_set_timeouts_ = false;
+ bool did_call_set_status_callback_ = false;
+ bool did_call_get_ie_proxy_config_ = false;
+ int proxy_resolver_identifier_ = 1;
+ std::set<HINTERNET> opened_proxy_resolvers_;
+ bool did_call_create_proxy_resolver_ = false;
+ bool did_call_get_proxy_for_url_ = false;
+ bool did_call_get_proxy_result_ = false;
+ bool did_call_free_proxy_result_ = false;
+ WINHTTP_STATUS_CALLBACK callback_ = nullptr;
+
+ base::WeakPtrFactory<MockWinHttpAPIWrapper> weak_factory_{this};
+};
+
+} // namespace
+
+// These tests verify the behavior of the WindowsSystemProxyResolverImpl in
+// isolation by mocking out the WinHttpAPIWrapper it uses.
+class WindowsSystemProxyResolverImplTest : public testing::Test {
+ public:
+ void SetUp() override {
+ testing::Test::SetUp();
+
+ if (!net::WindowsSystemProxyResolutionService::IsSupported()) {
+ GTEST_SKIP()
+ << "Windows System Proxy Resolution is only supported on Windows 8+.";
+ }
+
+ proxy_resolver_ = std::make_unique<WindowsSystemProxyResolverImpl>(
+ proxy_resolver_remote_.BindNewPipeAndPassReceiver());
+ auto winhttp_api_wrapper = std::make_unique<MockWinHttpAPIWrapper>();
+ winhttp_api_wrapper_ = winhttp_api_wrapper->GetWeakPtr();
+ proxy_resolver_->SetCreateWinHttpAPIWrapperForTesting(
+ std::move(winhttp_api_wrapper));
+ }
+
+ void TearDown() override {
+ ResetProxyResolutionService();
+
+ testing::Test::TearDown();
+ }
+
+ MockWinHttpAPIWrapper* winhttp_api_wrapper() {
+ return winhttp_api_wrapper_.get();
+ }
+
+ void ValidateProxyResult(base::OnceClosure closure,
+ const net::ProxyList& expected_proxy_list,
+ net::WinHttpStatus expected_winhttp_status,
+ int expected_windows_error,
+ const net::ProxyList& actual_proxy_list,
+ net::WinHttpStatus actual_winhttp_status,
+ int actual_windows_error) {
+ EXPECT_TRUE(expected_proxy_list.Equals(actual_proxy_list));
+ EXPECT_EQ(expected_winhttp_status, actual_winhttp_status);
+ EXPECT_EQ(expected_windows_error, actual_windows_error);
+ std::move(closure).Run();
+ }
+
+ void PerformGetProxyForUrlAndValidateResult(const net::ProxyList& proxy_list,
+ net::WinHttpStatus winhttp_status,
+ int windows_error) {
+ base::RunLoop run_loop;
+ proxy_resolver_remote_->GetProxyForUrl(
+ kUrl,
+ base::BindOnce(&WindowsSystemProxyResolverImplTest::ValidateProxyResult,
+ base::Unretained(this), run_loop.QuitClosure(),
+ proxy_list, winhttp_status, windows_error));
+ run_loop.Run();
+ }
+
+ // Tests that use DoFailedGetProxyForUrlTest validate failure conditions in
+ // WindowsSystemProxyResolverImpl.
+ void DoFailedGetProxyForUrlTest(net::WinHttpStatus winhttp_status,
+ int windows_error) {
+ PerformGetProxyForUrlAndValidateResult(net::ProxyList(), winhttp_status,
+ windows_error);
+ }
+
+ // Tests that use DoProxyConfigTest validate that the proxy configs retrieved
+ // from Windows can be read by WindowsSystemProxyResolverImpl.
+ void DoProxyConfigTest(const net::ProxyConfig& proxy_config) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
+ net::ProxyList proxy_list;
+ proxy_list.AddProxyServer(
+ net::PacResultElementToProxyServer("HTTPS foopy:8443"));
+
+ std::wstring pac_url;
+ if (proxy_config.has_pac_url())
+ pac_url = base::UTF8ToWide(proxy_config.pac_url().spec());
+
+ std::wstring proxy;
+ if (!proxy_config.proxy_rules().single_proxies.IsEmpty()) {
+ proxy = base::UTF8ToWide(
+ proxy_config.proxy_rules().single_proxies.ToPacString());
+ }
+
+ std::wstring proxy_bypass;
+ if (!proxy_config.proxy_rules().bypass_rules.ToString().empty()) {
+ proxy_bypass =
+ base::UTF8ToWide(proxy_config.proxy_rules().bypass_rules.ToString());
+ }
+
+ winhttp_api_wrapper_->set_ie_proxy_config(proxy_config.auto_detect(),
+ pac_url, proxy, proxy_bypass);
+
+ PerformGetProxyForUrlAndValidateResult(proxy_list, net::WinHttpStatus::kOk,
+ 0);
+ }
+
+ // Tests that use DoGetProxyForUrlTest validate successful proxy retrievals.
+ void DoGetProxyForUrlTest(const net::ProxyList& proxy_list) {
+ PerformGetProxyForUrlAndValidateResult(proxy_list, net::WinHttpStatus::kOk,
+ 0);
+ }
+
+ void ResetProxyResolutionService() {
+ proxy_resolver_remote_.reset();
+ winhttp_api_wrapper_.reset();
+ proxy_resolver_.reset();
+ }
+
+ protected:
+ mojo::Remote<mojom::WindowsSystemProxyResolver> proxy_resolver_remote_;
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<WindowsSystemProxyResolverImpl> proxy_resolver_;
+ base::WeakPtr<MockWinHttpAPIWrapper> winhttp_api_wrapper_;
+};
+
+TEST_F(WindowsSystemProxyResolverImplTest, InitializeFailOnOpen) {
+ winhttp_api_wrapper()->set_call_winhttp_open_success(false);
+ DoFailedGetProxyForUrlTest(net::WinHttpStatus::kWinHttpOpenFailed, 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, InitializeFailOnSetTimeouts) {
+ winhttp_api_wrapper()->set_call_winhttp_set_timeouts_success(false);
+ DoFailedGetProxyForUrlTest(net::WinHttpStatus::kWinHttpSetTimeoutsFailed, 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, InitializeFailOnSetStatusCallback) {
+ winhttp_api_wrapper()->set_call_winhttp_set_status_callback_success(false);
+ DoFailedGetProxyForUrlTest(
+ net::WinHttpStatus::kWinHttpSetStatusCallbackFailed, 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest,
+ GetProxyForUrlFailOnGetIEProxySettings) {
+ winhttp_api_wrapper()->set_call_winhttp_get_ie_proxy_config_success(false);
+ DoFailedGetProxyForUrlTest(
+ net::WinHttpStatus::kWinHttpGetIEProxyConfigForCurrentUserFailed, 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest,
+ GetProxyForUrlFailOnCreateProxyResolver) {
+ winhttp_api_wrapper()->set_call_winhttp_create_proxy_resolver_success(false);
+ DoFailedGetProxyForUrlTest(
+ net::WinHttpStatus::kWinHttpCreateProxyResolverFailed, 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest,
+ GetProxyForUrlFailOnWinHttpGetProxyForUrlEx) {
+ winhttp_api_wrapper()->set_call_winhttp_get_proxy_for_url_success(false);
+ DoFailedGetProxyForUrlTest(net::WinHttpStatus::kWinHttpGetProxyForURLExFailed,
+ 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlFailOnFailedCallback) {
+ winhttp_api_wrapper()->SetCallbackStatusAndInfo(
+ WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, API_RECEIVE_RESPONSE);
+ DoFailedGetProxyForUrlTest(net::WinHttpStatus::kStatusCallbackFailed,
+ API_RECEIVE_RESPONSE);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlFailOnGetProxyResult) {
+ winhttp_api_wrapper()->set_call_winhttp_get_proxy_result_success(false);
+ DoFailedGetProxyForUrlTest(net::WinHttpStatus::kWinHttpGetProxyResultFailed,
+ 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlFailOnNoResults) {
+ DoFailedGetProxyForUrlTest(net::WinHttpStatus::kEmptyProxyList, 0);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlConfigDirect) {
+ DoProxyConfigTest(net::ProxyConfig::CreateDirect());
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlConfigAutoDetect) {
+ DoProxyConfigTest(net::ProxyConfig::CreateAutoDetect());
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlConfigPacUrl) {
+ const GURL pac_url("http://pac-site.test/path/to/pac-url.pac");
+ DoProxyConfigTest(net::ProxyConfig::CreateFromCustomPacURL(pac_url));
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlConfigSingleProxy) {
+ net::ProxyConfig config;
+ const net::ProxyServer proxy_server =
+ net::PacResultElementToProxyServer("HTTPS ignored:33");
+ config.proxy_rules().single_proxies.AddProxyServer(proxy_server);
+ DoProxyConfigTest(config);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlConfigBypass) {
+ net::ProxyConfig config;
+ config.proxy_rules().bypass_rules.AddRuleFromString("example.test");
+ DoProxyConfigTest(config);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest,
+ GetProxyForUrlConfigMultipleSettings) {
+ net::ProxyConfig config;
+ config.set_auto_detect(true);
+
+ const GURL pac_url("http://pac-site.test/path/to/pac-url.pac");
+ config.set_pac_url(pac_url);
+
+ const net::ProxyServer proxy_server =
+ net::PacResultElementToProxyServer("HTTPS ignored:33");
+ config.proxy_rules().single_proxies.AddProxyServer(proxy_server);
+
+ DoProxyConfigTest(config);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlDirect) {
+ winhttp_api_wrapper()->AddDirectToProxyResults();
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(net::ProxyServer::Direct());
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlBypass) {
+ winhttp_api_wrapper()->AddBypassToProxyResults();
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(net::ProxyServer::Direct());
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlHTTP) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTP, L"foopy",
+ 8080);
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(
+ net::PacResultElementToProxyServer("PROXY foopy:8080"));
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlHTTPS) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(
+ net::PacResultElementToProxyServer("HTTPS foopy:8443"));
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlSOCKS) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_SOCKS, L"foopy",
+ 8080);
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(
+ net::PacResultElementToProxyServer("SOCKS4 foopy:8080"));
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlIDNProxy) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"föopy",
+ 8080);
+
+ // Expect L"föopy" to be ascii-encoded as "xn--fopy-5qa".
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(
+ net::PacResultElementToProxyServer("HTTPS xn--fopy-5qa:8080"));
+
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest,
+ GetProxyForUrlIgnoreInvalidProxyResults) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTP, L"foopy",
+ INTERNET_DEFAULT_PORT);
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_FTP, L"foopy", 80);
+
+ winhttp_api_wrapper()->AddDirectToProxyResults();
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(net::ProxyServer::Direct());
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+TEST_F(WindowsSystemProxyResolverImplTest, GetProxyForUrlMultipleResults) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
+ winhttp_api_wrapper()->AddDirectToProxyResults();
+
+ net::ProxyList expected_proxy_list;
+ expected_proxy_list.AddProxyServer(
+ net::PacResultElementToProxyServer("HTTPS foopy:8443"));
+ expected_proxy_list.AddProxyServer(net::ProxyServer::Direct());
+
+ DoGetProxyForUrlTest(expected_proxy_list);
+}
+
+} // namespace proxy_resolver_win
diff --git a/chromium/services/proxy_resolver_win/winhttp_api_wrapper.h b/chromium/services/proxy_resolver_win/winhttp_api_wrapper.h
index c39c7e7ddb5..64943458c33 100644
--- a/chromium/services/proxy_resolver_win/winhttp_api_wrapper.h
+++ b/chromium/services/proxy_resolver_win/winhttp_api_wrapper.h
@@ -8,71 +8,51 @@
#include <windows.h>
#include <winhttp.h>
-#include <memory>
#include <string>
#include "base/compiler_specific.h"
+#include "base/component_export.h"
namespace proxy_resolver_win {
-// This is a utility class that encapsulates the memory management necessary for
-// WINHTTP_CURRENT_USER_IE_PROXY_CONFIG in RAII style.
-class ScopedIEConfig final {
- public:
- ScopedIEConfig();
-
- ScopedIEConfig(const ScopedIEConfig&) = delete;
- ScopedIEConfig& operator=(const ScopedIEConfig&) = delete;
-
- ~ScopedIEConfig();
-
- WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* config() { return &ie_config; }
-
- private:
- WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_config = {0};
-};
-
// This provides a layer of abstraction between calling code and WinHTTP APIs,
// allowing them to be mocked out for testing. This object is not thread safe
// and it's expected that the caller will handle using it on the same thread or
// sequence. In general, documentation for these APIs can be found here:
// https://docs.microsoft.com/en-us/windows/win32/api/winhttp/
-class WinHttpAPIWrapper {
+class COMPONENT_EXPORT(PROXY_RESOLVER_WIN) WinHttpAPIWrapper {
public:
- WinHttpAPIWrapper();
-
- WinHttpAPIWrapper(const WinHttpAPIWrapper&) = delete;
- WinHttpAPIWrapper& operator=(const WinHttpAPIWrapper&) = delete;
-
- virtual ~WinHttpAPIWrapper();
+ virtual ~WinHttpAPIWrapper() = default;
// Creates our WinHttp session handle |session_handle_|. The lifetime of that
// session handle is determined by the lifetime of this object. It'll get
// closed when this object destructs.
- virtual bool CallWinHttpOpen() WARN_UNUSED_RESULT;
+ virtual bool CallWinHttpOpen() WARN_UNUSED_RESULT = 0;
// Controls the timeout for WinHttpGetProxyForUrlEx().
virtual bool CallWinHttpSetTimeouts(int resolve_timeout,
int connect_timeout,
int send_timeout,
- int receive_timeout) WARN_UNUSED_RESULT;
+ int receive_timeout)
+ WARN_UNUSED_RESULT = 0;
// Sets the callback WinHttp will call into with the result of any
// asynchronous call.
virtual bool CallWinHttpSetStatusCallback(
- WINHTTP_STATUS_CALLBACK internet_callback) WARN_UNUSED_RESULT;
+ WINHTTP_STATUS_CALLBACK internet_callback) WARN_UNUSED_RESULT = 0;
// Fetches the proxy configs for the current active network connection and
// current Windows user. The |ie_proxy_config| says whether or not
// AutoProxy (WPAD) is enabled and if there's a PAC URL configured for this
// connection/user.
virtual bool CallWinHttpGetIEProxyConfigForCurrentUser(
- WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_proxy_config) WARN_UNUSED_RESULT;
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_proxy_config)
+ WARN_UNUSED_RESULT = 0;
// Creates a handle |resolver_handle| that should be used for the call to
// WinHttpGetProxyForUrlEx().
virtual bool CallWinHttpCreateProxyResolver(HINTERNET* out_resolver_handle)
- WARN_UNUSED_RESULT;
+ WARN_UNUSED_RESULT = 0;
// Using the specific |resolver_handle| handle from
// CallWinHttpCreateProxyResolver(), resolve a proxy for a specific |url| with
@@ -99,7 +79,7 @@ class WinHttpAPIWrapper {
HINTERNET resolver_handle,
const std::string& url,
WINHTTP_AUTOPROXY_OPTIONS* autoproxy_options,
- DWORD_PTR context) WARN_UNUSED_RESULT;
+ DWORD_PTR context) WARN_UNUSED_RESULT = 0;
// As long as CallWinHttpGetProxyForUrlEx() doesn't hit any errors, there will
// be a proxy result to examine. This function retrieves that proxy resolution
@@ -107,21 +87,16 @@ class WinHttpAPIWrapper {
// result must be freed with CallWinHttpFreeProxyResult().
virtual bool CallWinHttpGetProxyResult(HINTERNET resolver_handle,
WINHTTP_PROXY_RESULT* proxy_result)
- WARN_UNUSED_RESULT;
+ WARN_UNUSED_RESULT = 0;
// Frees the |proxy_result| retrieved by CallWinHttpGetProxyResult().
- virtual void CallWinHttpFreeProxyResult(WINHTTP_PROXY_RESULT* proxy_result);
+ virtual void CallWinHttpFreeProxyResult(
+ WINHTTP_PROXY_RESULT* proxy_result) = 0;
// Every opened HINTERNET handle must be closed. This closes handle
// |internet_handle|. After being closed, WinHttp calls cannot be made using
// that handle.
- virtual void CallWinHttpCloseHandle(HINTERNET internet_handle);
-
- private:
- // Closes |session_handle_|.
- void CloseSessionHandle();
-
- HINTERNET session_handle_ = nullptr;
+ virtual void CallWinHttpCloseHandle(HINTERNET internet_handle) = 0;
};
} // namespace proxy_resolver_win
diff --git a/chromium/services/proxy_resolver_win/winhttp_api_wrapper.cc b/chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.cc
index dd085008a11..bbc7e0c4b48 100644
--- a/chromium/services/proxy_resolver_win/winhttp_api_wrapper.cc
+++ b/chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/proxy_resolver_win/winhttp_api_wrapper.h"
+#include "services/proxy_resolver_win/winhttp_api_wrapper_impl.h"
#include <string>
#include <utility>
#include "base/check_op.h"
-#include "base/macros.h"
+#include "base/ignore_result.h"
#include "services/proxy_resolver_win/winhttp_proxy_resolver_functions.h"
namespace proxy_resolver_win {
@@ -26,14 +26,14 @@ ScopedIEConfig::~ScopedIEConfig() {
GlobalFree(ie_config.lpszProxyBypass);
}
-WinHttpAPIWrapper::WinHttpAPIWrapper() = default;
-WinHttpAPIWrapper::~WinHttpAPIWrapper() {
+WinHttpAPIWrapperImpl::WinHttpAPIWrapperImpl() = default;
+WinHttpAPIWrapperImpl::~WinHttpAPIWrapperImpl() {
if (session_handle_)
ignore_result(CallWinHttpSetStatusCallback(nullptr));
CloseSessionHandle();
}
-bool WinHttpAPIWrapper::CallWinHttpOpen() {
+bool WinHttpAPIWrapperImpl::CallWinHttpOpen() {
DCHECK_EQ(nullptr, session_handle_);
session_handle_ =
WinHttpOpen(nullptr, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME,
@@ -41,16 +41,16 @@ bool WinHttpAPIWrapper::CallWinHttpOpen() {
return (session_handle_ != nullptr);
}
-bool WinHttpAPIWrapper::CallWinHttpSetTimeouts(int resolve_timeout,
- int connect_timeout,
- int send_timeout,
- int receive_timeout) {
+bool WinHttpAPIWrapperImpl::CallWinHttpSetTimeouts(int resolve_timeout,
+ int connect_timeout,
+ int send_timeout,
+ int receive_timeout) {
DCHECK_NE(nullptr, session_handle_);
return (!!WinHttpSetTimeouts(session_handle_, resolve_timeout,
connect_timeout, send_timeout, receive_timeout));
}
-bool WinHttpAPIWrapper::CallWinHttpSetStatusCallback(
+bool WinHttpAPIWrapperImpl::CallWinHttpSetStatusCallback(
WINHTTP_STATUS_CALLBACK internet_callback) {
DCHECK_NE(nullptr, session_handle_);
const WINHTTP_STATUS_CALLBACK winhttp_status_callback =
@@ -62,12 +62,12 @@ bool WinHttpAPIWrapper::CallWinHttpSetStatusCallback(
return (winhttp_status_callback != WINHTTP_INVALID_STATUS_CALLBACK);
}
-bool WinHttpAPIWrapper::CallWinHttpGetIEProxyConfigForCurrentUser(
+bool WinHttpAPIWrapperImpl::CallWinHttpGetIEProxyConfigForCurrentUser(
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_proxy_config) {
return !!WinHttpGetIEProxyConfigForCurrentUser(ie_proxy_config);
}
-bool WinHttpAPIWrapper::CallWinHttpCreateProxyResolver(
+bool WinHttpAPIWrapperImpl::CallWinHttpCreateProxyResolver(
HINTERNET* out_resolver_handle) {
DCHECK_NE(nullptr, session_handle_);
const DWORD result =
@@ -76,7 +76,7 @@ bool WinHttpAPIWrapper::CallWinHttpCreateProxyResolver(
return (result == ERROR_SUCCESS);
}
-bool WinHttpAPIWrapper::CallWinHttpGetProxyForUrlEx(
+bool WinHttpAPIWrapperImpl::CallWinHttpGetProxyForUrlEx(
HINTERNET resolver_handle,
const std::string& url,
WINHTTP_AUTOPROXY_OPTIONS* autoproxy_options,
@@ -90,7 +90,7 @@ bool WinHttpAPIWrapper::CallWinHttpGetProxyForUrlEx(
return (result == ERROR_IO_PENDING);
}
-bool WinHttpAPIWrapper::CallWinHttpGetProxyResult(
+bool WinHttpAPIWrapperImpl::CallWinHttpGetProxyResult(
HINTERNET resolver_handle,
WINHTTP_PROXY_RESULT* proxy_result) {
const DWORD result =
@@ -99,16 +99,16 @@ bool WinHttpAPIWrapper::CallWinHttpGetProxyResult(
return (result == ERROR_SUCCESS);
}
-VOID WinHttpAPIWrapper::CallWinHttpFreeProxyResult(
+VOID WinHttpAPIWrapperImpl::CallWinHttpFreeProxyResult(
WINHTTP_PROXY_RESULT* proxy_result) {
WinHttpProxyResolverFunctions::GetInstance().free_proxy_result(proxy_result);
}
-void WinHttpAPIWrapper::CallWinHttpCloseHandle(HINTERNET internet_handle) {
+void WinHttpAPIWrapperImpl::CallWinHttpCloseHandle(HINTERNET internet_handle) {
WinHttpCloseHandle(internet_handle);
}
-void WinHttpAPIWrapper::CloseSessionHandle() {
+void WinHttpAPIWrapperImpl::CloseSessionHandle() {
if (session_handle_) {
CallWinHttpCloseHandle(session_handle_);
session_handle_ = nullptr;
diff --git a/chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.h b/chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.h
new file mode 100644
index 00000000000..264872ac640
--- /dev/null
+++ b/chromium/services/proxy_resolver_win/winhttp_api_wrapper_impl.h
@@ -0,0 +1,74 @@
+// 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_PROXY_RESOLVER_WIN_WINHTTP_API_WRAPPER_IMPL_H_
+#define SERVICES_PROXY_RESOLVER_WIN_WINHTTP_API_WRAPPER_IMPL_H_
+
+#include <windows.h>
+#include <winhttp.h>
+
+#include <string>
+
+#include "services/proxy_resolver_win/winhttp_api_wrapper.h"
+
+namespace proxy_resolver_win {
+
+// This is a utility class that encapsulates the memory management necessary for
+// WINHTTP_CURRENT_USER_IE_PROXY_CONFIG in RAII style.
+class ScopedIEConfig final {
+ public:
+ ScopedIEConfig();
+
+ ScopedIEConfig(const ScopedIEConfig&) = delete;
+ ScopedIEConfig& operator=(const ScopedIEConfig&) = delete;
+
+ ~ScopedIEConfig();
+
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* config() { return &ie_config; }
+
+ private:
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_config = {0};
+};
+
+// This is the implementation of WinHttpAPIWrapper that gets used in the
+// product.
+class WinHttpAPIWrapperImpl final : public WinHttpAPIWrapper {
+ public:
+ WinHttpAPIWrapperImpl();
+
+ WinHttpAPIWrapperImpl(const WinHttpAPIWrapperImpl&) = delete;
+ WinHttpAPIWrapperImpl& operator=(const WinHttpAPIWrapperImpl&) = delete;
+
+ ~WinHttpAPIWrapperImpl() override;
+
+ // WinHttpAPIWrapper Implementation
+ bool CallWinHttpOpen() override;
+ bool CallWinHttpSetTimeouts(int resolve_timeout,
+ int connect_timeout,
+ int send_timeout,
+ int receive_timeout) override;
+ bool CallWinHttpSetStatusCallback(
+ WINHTTP_STATUS_CALLBACK internet_callback) override;
+ bool CallWinHttpGetIEProxyConfigForCurrentUser(
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_proxy_config) override;
+ bool CallWinHttpCreateProxyResolver(HINTERNET* out_resolver_handle) override;
+ bool CallWinHttpGetProxyForUrlEx(HINTERNET resolver_handle,
+ const std::string& url,
+ WINHTTP_AUTOPROXY_OPTIONS* autoproxy_options,
+ DWORD_PTR context) override;
+ bool CallWinHttpGetProxyResult(HINTERNET resolver_handle,
+ WINHTTP_PROXY_RESULT* proxy_result) override;
+ void CallWinHttpFreeProxyResult(WINHTTP_PROXY_RESULT* proxy_result) override;
+ void CallWinHttpCloseHandle(HINTERNET internet_handle) override;
+
+ private:
+ // Closes |session_handle_|.
+ void CloseSessionHandle();
+
+ HINTERNET session_handle_ = nullptr;
+};
+
+} // namespace proxy_resolver_win
+
+#endif // SERVICES_PROXY_RESOLVER_WIN_WINHTTP_API_WRAPPER_IMPL_H_
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/graph.h b/chromium/services/resource_coordinator/memory_instrumentation/graph.h
index 24575e61b71..f92bcf2e767 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/graph.h
+++ b/chromium/services/resource_coordinator/memory_instrumentation/graph.h
@@ -13,7 +13,7 @@
#include <vector>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/process/process_handle.h"
#include "base/strings/string_piece.h"
#include "base/trace_event/memory_allocator_dump_guid.h"
@@ -57,8 +57,8 @@ class GlobalDumpGraph {
private:
base::ProcessId pid_;
- GlobalDumpGraph* global_graph_;
- GlobalDumpGraph::Node* root_;
+ raw_ptr<GlobalDumpGraph> global_graph_;
+ raw_ptr<GlobalDumpGraph::Node> root_;
};
// A single node in the graph of allocator dumps associated with a
@@ -180,8 +180,8 @@ class GlobalDumpGraph {
}
private:
- GlobalDumpGraph::Process* dump_graph_;
- Node* const parent_;
+ raw_ptr<GlobalDumpGraph::Process> dump_graph_;
+ const raw_ptr<Node> parent_;
base::trace_event::MemoryAllocatorDumpGuid guid_;
std::map<std::string, Entry> entries_;
std::map<std::string, Node*> children_;
@@ -194,7 +194,7 @@ class GlobalDumpGraph {
double cumulative_owned_coefficient_ = 1;
double cumulative_owning_coefficient_ = 1;
- GlobalDumpGraph::Edge* owns_edge_;
+ raw_ptr<GlobalDumpGraph::Edge> owns_edge_;
std::vector<GlobalDumpGraph::Edge*> owned_by_edges_;
};
@@ -253,6 +253,10 @@ class GlobalDumpGraph {
std::map<base::trace_event::MemoryAllocatorDumpGuid, Node*>;
GlobalDumpGraph();
+
+ GlobalDumpGraph(const GlobalDumpGraph&) = delete;
+ GlobalDumpGraph& operator=(const GlobalDumpGraph&) = delete;
+
~GlobalDumpGraph();
// Creates a container for all the dump graphs for the process given
@@ -293,8 +297,6 @@ class GlobalDumpGraph {
GuidNodeMap nodes_by_guid_;
std::unique_ptr<GlobalDumpGraph::Process> shared_memory_graph_;
ProcessDumpGraphMap process_dump_graphs_;
-
- DISALLOW_COPY_AND_ASSIGN(GlobalDumpGraph);
};
} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h
index 31b36ed7dc7..5660a8538d1 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h
+++ b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/containers/flat_map.h"
+#include "base/memory/raw_ptr.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "services/resource_coordinator/memory_instrumentation/coordinator_impl.h"
#include "services/resource_coordinator/memory_instrumentation/queued_request.h"
@@ -45,7 +46,7 @@ class QueuedRequestDispatcher {
ClientInfo(ClientInfo&& other);
~ClientInfo();
- mojom::ClientProcess* const client;
+ const raw_ptr<mojom::ClientProcess> client;
const base::ProcessId pid;
const mojom::ProcessType process_type;
const absl::optional<std::string> service_name;
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 1afe539a082..0559f0a4a59 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
@@ -7,9 +7,9 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/flat_map.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "build/build_config.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
index aef7f5a0309..7365b1e4d49 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
@@ -7,8 +7,8 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -37,6 +37,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
mojo::PendingRemote<mojom::Coordinator> coordinator,
bool is_browser_process = false);
+ ClientProcessImpl(const ClientProcessImpl&) = delete;
+ ClientProcessImpl& operator=(const ClientProcessImpl&) = delete;
+
private:
friend std::default_delete<ClientProcessImpl>; // For testing
friend class MemoryTracingIntegrationTest;
@@ -103,8 +106,6 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
// MemoryDumpManager in each process. Setting up MemoryDumpManager should
// be moved away from TracingObserver.
std::unique_ptr<TracingObserver> tracing_observer_;
-
- DISALLOW_COPY_AND_ASSIGN(ClientProcessImpl);
};
} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
index 216e1bc6726..38fe3f92099 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
@@ -79,6 +79,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
const mojom::AggregatedMetricsPtr aggregated_metrics_;
};
+ GlobalMemoryDump(const GlobalMemoryDump&) = delete;
+ GlobalMemoryDump& operator=(const GlobalMemoryDump&) = delete;
+
~GlobalMemoryDump();
// Creates an owned instance of this class wrapping the given mojo struct.
@@ -97,8 +100,6 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
std::forward_list<ProcessDump> process_dumps_;
AggregatedMetrics aggregated_metrics_;
-
- DISALLOW_COPY_AND_ASSIGN(GlobalMemoryDump);
};
} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
index 72157b5345f..3426eadf1ee 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
@@ -38,6 +38,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
bool is_browser_process);
static MemoryInstrumentation* GetInstance();
+ MemoryInstrumentation(const MemoryInstrumentation&) = delete;
+ MemoryInstrumentation& operator=(const MemoryInstrumentation&) = delete;
+
// Retrieves a Coordinator interface to communicate with the service. This is
// safe to call from any thread.
memory_instrumentation::mojom::Coordinator* GetCoordinator() const {
@@ -110,8 +113,6 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
// Only browser process is allowed to request memory dumps.
const bool is_browser_process_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryInstrumentation);
};
} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc
index 374ff2a3d14..a99c1ce55f5 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/raw_ptr.h"
#include "base/test/task_environment.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
@@ -9,7 +10,7 @@
#include "base/callback_helpers.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/test/test_io_thread.h"
#include "base/test/trace_event_analyzer.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -132,7 +133,7 @@ class MockCoordinator : public mojom::Coordinator {
private:
mojo::ReceiverSet<mojom::Coordinator> receivers_;
- MemoryTracingIntegrationTest* client_;
+ raw_ptr<MemoryTracingIntegrationTest> client_;
};
class MemoryTracingIntegrationTest : public testing::Test {
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h
index 0cd0b40e418..431a81a87fe 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h
@@ -6,7 +6,7 @@
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
@@ -57,8 +57,8 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
// Returns true if the dump mode is allowed for current tracing session.
bool IsDumpModeAllowed(base::trace_event::MemoryDumpLevelOfDetail) const;
- base::trace_event::MemoryDumpManager* const memory_dump_manager_;
- base::trace_event::TraceLog* const trace_log_;
+ const raw_ptr<base::trace_event::MemoryDumpManager> memory_dump_manager_;
+ const raw_ptr<base::trace_event::TraceLog> trace_log_;
std::unique_ptr<base::trace_event::TraceConfig::MemoryDumpConfig>
memory_dump_config_;
};
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h
index 6dc9a0db3d6..bea41d11557 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h
@@ -6,7 +6,6 @@
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/thread_annotations.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h
index 60cc56e6a18..81c75623cc7 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h
@@ -6,7 +6,6 @@
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h"
diff --git a/chromium/services/service_manager/BUILD.gn b/chromium/services/service_manager/BUILD.gn
index 51ca59e213a..b28a2863592 100644
--- a/chromium/services/service_manager/BUILD.gn
+++ b/chromium/services/service_manager/BUILD.gn
@@ -43,13 +43,14 @@ source_set("service_manager") {
"//build:chromeos_buildflags",
"//components/services/filesystem:lib",
"//components/services/filesystem/public/mojom",
+ "//sandbox/policy",
"//ui/base",
]
public_deps = [
"//base",
"//mojo/public/cpp/bindings",
- "//sandbox/policy",
+ "//sandbox/policy/mojom",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
]
diff --git a/chromium/services/service_manager/background_service_manager.cc b/chromium/services/service_manager/background_service_manager.cc
index 22656514c8d..5221bfe663b 100644
--- a/chromium/services/service_manager/background_service_manager.cc
+++ b/chromium/services/service_manager/background_service_manager.cc
@@ -12,9 +12,9 @@
#include "base/message_loop/message_pump_default.h"
#include "base/path_service.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/simple_thread.h"
#include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/service_manager.h"
diff --git a/chromium/services/service_manager/background_service_manager.h b/chromium/services/service_manager/background_service_manager.h
index d7b1a1b8019..438791d1c2e 100644
--- a/chromium/services/service_manager/background_service_manager.h
+++ b/chromium/services/service_manager/background_service_manager.h
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/macros.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "services/service_manager/public/cpp/manifest.h"
diff --git a/chromium/services/service_manager/catalog.h b/chromium/services/service_manager/catalog.h
index a01722a65cb..f12652d39e2 100644
--- a/chromium/services/service_manager/catalog.h
+++ b/chromium/services/service_manager/catalog.h
@@ -8,7 +8,6 @@
#include <map>
#include <vector>
-#include "base/macros.h"
#include "services/service_manager/public/cpp/manifest.h"
namespace service_manager {
diff --git a/chromium/services/service_manager/public/cpp/connector.h b/chromium/services/service_manager/public/cpp/connector.h
index 303dab76f41..9192b791cdd 100644
--- a/chromium/services/service_manager/public/cpp/connector.h
+++ b/chromium/services/service_manager/public/cpp/connector.h
@@ -10,6 +10,7 @@
#include <utility>
#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -62,11 +63,15 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT Connector {
}
private:
- Connector* connector_;
+ raw_ptr<Connector> connector_;
};
explicit Connector(mojo::PendingRemote<mojom::Connector> unbound_state);
explicit Connector(mojo::Remote<mojom::Connector> connector);
+
+ Connector(const Connector&) = delete;
+ Connector& operator=(const Connector&) = delete;
+
~Connector();
// Creates a new Connector instance and fills in |*receiver| with a request
@@ -264,8 +269,6 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT Connector {
local_binder_overrides_;
base::WeakPtrFactory<Connector> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(Connector);
};
} // namespace service_manager
diff --git a/chromium/services/service_manager/public/cpp/interface_provider.cc b/chromium/services/service_manager/public/cpp/interface_provider.cc
index dd64443650f..f60cd7ece3d 100644
--- a/chromium/services/service_manager/public/cpp/interface_provider.cc
+++ b/chromium/services/service_manager/public/cpp/interface_provider.cc
@@ -4,8 +4,6 @@
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "base/macros.h"
-
namespace service_manager {
InterfaceProvider::InterfaceProvider(
@@ -35,7 +33,6 @@ void InterfaceProvider::Close() {
void InterfaceProvider::Bind(
mojo::PendingRemote<mojom::InterfaceProvider> interface_provider) {
DCHECK(pending_receiver_ || !interface_provider_);
- DCHECK(forward_callback_.is_null());
if (pending_receiver_) {
mojo::FusePipes(std::move(pending_receiver_),
std::move(interface_provider));
@@ -44,14 +41,6 @@ void InterfaceProvider::Bind(
}
}
-void InterfaceProvider::Forward(const ForwardCallback& callback) {
- DCHECK(pending_receiver_);
- DCHECK(forward_callback_.is_null());
- interface_provider_.reset();
- pending_receiver_.PassPipe().reset();
- forward_callback_ = callback;
-}
-
void InterfaceProvider::SetConnectionLostClosure(
base::OnceClosure connection_lost_closure) {
interface_provider_.set_disconnect_handler(
@@ -72,13 +61,8 @@ void InterfaceProvider::GetInterfaceByName(
return;
}
- if (!forward_callback_.is_null()) {
- DCHECK(!interface_provider_.is_bound());
- forward_callback_.Run(name, std::move(request_handle));
- } else {
- DCHECK(interface_provider_.is_bound());
- interface_provider_->GetInterface(name, std::move(request_handle));
- }
+ DCHECK(interface_provider_.is_bound());
+ interface_provider_->GetInterface(name, std::move(request_handle));
}
bool InterfaceProvider::HasBinderForName(const std::string& name) const {
diff --git a/chromium/services/service_manager/public/cpp/interface_provider.h b/chromium/services/service_manager/public/cpp/interface_provider.h
index e6467d7c4fb..fc38c39bba0 100644
--- a/chromium/services/service_manager/public/cpp/interface_provider.h
+++ b/chromium/services/service_manager/public/cpp/interface_provider.h
@@ -6,6 +6,7 @@
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_INTERFACE_PROVIDER_H_
#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -23,9 +24,6 @@ namespace service_manager {
// Connection.
class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
public:
- using ForwardCallback =
- base::RepeatingCallback<void(const std::string&,
- mojo::ScopedMessagePipeHandle)>;
class TestApi {
public:
explicit TestApi(InterfaceProvider* provider) : provider_(provider) {}
@@ -54,7 +52,7 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
}
private:
- InterfaceProvider* provider_;
+ raw_ptr<InterfaceProvider> provider_;
};
// Constructs an InterfaceProvider which is usable immediately despite not
@@ -71,6 +69,9 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
mojo::PendingRemote<mojom::InterfaceProvider> interface_provider,
scoped_refptr<base::SequencedTaskRunner> task_runner);
+ InterfaceProvider(const InterfaceProvider&) = delete;
+ InterfaceProvider& operator=(const InterfaceProvider&) = delete;
+
~InterfaceProvider();
// Closes the currently bound mojo::PendingRemote<InterfaceProvider> for this
@@ -79,16 +80,8 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
void Close();
// Binds this InterfaceProvider to an actual mojom::InterfaceProvider pipe.
- // It is an error to call this on a forwarding InterfaceProvider, i.e. this
- // call is exclusive to Forward().
void Bind(mojo::PendingRemote<mojom::InterfaceProvider> interface_provider);
- // Sets this InterfaceProvider to forward all GetInterface() requests to
- // |callback|. It is an error to call this on a bound InterfaceProvider, i.e.
- // this call is exclusive to Bind(). In addition, and unlike Bind(), this MUST
- // be called before any calls to GetInterface() are made.
- void Forward(const ForwardCallback& callback);
-
// Sets a closure to be run when the remote InterfaceProvider pipe is closed.
void SetConnectionLostClosure(base::OnceClosure connection_lost_closure);
@@ -125,13 +118,7 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
mojo::PendingReceiver<mojom::InterfaceProvider> pending_receiver_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
- // A callback to receive all GetInterface() requests in lieu of the
- // InterfaceProvider pipe.
- ForwardCallback forward_callback_;
-
base::WeakPtrFactory<InterfaceProvider> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(InterfaceProvider);
};
} // namespace service_manager
diff --git a/chromium/services/service_manager/public/cpp/local_interface_provider.h b/chromium/services/service_manager/public/cpp/local_interface_provider.h
index b8e03ca38c5..2dbbbf48a02 100644
--- a/chromium/services/service_manager/public/cpp/local_interface_provider.h
+++ b/chromium/services/service_manager/public/cpp/local_interface_provider.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_SERVICE_MANAGER_PUBLIC_CPP_LOCAL_INTERFACE_PROVIDER_H_
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_LOCAL_INTERFACE_PROVIDER_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/service_manager/public/cpp/export.h"
diff --git a/chromium/services/service_manager/public/cpp/manifest.h b/chromium/services/service_manager/public/cpp/manifest.h
index 568d9f37b0d..3162eb6819f 100644
--- a/chromium/services/service_manager/public/cpp/manifest.h
+++ b/chromium/services/service_manager/public/cpp/manifest.h
@@ -92,7 +92,7 @@ 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 sandbox::policy::SandboxType (see
+ // a child process sandboxed according to sandbox::mojom::Sandbox (see
// Options below).
kOutOfProcessBuiltin,
@@ -102,7 +102,7 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_CPP) Manifest {
// "${service_name}.service.exe" on Windows).
//
// Proper sandboxing is currently not supported for standalone service
- // executables, so sandbox::policy::SandboxType (see Options below) is
+ // executables, so sandbox::mojom::Sandbox (see Options below) is
// ignored. This renders
// standalone service executables generally unsuitable for production
// environments.
@@ -153,7 +153,7 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_CPP) Manifest {
// |kStandaloneExecutable|.
//
// TODO(https://crbug.com/915806): Make this field a
- // sandbox::policy::SandboxType enum.
+ // sandbox::mojom::Sandbox 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 c3ec6c6a4cd..3e943541994 100644
--- a/chromium/services/service_manager/public/cpp/service.h
+++ b/chromium/services/service_manager/public/cpp/service.h
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/process/process_handle.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
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 745a09b6579..db840830668 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/main.cc
+++ b/chromium/services/service_manager/public/cpp/service_executable/main.cc
@@ -12,7 +12,6 @@
#include "base/files/file_path.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/process/launch.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
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 8d99a8e2773..172f9d8ed85 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
@@ -23,6 +23,7 @@
#include "base/rand_util.h"
#include "base/system/sys_info.h"
#include "sandbox/policy/linux/sandbox_linux.h"
+#include "sandbox/policy/sandbox_type.h"
#endif
namespace service_manager {
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 9f3f1a3c7ee..4c32cc68eae 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
@@ -5,7 +5,6 @@
#ifndef SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_EXECUTABLE_SERVICE_EXECUTABLE_ENVIRONMENT_H_
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_EXECUTABLE_SERVICE_EXECUTABLE_ENVIRONMENT_H_
-#include "base/macros.h"
#include "base/threading/thread.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/services/service_manager/public/cpp/service_filter.h b/chromium/services/service_manager/public/cpp/service_filter.h
index ca71447ba3e..4e7afe79bb5 100644
--- a/chromium/services/service_manager/public/cpp/service_filter.h
+++ b/chromium/services/service_manager/public/cpp/service_filter.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/token.h"
#include "services/service_manager/public/cpp/identity.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chromium/services/service_manager/public/cpp/service_keepalive.h b/chromium/services/service_manager/public/cpp/service_keepalive.h
index 5ae458ceace..71416c4085f 100644
--- a/chromium/services/service_manager/public/cpp/service_keepalive.h
+++ b/chromium/services/service_manager/public/cpp/service_keepalive.h
@@ -6,7 +6,7 @@
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_KEEPALIVE_H_
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
@@ -86,7 +86,7 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceKeepalive {
void OnTimerExpired();
- ServiceReceiver* const receiver_;
+ const raw_ptr<ServiceReceiver> receiver_;
const absl::optional<base::TimeDelta> idle_timeout_;
absl::optional<base::OneShotTimer> idle_timer_;
base::ObserverList<Observer> observers_;
diff --git a/chromium/services/service_manager/public/cpp/service_receiver.h b/chromium/services/service_manager/public/cpp/service_receiver.h
index 4ed67e1c27c..dd6301c51e2 100644
--- a/chromium/services/service_manager/public/cpp/service_receiver.h
+++ b/chromium/services/service_manager/public/cpp/service_receiver.h
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/service_manager/public/cpp/standalone_connector_impl.h b/chromium/services/service_manager/public/cpp/standalone_connector_impl.h
index 7f578ea9be5..18723ff0e3f 100644
--- a/chromium/services/service_manager/public/cpp/standalone_connector_impl.h
+++ b/chromium/services/service_manager/public/cpp/standalone_connector_impl.h
@@ -6,7 +6,7 @@
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_STANDALONE_CONNECTOR_IMPL_H_
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -71,7 +71,7 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) StandaloneConnectorImpl
RegisterServiceInstanceCallback callback) override;
void Clone(mojo::PendingReceiver<mojom::Connector> receiver) override;
- Delegate* const delegate_;
+ const raw_ptr<Delegate> delegate_;
mojo::ReceiverSet<mojom::Connector> receivers_;
};
diff --git a/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc b/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc
index 77530d61bd9..560cf0da535 100644
--- a/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc
+++ b/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc
@@ -4,7 +4,6 @@
#include "services/service_manager/public/cpp/standalone_connector_impl.h"
-#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
diff --git a/chromium/services/service_manager/public/java/src/org/chromium/services/service_manager/Connector.java b/chromium/services/service_manager/public/java/src/org/chromium/services/service_manager/Connector.java
index 6b4fdcee4a4..8c72cadbf8c 100644
--- a/chromium/services/service_manager/public/java/src/org/chromium/services/service_manager/Connector.java
+++ b/chromium/services/service_manager/public/java/src/org/chromium/services/service_manager/Connector.java
@@ -19,7 +19,7 @@ public class Connector implements ConnectionErrorHandler {
private org.chromium.service_manager.mojom.Connector.Proxy mConnector;
private static class ConnectorBindInterfaceResponseImpl
- implements org.chromium.service_manager.mojom.Connector.BindInterfaceResponse {
+ implements org.chromium.service_manager.mojom.Connector.BindInterface_Response {
@Override
public void call(Integer result, Identity identity) {}
}
@@ -41,7 +41,7 @@ public class Connector implements ConnectionErrorHandler {
ServiceFilter filter = new ServiceFilter();
filter.serviceName = serviceName;
- org.chromium.service_manager.mojom.Connector.BindInterfaceResponse callback =
+ org.chromium.service_manager.mojom.Connector.BindInterface_Response callback =
new ConnectorBindInterfaceResponseImpl();
mConnector.bindInterface(filter, interfaceName, request.passHandle(),
org.chromium.service_manager.mojom.BindInterfacePriority.IMPORTANT, callback);
diff --git a/chromium/services/service_manager/service_instance.cc b/chromium/services/service_manager/service_instance.cc
index 192056ff5fa..5de3bb55ff9 100644
--- a/chromium/services/service_manager/service_instance.cc
+++ b/chromium/services/service_manager/service_instance.cc
@@ -20,6 +20,7 @@
#include "ui/base/l10n/l10n_util.h"
#if !defined(OS_IOS)
+#include "sandbox/policy/mojom/sandbox.mojom.h"
#include "services/service_manager/service_process_launcher.h"
#endif // !defined(OS_IOS)
@@ -156,7 +157,7 @@ void ServiceInstance::StartWithRemote(
#if !defined(OS_IOS)
bool ServiceInstance::StartWithProcessHost(
std::unique_ptr<ServiceProcessHost> host,
- sandbox::policy::SandboxType sandbox_type) {
+ sandbox::mojom::Sandbox sandbox_type) {
DCHECK(!service_remote_);
DCHECK(!process_host_);
diff --git a/chromium/services/service_manager/service_instance.h b/chromium/services/service_manager/service_instance.h
index df3d73854b7..e5d03b78d5e 100644
--- a/chromium/services/service_manager/service_instance.h
+++ b/chromium/services/service_manager/service_instance.h
@@ -12,7 +12,7 @@
#include <string>
#include "base/containers/unique_ptr_adapters.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process_handle.h"
#include "build/build_config.h"
@@ -23,7 +23,6 @@
#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"
@@ -32,6 +31,12 @@
#include "services/service_manager/public/mojom/service_manager.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+namespace sandbox {
+namespace mojom {
+enum class Sandbox;
+}
+} // namespace sandbox
+
namespace service_manager {
class ServiceManager;
@@ -69,7 +74,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,
- sandbox::policy::SandboxType sandbox_type);
+ sandbox::mojom::Sandbox sandbox_type);
#endif // !defined(OS_IOS)
// Binds an endpoint for this instance to receive metadata about its
@@ -158,7 +163,7 @@ class ServiceInstance : public mojom::Connector,
mojo::PendingRemote<mojom::ServiceManagerListener> listener) override;
// Always owns |this|.
- service_manager::ServiceManager* const service_manager_;
+ const raw_ptr<service_manager::ServiceManager> service_manager_;
// A unique identity for this instance. Distinct from PID, as a single process
// may host multiple service instances. Globally unique across time and space.
diff --git a/chromium/services/service_manager/service_instance_registry.h b/chromium/services/service_manager/service_instance_registry.h
index e82a36806a2..94252a1067c 100644
--- a/chromium/services/service_manager/service_instance_registry.h
+++ b/chromium/services/service_manager/service_instance_registry.h
@@ -8,7 +8,7 @@
#include <map>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/token.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/service_filter.h"
@@ -62,7 +62,7 @@ class ServiceInstanceRegistry {
~Entry();
base::Token guid;
- ServiceInstance* instance = nullptr;
+ raw_ptr<ServiceInstance> instance = nullptr;
};
struct RegularInstanceKey {
diff --git a/chromium/services/service_manager/service_manager.cc b/chromium/services/service_manager/service_manager.cc
index 3b43d60a938..493a95a4c6a 100644
--- a/chromium/services/service_manager/service_manager.cc
+++ b/chromium/services/service_manager/service_manager.cc
@@ -12,7 +12,6 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/process/process.h"
@@ -20,7 +19,7 @@
#include "base/token.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "sandbox/policy/sandbox_type.h"
+#include "sandbox/policy/mojom/sandbox.mojom.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"
@@ -83,15 +82,15 @@ class DefaultServiceProcessHost : public ServiceProcessHost {
mojo::PendingRemote<mojom::Service> Launch(
const Identity& identity,
- sandbox::policy::SandboxType sandbox_type,
+ sandbox::mojom::Sandbox sandbox_type,
const std::u16string& display_name,
LaunchCallback callback) override {
#if defined(OS_IOS)
return mojo::NullRemote();
#else
// TODO(https://crbug.com/781334): Support sandboxing.
- CHECK_EQ(sandbox_type, sandbox::policy::SandboxType::kNoSandbox);
- return launcher_.Start(identity, sandbox::policy::SandboxType::kNoSandbox,
+ CHECK_EQ(sandbox_type, sandbox::mojom::Sandbox::kNoSandbox);
+ return launcher_.Start(identity, sandbox::mojom::Sandbox::kNoSandbox,
std::move(callback));
#endif // defined(OS_IOS)
}
diff --git a/chromium/services/service_manager/service_manager.h b/chromium/services/service_manager/service_manager.h
index b1e9d35bcd3..dabffe588d7 100644
--- a/chromium/services/service_manager/service_manager.h
+++ b/chromium/services/service_manager/service_manager.h
@@ -11,7 +11,7 @@
#include "base/containers/unique_ptr_adapters.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/process/process.h"
#include "base/token.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -204,7 +204,7 @@ class ServiceManager : public Service {
// Always points to the ServiceManager's own Instance. Note that this
// ServiceInstance still has an entry in |instances_|.
- ServiceInstance* service_manager_instance_;
+ raw_ptr<ServiceInstance> service_manager_instance_;
mojo::RemoteSet<mojom::ServiceManagerListener> listeners_;
};
diff --git a/chromium/services/service_manager/service_process_host.h b/chromium/services/service_manager/service_process_host.h
index 9bb97736459..81d1b17f920 100644
--- a/chromium/services/service_manager/service_process_host.h
+++ b/chromium/services/service_manager/service_process_host.h
@@ -8,10 +8,9 @@
#include <string>
#include "base/callback.h"
-#include "base/macros.h"
#include "base/process/process_handle.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "sandbox/policy/sandbox_type.h"
+#include "sandbox/policy/mojom/sandbox.mojom.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/mojom/service.mojom.h"
@@ -37,7 +36,7 @@ class ServiceProcessHost {
using LaunchCallback = base::OnceCallback<void(base::ProcessId)>;
virtual mojo::PendingRemote<mojom::Service> Launch(
const Identity& identity,
- sandbox::policy::SandboxType sandbox_type,
+ sandbox::mojom::Sandbox sandbox_type,
const std::u16string& 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 72a2161d61c..5f32c48eb61 100644
--- a/chromium/services/service_manager/service_process_launcher.cc
+++ b/chromium/services/service_manager/service_process_launcher.cc
@@ -23,8 +23,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
+#include "base/task/task_runner_util.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -32,6 +32,8 @@
#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/mojom/sandbox.mojom.h"
+#include "sandbox/policy/sandbox_type.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"
@@ -57,9 +59,12 @@ class ServiceProcessLauncher::ProcessState
public:
ProcessState() { DETACH_FROM_SEQUENCE(sequence_checker_); }
+ ProcessState(const ProcessState&) = delete;
+ ProcessState& operator=(const ProcessState&) = delete;
+
base::ProcessId LaunchInBackground(
const Identity& target,
- sandbox::policy::SandboxType sandbox_type,
+ sandbox::mojom::Sandbox sandbox_type,
std::unique_ptr<base::CommandLine> child_command_line,
mojo::PlatformChannel::HandlePassingInfo handle_passing_info,
mojo::PlatformChannel channel,
@@ -74,8 +79,6 @@ class ServiceProcessLauncher::ProcessState
base::Process child_process_;
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(ProcessState);
};
ServiceProcessLauncher::ServiceProcessLauncher(
@@ -98,7 +101,7 @@ ServiceProcessLauncher::~ServiceProcessLauncher() {
mojo::PendingRemote<mojom::Service> ServiceProcessLauncher::Start(
const Identity& target,
- sandbox::policy::SandboxType sandbox_type,
+ sandbox::mojom::Sandbox sandbox_type,
ProcessReadyCallback callback) {
DCHECK(!state_);
@@ -132,10 +135,10 @@ mojo::PendingRemote<mojom::Service> ServiceProcessLauncher::Start(
target.instance_group().ToString());
#endif
- if (!IsUnsandboxedSandboxType(sandbox_type)) {
+ if (!sandbox::policy::IsUnsandboxedSandboxType(sandbox_type)) {
child_command_line->AppendSwitchASCII(
sandbox::policy::switches::kServiceSandboxType,
- StringFromUtilitySandboxType(sandbox_type));
+ sandbox::policy::StringFromUtilitySandboxType(sandbox_type));
}
mojo::PlatformChannel::HandlePassingInfo handle_passing_info;
@@ -177,7 +180,7 @@ ServiceProcessLauncher::PassServiceRequestOnCommandLine(
base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground(
const Identity& target,
- sandbox::policy::SandboxType sandbox_type,
+ sandbox::mojom::Sandbox sandbox_type,
std::unique_ptr<base::CommandLine> child_command_line,
mojo::PlatformChannel::HandlePassingInfo handle_passing_info,
mojo::PlatformChannel channel,
@@ -211,7 +214,7 @@ base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground(
}
#elif defined(OS_FUCHSIA)
// LaunchProcess will share stdin/out/err with the child process by default.
- if (!IsUnsandboxedSandboxType(sandbox_type))
+ if (!sandbox::policy::IsUnsandboxedSandboxType(sandbox_type))
NOTIMPLEMENTED();
options.handles_to_transfer = std::move(handle_passing_info);
#elif defined(OS_POSIX)
@@ -232,7 +235,7 @@ base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground(
DVLOG(2) << "Launching child with command line: "
<< child_command_line->GetCommandLineString();
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
- if (!IsUnsandboxedSandboxType(sandbox_type)) {
+ if (!sandbox::policy::IsUnsandboxedSandboxType(sandbox_type)) {
child_process_ =
sandbox::NamespaceSandbox::LaunchProcess(*child_command_line, options);
if (!child_process_.IsValid())
diff --git a/chromium/services/service_manager/service_process_launcher.h b/chromium/services/service_manager/service_process_launcher.h
index 43b29a4a357..a0d5a8eed64 100644
--- a/chromium/services/service_manager/service_process_launcher.h
+++ b/chromium/services/service_manager/service_process_launcher.h
@@ -7,13 +7,12 @@
#include "base/callback.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "sandbox/policy/sandbox_type.h"
+#include "sandbox/policy/mojom/sandbox.mojom.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/service_manager/service_process_launcher_delegate.h"
@@ -51,7 +50,7 @@ class ServiceProcessLauncher {
// |Start()| was called) when the child has been started (or failed to start).
mojo::PendingRemote<mojom::Service> Start(
const Identity& target,
- sandbox::policy::SandboxType sandbox_type,
+ sandbox::mojom::Sandbox sandbox_type,
ProcessReadyCallback callback);
// Exposed publicly for use in tests. Creates a new Service pipe, passing the
diff --git a/chromium/services/services_strings.grd b/chromium/services/services_strings.grd
index 10b6efc7a3a..77fce4ebd86 100644
--- a/chromium/services/services_strings.grd
+++ b/chromium/services/services_strings.grd
@@ -191,6 +191,9 @@ This file contains strings for code in //services.
<message name="IDS_PROXY_RESOLVER_DISPLAY_NAME" desc="The name of the display name (in system task manager, etc) of the service process used for out-of-process V8 proxy resolution.">
V8 Proxy Resolver
</message>
+ <message name="IDS_WINDOWS_SYSTEM_PROXY_RESOLVER_DISPLAY_NAME" desc="The name of the display name (in system task manager, etc) of the service process used for out-of-process WinHttp proxy resolution.">
+ WinHttp Proxy Resolver
+ </message>
</messages>
</release>
</grit>
diff --git a/chromium/services/services_strings_grd/IDS_WINDOWS_SYSTEM_PROXY_RESOLVER_DISPLAY_NAME.png.sha1 b/chromium/services/services_strings_grd/IDS_WINDOWS_SYSTEM_PROXY_RESOLVER_DISPLAY_NAME.png.sha1
new file mode 100644
index 00000000000..eb0053ffdaa
--- /dev/null
+++ b/chromium/services/services_strings_grd/IDS_WINDOWS_SYSTEM_PROXY_RESOLVER_DISPLAY_NAME.png.sha1
@@ -0,0 +1 @@
+9976cb73a1085fc055d881101064e2c8996a12fc \ No newline at end of file
diff --git a/chromium/services/shape_detection/BUILD.gn b/chromium/services/shape_detection/BUILD.gn
index 47c56772153..b61237bc9ff 100644
--- a/chromium/services/shape_detection/BUILD.gn
+++ b/chromium/services/shape_detection/BUILD.gn
@@ -5,6 +5,8 @@
import("//build/config/chromeos/ui_mode.gni")
import("//testing/test.gni")
+use_barhopper = is_chrome_branded && (is_chromeos_ash || is_chromeos_lacros)
+
source_set("lib") {
sources = [
"shape_detection_service.cc",
@@ -12,16 +14,16 @@ source_set("lib") {
"text_detection_impl.h",
]
+ deps = [
+ "//build:branding_buildflags",
+ "//build:chromeos_buildflags",
+ "//mojo/public/cpp/bindings",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ]
+
if (is_mac) {
sources += [
- "barcode_detection_impl_mac.h",
- "barcode_detection_impl_mac.mm",
- "barcode_detection_impl_mac_vision.h",
- "barcode_detection_impl_mac_vision.mm",
- "barcode_detection_impl_mac_vision_api.h",
- "barcode_detection_impl_mac_vision_api.mm",
- "barcode_detection_provider_mac.h",
- "barcode_detection_provider_mac.mm",
"detection_utils_mac.h",
"detection_utils_mac.mm",
"face_detection_impl_mac.h",
@@ -37,8 +39,6 @@ source_set("lib") {
weak_frameworks = [ "Vision.framework" ]
} else if (is_win) {
sources += [
- "barcode_detection_provider_impl.cc",
- "barcode_detection_provider_impl.h",
"detection_utils_win.cc",
"detection_utils_win.h",
"face_detection_impl_win.cc",
@@ -48,40 +48,48 @@ source_set("lib") {
"text_detection_impl_win.cc",
"text_detection_impl_win.h",
]
- } else if (is_chromeos_ash && is_chrome_branded) {
+ } else if (is_android) {
+ # No C++ sources needed, face and text detection is provided by Java.
+ } else {
+ sources += [
+ "face_detection_provider_impl.cc",
+ "face_detection_provider_impl.h",
+ "text_detection_impl.cc",
+ ]
+ }
+
+ if (is_mac) {
+ # On macOS there is a barcode detection API available from the platform.
+ sources += [
+ "barcode_detection_impl_mac.h",
+ "barcode_detection_impl_mac.mm",
+ "barcode_detection_impl_mac_vision.h",
+ "barcode_detection_impl_mac_vision.mm",
+ "barcode_detection_impl_mac_vision_api.h",
+ "barcode_detection_impl_mac_vision_api.mm",
+ "barcode_detection_provider_mac.h",
+ "barcode_detection_provider_mac.mm",
+ ]
+ } else if (is_android) {
+ # No C++ sources needed, barcode detection is provided by Java.
+ } else if (use_barhopper) {
sources += [
"barcode_detection_impl_barhopper.cc",
"barcode_detection_impl_barhopper.h",
"barcode_detection_provider_barhopper.cc",
"barcode_detection_provider_barhopper.h",
- "face_detection_provider_impl.cc",
- "face_detection_provider_impl.h",
- "text_detection_impl.cc",
]
+ deps += [ "//third_party/barhopper" ]
} else {
+ # Otherwise, use a stub implementation.
sources += [
"barcode_detection_provider_impl.cc",
"barcode_detection_provider_impl.h",
- "face_detection_provider_impl.cc",
- "face_detection_provider_impl.h",
- "text_detection_impl.cc",
]
}
configs += [ "//build/config/compiler:wexit_time_destructors" ]
- deps = [
- "//build:branding_buildflags",
- "//build:chromeos_buildflags",
- "//mojo/public/cpp/bindings",
- "//ui/gfx",
- "//ui/gfx/geometry",
- ]
-
- if (is_chromeos_ash && is_chrome_branded) {
- deps += [ "//third_party/barhopper:barhopper" ]
- }
-
public_deps = [
"//base",
"//media/capture",
@@ -153,7 +161,7 @@ source_set("tests") {
]
}
- if (is_chromeos_ash && is_chrome_branded) {
+ if (use_barhopper) {
sources += [ "barcode_detection_impl_barhopper_unittest.cc" ]
}
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 88b115891fe..dadafee8712 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
@@ -53,7 +53,7 @@ public class BarcodeDetectionImplTest {
final ArrayBlockingQueue<int[]> queue = new ArrayBlockingQueue<>(13);
provider.enumerateSupportedFormats(
- new BarcodeDetectionProvider.EnumerateSupportedFormatsResponse() {
+ new BarcodeDetectionProvider.EnumerateSupportedFormats_Response() {
@Override
public void call(int[] results) {
queue.add(results);
@@ -87,7 +87,7 @@ public class BarcodeDetectionImplTest {
BarcodeDetection detector = new BarcodeDetectionImpl(options);
final ArrayBlockingQueue<BarcodeDetectionResult[]> queue = new ArrayBlockingQueue<>(1);
- detector.detect(mojoBitmap, new BarcodeDetection.DetectResponse() {
+ detector.detect(mojoBitmap, new BarcodeDetection.Detect_Response() {
@Override
public void call(BarcodeDetectionResult[] results) {
queue.add(results);
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 de1eab01226..924858b9ca8 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
@@ -63,7 +63,7 @@ public class FaceDetectionImplTest {
}
final ArrayBlockingQueue<FaceDetectionResult[]> queue = new ArrayBlockingQueue<>(1);
- detector.detect(mojoBitmap, new FaceDetection.DetectResponse() {
+ detector.detect(mojoBitmap, new FaceDetection.Detect_Response() {
@Override
public void call(FaceDetectionResult[] results) {
queue.add(results);
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 9ea54a4fa93..864155f0152 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
@@ -41,7 +41,7 @@ public class TextDetectionImplTest {
TextDetection detector = new TextDetectionImpl();
final ArrayBlockingQueue<TextDetectionResult[]> queue = new ArrayBlockingQueue<>(1);
- detector.detect(mojoBitmap, new TextDetection.DetectResponse() {
+ detector.detect(mojoBitmap, new TextDetection.Detect_Response() {
@Override
public void call(TextDetectionResult[] results) {
queue.add(results);
diff --git a/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc b/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc
index d934ca7585b..644cd688aeb 100644
--- a/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc
+++ b/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc
@@ -15,25 +15,27 @@
namespace shape_detection {
-struct TestParams {
- std::string filename;
- std::string expected_value;
+constexpr struct TestParams {
+ base::FilePath::StringPieceType filename;
+ base::StringPiece expected_value;
float x;
float y;
float width;
float height;
-} kTestParams[] = {{"codabar.png", "A6.2831853B", 24, 24, 448, 95},
- {"code_39.png", "CHROMIUM", 20, 20, 318, 75},
- {"code_93.png", "CHROMIUM", 20, 20, 216, 75},
- {"code_128.png", "Chromium", 20, 20, 246, 75},
- {"data_matrix.png", "Chromium", 11, 11, 53, 53},
- {"ean_8.png", "62831857", 14, 10, 134, 75},
- {"ean_13.png", "6283185307179", 27, 10, 190, 75},
- {"itf.png", "62831853071795", 10, 10, 135, 39},
- {"pdf417.png", "Chromium", 20, 20, 240, 44},
- {"qr_code.png", "https://chromium.org", 40, 40, 250, 250},
- {"upc_a.png", "628318530714", 23, 10, 190, 75},
- {"upc_e.png", "06283186", 23, 10, 102, 75}};
+} kTestParams[] = {
+ {FILE_PATH_LITERAL("codabar.png"), "A6.2831853B", 24, 24, 448, 95},
+ {FILE_PATH_LITERAL("code_39.png"), "CHROMIUM", 20, 20, 318, 75},
+ {FILE_PATH_LITERAL("code_93.png"), "CHROMIUM", 20, 20, 216, 75},
+ {FILE_PATH_LITERAL("code_128.png"), "Chromium", 20, 20, 246, 75},
+ {FILE_PATH_LITERAL("data_matrix.png"), "Chromium", 11, 11, 53, 53},
+ {FILE_PATH_LITERAL("ean_8.png"), "62831857", 14, 10, 134, 75},
+ {FILE_PATH_LITERAL("ean_13.png"), "6283185307179", 27, 10, 190, 75},
+ {FILE_PATH_LITERAL("itf.png"), "62831853071795", 10, 10, 135, 39},
+ {FILE_PATH_LITERAL("pdf417.png"), "Chromium", 20, 20, 240, 44},
+ {FILE_PATH_LITERAL("qr_code.png"), "https://chromium.org", 40, 40, 250,
+ 250},
+ {FILE_PATH_LITERAL("upc_a.png"), "628318530714", 23, 10, 190, 75},
+ {FILE_PATH_LITERAL("upc_e.png"), "06283186", 23, 10, 102, 75}};
class BarcodeDetectionImplBarhopperTest
: public testing::TestWithParam<struct TestParams> {
@@ -58,14 +60,15 @@ class BarcodeDetectionImplBarhopperTest
return barcode_service;
}
- std::unique_ptr<SkBitmap> LoadTestImage(std::string filename) {
+ std::unique_ptr<SkBitmap> LoadTestImage(
+ base::FilePath::StringPieceType filename) {
// Load image data from test directory.
base::FilePath image_path;
EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &image_path));
image_path = image_path.Append(FILE_PATH_LITERAL("services"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("data"))
- .Append(FILE_PATH_LITERAL(filename));
+ .Append(filename);
EXPECT_TRUE(base::PathExists(image_path));
std::string image_data;
EXPECT_TRUE(base::ReadFileToString(image_path, &image_data));
@@ -114,4 +117,4 @@ INSTANTIATE_TEST_SUITE_P(,
BarcodeDetectionImplBarhopperTest,
testing::ValuesIn(kTestParams));
-} // namespace shape_detection \ No newline at end of file
+} // namespace shape_detection
diff --git a/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm b/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm
index 62a57d722b6..8af03ca340a 100644
--- a/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm
+++ b/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm
@@ -112,7 +112,9 @@ TEST_P(BarcodeDetectionImplMacTest, CreateAndDestroy) {
}
// This test generates a single barcode and scans it back.
-TEST_P(BarcodeDetectionImplMacTest, ScanOneBarcode) {
+// Currently disabled due to failures on Mac 12.0
+// TODO(crbug.com/1279895): Re-enable this test.
+TEST_P(BarcodeDetectionImplMacTest, DISABLED_ScanOneBarcode) {
// Barcode detection needs GPU infrastructure.
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseGpuInTests)) {
diff --git a/chromium/services/shape_detection/barcode_detection_impl_mac_vision.h b/chromium/services/shape_detection/barcode_detection_impl_mac_vision.h
index d10211e00f9..4d19d31e40b 100644
--- a/chromium/services/shape_detection/barcode_detection_impl_mac_vision.h
+++ b/chromium/services/shape_detection/barcode_detection_impl_mac_vision.h
@@ -12,7 +12,6 @@
#include <vector>
#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/shape_detection/barcode_detection_impl_mac_vision_api.h"
diff --git a/chromium/services/shape_detection/barcode_detection_provider_mac.h b/chromium/services/shape_detection/barcode_detection_provider_mac.h
index 21e520cd2f3..5dccc8f80cb 100644
--- a/chromium/services/shape_detection/barcode_detection_provider_mac.h
+++ b/chromium/services/shape_detection/barcode_detection_provider_mac.h
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/shape_detection/barcode_detection_impl_mac_vision_api.h"
#include "services/shape_detection/public/mojom/barcodedetection.mojom.h"
diff --git a/chromium/services/shape_detection/detection_utils_mac.h b/chromium/services/shape_detection/detection_utils_mac.h
index 52be0cc89c2..743ad236d4b 100644
--- a/chromium/services/shape_detection/detection_utils_mac.h
+++ b/chromium/services/shape_detection/detection_utils_mac.h
@@ -14,7 +14,6 @@
#include "base/callback.h"
#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/services/shape_detection/detection_utils_mac.mm b/chromium/services/shape_detection/detection_utils_mac.mm
index 32c42f8cf14..93e67f0ddd4 100644
--- a/chromium/services/shape_detection/detection_utils_mac.mm
+++ b/chromium/services/shape_detection/detection_utils_mac.mm
@@ -14,8 +14,8 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/checked_math.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/sys_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
diff --git a/chromium/services/shape_detection/face_detection_impl_mac_vision.h b/chromium/services/shape_detection/face_detection_impl_mac_vision.h
index 203058b66a8..a48116197a4 100644
--- a/chromium/services/shape_detection/face_detection_impl_mac_vision.h
+++ b/chromium/services/shape_detection/face_detection_impl_mac_vision.h
@@ -10,7 +10,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/shape_detection/detection_utils_mac.h"
diff --git a/chromium/services/shape_detection/face_detection_impl_win.h b/chromium/services/shape_detection/face_detection_impl_win.h
index 92f9b18caad..19552c83a5f 100644
--- a/chromium/services/shape_detection/face_detection_impl_win.h
+++ b/chromium/services/shape_detection/face_detection_impl_win.h
@@ -14,7 +14,6 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/shape_detection/public/mojom/facedetection.mojom.h"
diff --git a/chromium/services/shape_detection/face_detection_impl_win_unittest.cc b/chromium/services/shape_detection/face_detection_impl_win_unittest.cc
index ed6b625bce0..aac05ae9e9b 100644
--- a/chromium/services/shape_detection/face_detection_impl_win_unittest.cc
+++ b/chromium/services/shape_detection/face_detection_impl_win_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
-#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
@@ -34,6 +33,10 @@ void DetectCallback(base::OnceClosure quit_closure,
} // namespace
class FaceDetectionImplWinTest : public testing::Test {
+ public:
+ FaceDetectionImplWinTest(const FaceDetectionImplWinTest&) = delete;
+ FaceDetectionImplWinTest& operator=(const FaceDetectionImplWinTest&) = delete;
+
protected:
FaceDetectionImplWinTest() = default;
~FaceDetectionImplWinTest() override = default;
@@ -84,8 +87,6 @@ class FaceDetectionImplWinTest : public testing::Test {
std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer_;
base::test::TaskEnvironment task_environment_;
-
- DISALLOW_COPY_AND_ASSIGN(FaceDetectionImplWinTest);
};
TEST_F(FaceDetectionImplWinTest, ScanOneFace) {
diff --git a/chromium/services/shape_detection/face_detection_provider_mac.h b/chromium/services/shape_detection/face_detection_provider_mac.h
index 013f09cc3c5..2891e7d02ee 100644
--- a/chromium/services/shape_detection/face_detection_provider_mac.h
+++ b/chromium/services/shape_detection/face_detection_provider_mac.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_SHAPE_DETECTION_FACE_DETECTION_PROVIDER_MAC_H_
#define SERVICES_SHAPE_DETECTION_FACE_DETECTION_PROVIDER_MAC_H_
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/shape_detection/public/mojom/facedetection_provider.mojom.h"
diff --git a/chromium/services/shape_detection/face_detection_provider_win.h b/chromium/services/shape_detection/face_detection_provider_win.h
index d4a96233217..81b8385665a 100644
--- a/chromium/services/shape_detection/face_detection_provider_win.h
+++ b/chromium/services/shape_detection/face_detection_provider_win.h
@@ -11,7 +11,6 @@
#include <memory>
#include <utility>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
diff --git a/chromium/services/shape_detection/public/mojom/BUILD.gn b/chromium/services/shape_detection/public/mojom/BUILD.gn
index c0a9ffe7608..2a75d2d1c3c 100644
--- a/chromium/services/shape_detection/public/mojom/BUILD.gn
+++ b/chromium/services/shape_detection/public/mojom/BUILD.gn
@@ -21,8 +21,8 @@ mojom("mojom") {
"//ui/gfx/geometry/mojom",
]
- # Platforms except ChromeOS Ash host shape detection in the GPU process.
- if (is_chromeos_ash && is_chrome_branded) {
+ # Platforms except Chrome OS host shape detection in the GPU process.
+ if ((is_chromeos_ash || is_chromeos_lacros) && is_chrome_branded) {
enabled_features = [ "has_shape_detection_utility" ]
}
}
diff --git a/chromium/services/shape_detection/shape_detection_service.cc b/chromium/services/shape_detection/shape_detection_service.cc
index ec99435c930..408955b4e14 100644
--- a/chromium/services/shape_detection/shape_detection_service.cc
+++ b/chromium/services/shape_detection/shape_detection_service.cc
@@ -8,27 +8,34 @@
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
#include "build/branding_buildflags.h"
#include "build/chromeos_buildflags.h"
-#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_MAC)
+#include "services/shape_detection/text_detection_impl.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#include "services/shape_detection/shape_detection_jni_headers/InterfaceRegistrar_jni.h"
+#endif
+
+#if defined(OS_MAC)
#include "services/shape_detection/barcode_detection_provider_mac.h"
-#include "services/shape_detection/face_detection_provider_mac.h"
-#elif BUILDFLAG(GOOGLE_CHROME_BRANDING) && BUILDFLAG(IS_CHROMEOS_ASH)
+#elif defined(OS_ANDROID)
+// No C++ code, barcode detection comes from Java.
+#elif BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
+ (BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS))
#include "services/shape_detection/barcode_detection_provider_barhopper.h"
-#include "services/shape_detection/face_detection_provider_impl.h"
#else
#include "services/shape_detection/barcode_detection_provider_impl.h"
-#include "services/shape_detection/face_detection_provider_impl.h"
#endif
-#include "services/shape_detection/text_detection_impl.h"
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "services/shape_detection/shape_detection_jni_headers/InterfaceRegistrar_jni.h"
+#if defined(OS_WIN)
+#include "services/shape_detection/face_detection_provider_win.h"
+#elif defined(OS_MAC)
+#include "services/shape_detection/face_detection_provider_mac.h"
+#elif defined(OS_ANDROID)
+// No C++ code, face detection comes from Java.
+#else
+#include "services/shape_detection/face_detection_provider_impl.h"
#endif
namespace shape_detection {
@@ -48,7 +55,8 @@ void ShapeDetectionService::BindBarcodeDetectionProvider(
receiver.PassPipe().release().value());
#elif defined(OS_MAC)
BarcodeDetectionProviderMac::Create(std::move(receiver));
-#elif BUILDFLAG(GOOGLE_CHROME_BRANDING) && BUILDFLAG(IS_CHROMEOS_ASH)
+#elif BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
+ (BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS))
BarcodeDetectionProviderBarhopper::Create(std::move(receiver));
#else
BarcodeDetectionProviderImpl::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 8ca0e0cd185..4e2359316df 100644
--- a/chromium/services/shape_detection/shape_detection_service.h
+++ b/chromium/services/shape_detection/shape_detection_service.h
@@ -6,7 +6,6 @@
#define SERVICES_SHAPE_DETECTION_SHAPE_DETECTION_SERVICE_H_
#include "base/callback.h"
-#include "base/macros.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chromium/services/shape_detection/text_detection_impl.h b/chromium/services/shape_detection/text_detection_impl.h
index d305e3a9903..9aa699f9c45 100644
--- a/chromium/services/shape_detection/text_detection_impl.h
+++ b/chromium/services/shape_detection/text_detection_impl.h
@@ -15,10 +15,11 @@ class TextDetectionImpl {
// Binds TextDetection receiver to an implementation of mojom::TextDetection.
static void Create(mojo::PendingReceiver<mojom::TextDetection> receiver);
+ TextDetectionImpl(const TextDetectionImpl&) = delete;
+ TextDetectionImpl& operator=(const TextDetectionImpl&) = delete;
+
private:
~TextDetectionImpl() = default;
-
- DISALLOW_COPY_AND_ASSIGN(TextDetectionImpl);
};
} // namespace shape_detection
diff --git a/chromium/services/shape_detection/text_detection_impl_win.h b/chromium/services/shape_detection/text_detection_impl_win.h
index 391d32cee20..0aac04d2687 100644
--- a/chromium/services/shape_detection/text_detection_impl_win.h
+++ b/chromium/services/shape_detection/text_detection_impl_win.h
@@ -12,7 +12,6 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/shape_detection/public/mojom/textdetection.mojom.h"
diff --git a/chromium/services/shape_detection/text_detection_impl_win_unittest.cc b/chromium/services/shape_detection/text_detection_impl_win_unittest.cc
index b89f0de8173..5be1115923a 100644
--- a/chromium/services/shape_detection/text_detection_impl_win_unittest.cc
+++ b/chromium/services/shape_detection/text_detection_impl_win_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
@@ -35,6 +34,10 @@ void DetectTextCallback(base::OnceClosure quit_closure,
} // namespace
class TextDetectionImplWinTest : public testing::Test {
+ public:
+ TextDetectionImplWinTest(const TextDetectionImplWinTest&) = delete;
+ TextDetectionImplWinTest& operator=(const TextDetectionImplWinTest&) = delete;
+
protected:
TextDetectionImplWinTest() = default;
~TextDetectionImplWinTest() override = default;
@@ -49,8 +52,6 @@ class TextDetectionImplWinTest : public testing::Test {
std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer_;
base::test::TaskEnvironment task_environment_;
-
- DISALLOW_COPY_AND_ASSIGN(TextDetectionImplWinTest);
};
TEST_F(TextDetectionImplWinTest, ScanOnce) {
diff --git a/chromium/services/strings/services_strings_af.xtb b/chromium/services/strings/services_strings_af.xtb
index b17e1be29f3..dc2e8433ab9 100644
--- a/chromium/services/strings/services_strings_af.xtb
+++ b/chromium/services/strings/services_strings_af.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="af">
+<translation id="1553734813273230889">WinHttp-instaanbedieneroplosser</translation>
<translation id="8191453843330043793">V8-instaanbedieneroplosser</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_am.xtb b/chromium/services/strings/services_strings_am.xtb
index e0e57abff0d..f4e1cc4aded 100644
--- a/chromium/services/strings/services_strings_am.xtb
+++ b/chromium/services/strings/services_strings_am.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="am">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ar.xtb b/chromium/services/strings/services_strings_ar.xtb
index 5784bb0da07..d0c9d9d357c 100644
--- a/chromium/services/strings/services_strings_ar.xtb
+++ b/chromium/services/strings/services_strings_ar.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ar">
+<translation id="1553734813273230889">‏برنامج تعيين الخادم الوكيل لخدمة WinHttp</translation>
<translation id="8191453843330043793">‏محلل وكيل V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_as.xtb b/chromium/services/strings/services_strings_as.xtb
index baaff5aa7e8..0a4cee4c56e 100644
--- a/chromium/services/strings/services_strings_as.xtb
+++ b/chromium/services/strings/services_strings_as.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="as">
+<translation id="1553734813273230889">WinHttp প্ৰ’ক্সী সমাধানকাৰী</translation>
<translation id="8191453843330043793">V8 প্ৰক্সি সমাধানকাৰী</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_az.xtb b/chromium/services/strings/services_strings_az.xtb
index 9866bd507a0..a49470f1c5e 100644
--- a/chromium/services/strings/services_strings_az.xtb
+++ b/chromium/services/strings/services_strings_az.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="az">
+<translation id="1553734813273230889">WinHttp Proksi Həlledicisi</translation>
<translation id="8191453843330043793">V8 Proksi Həlledicisi</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_be.xtb b/chromium/services/strings/services_strings_be.xtb
index df1af97cd10..e49ec4ca37e 100644
--- a/chromium/services/strings/services_strings_be.xtb
+++ b/chromium/services/strings/services_strings_be.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="be">
+<translation id="1553734813273230889">Ператваральнік для проксі-сервераў WinHttp</translation>
<translation id="8191453843330043793">Ператваральнік для проксі-сервераў V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_bg.xtb b/chromium/services/strings/services_strings_bg.xtb
index a3c22afccb4..8df857bdd87 100644
--- a/chromium/services/strings/services_strings_bg.xtb
+++ b/chromium/services/strings/services_strings_bg.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="bg">
+<translation id="1553734813273230889">Резолвер за WinHttp прокси сървъри</translation>
<translation id="8191453843330043793">Основано на V8 преобразуване на прокси сървъри</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_bn.xtb b/chromium/services/strings/services_strings_bn.xtb
index e46467aef57..ecf55dfdd60 100644
--- a/chromium/services/strings/services_strings_bn.xtb
+++ b/chromium/services/strings/services_strings_bn.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="bn">
+<translation id="1553734813273230889">WinHttp প্রক্সি রিসলভার</translation>
<translation id="8191453843330043793">V8 প্রক্সি সমাধানকারী</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_bs.xtb b/chromium/services/strings/services_strings_bs.xtb
index bb00ea28c55..94bda3929dd 100644
--- a/chromium/services/strings/services_strings_bs.xtb
+++ b/chromium/services/strings/services_strings_bs.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="bs">
+<translation id="1553734813273230889">Razrješivač proksi servera WinHttp</translation>
<translation id="8191453843330043793">Rezrješivač proksi servera V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ca.xtb b/chromium/services/strings/services_strings_ca.xtb
index c74aa85a038..fbf8de7759a 100644
--- a/chromium/services/strings/services_strings_ca.xtb
+++ b/chromium/services/strings/services_strings_ca.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ca">
+<translation id="1553734813273230889">Solucionador de servidors intermediaris WinHttp</translation>
<translation id="8191453843330043793">Solucionador de servidors intermediaris V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_cs.xtb b/chromium/services/strings/services_strings_cs.xtb
index 7041cd4d5b6..ffa44b6ea1b 100644
--- a/chromium/services/strings/services_strings_cs.xtb
+++ b/chromium/services/strings/services_strings_cs.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="cs">
+<translation id="1553734813273230889">Resolver proxy WinHttp</translation>
<translation id="8191453843330043793">Překladač proxy serverů V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_da.xtb b/chromium/services/strings/services_strings_da.xtb
index ec8a11e2c41..62c20f7e1ba 100644
--- a/chromium/services/strings/services_strings_da.xtb
+++ b/chromium/services/strings/services_strings_da.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="da">
+<translation id="1553734813273230889">WinHttp-proxyresolver</translation>
<translation id="8191453843330043793">V8-proxyresolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_de.xtb b/chromium/services/strings/services_strings_de.xtb
index 11fccdfb1a6..91bbf02b504 100644
--- a/chromium/services/strings/services_strings_de.xtb
+++ b/chromium/services/strings/services_strings_de.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="de">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8-Proxy-Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_el.xtb b/chromium/services/strings/services_strings_el.xtb
index 138637a63f3..076140fac86 100644
--- a/chromium/services/strings/services_strings_el.xtb
+++ b/chromium/services/strings/services_strings_el.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="el">
+<translation id="1553734813273230889">Εργαλείο επίλυσης διακομιστή διαμεσολάβησης WinHttp</translation>
<translation id="8191453843330043793">Εργαλείο επίλυσης διακομιστή μεσολάβησης V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_en-GB.xtb b/chromium/services/strings/services_strings_en-GB.xtb
index 9bfa86cf947..ff155905eaa 100644
--- a/chromium/services/strings/services_strings_en-GB.xtb
+++ b/chromium/services/strings/services_strings_en-GB.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="en-GB">
+<translation id="1553734813273230889">WinHttp proxy resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_es-419.xtb b/chromium/services/strings/services_strings_es-419.xtb
index 63ee441107c..21f57b9c18e 100644
--- a/chromium/services/strings/services_strings_es-419.xtb
+++ b/chromium/services/strings/services_strings_es-419.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="es-419">
+<translation id="1553734813273230889">Agente de resolución de proxy WinHttp</translation>
<translation id="8191453843330043793">Herramienta de resolución de proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_es.xtb b/chromium/services/strings/services_strings_es.xtb
index 49873de1f6d..20ac9d52420 100644
--- a/chromium/services/strings/services_strings_es.xtb
+++ b/chromium/services/strings/services_strings_es.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="es">
+<translation id="1553734813273230889">Solucionador de proxies WinHttp</translation>
<translation id="8191453843330043793">Solucionador de proxies V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_et.xtb b/chromium/services/strings/services_strings_et.xtb
index 78178cc984f..6e9d279080c 100644
--- a/chromium/services/strings/services_strings_et.xtb
+++ b/chromium/services/strings/services_strings_et.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="et">
+<translation id="1553734813273230889">WinHttp puhverserveri lahendaja</translation>
<translation id="8191453843330043793">V8 puhverserveri lahendaja</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_eu.xtb b/chromium/services/strings/services_strings_eu.xtb
index 818eea922d3..670ff2b8ad9 100644
--- a/chromium/services/strings/services_strings_eu.xtb
+++ b/chromium/services/strings/services_strings_eu.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="eu">
+<translation id="1553734813273230889">WinHttp proxy-ebazlea</translation>
<translation id="8191453843330043793">V8 proxy-ebazlea</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_fa.xtb b/chromium/services/strings/services_strings_fa.xtb
index 88d7f1041d3..d3518136372 100644
--- a/chromium/services/strings/services_strings_fa.xtb
+++ b/chromium/services/strings/services_strings_fa.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="fa">
+<translation id="1553734813273230889">‏رافع پراکسی WinHttp</translation>
<translation id="8191453843330043793">‏تحلیل‌گر پراکسی V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_fi.xtb b/chromium/services/strings/services_strings_fi.xtb
index 86468b8e158..58fa3b93d80 100644
--- a/chromium/services/strings/services_strings_fi.xtb
+++ b/chromium/services/strings/services_strings_fi.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="fi">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8-välityspalvelimen selvittäjä</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_fil.xtb b/chromium/services/strings/services_strings_fil.xtb
index a86ea8a8cb6..fd0fa39a8ed 100644
--- a/chromium/services/strings/services_strings_fil.xtb
+++ b/chromium/services/strings/services_strings_fil.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="fil">
+<translation id="1553734813273230889">Proxy Resolver ng WinHttp</translation>
<translation id="8191453843330043793">Panglutas ng Proxy ng V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_fr-CA.xtb b/chromium/services/strings/services_strings_fr-CA.xtb
index 73b10448236..8aa2eef7c75 100644
--- a/chromium/services/strings/services_strings_fr-CA.xtb
+++ b/chromium/services/strings/services_strings_fr-CA.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="fr-CA">
+<translation id="1553734813273230889">Résolveur du serveur mandataire WinHttp</translation>
<translation id="8191453843330043793">Résolveur du serveur mandataire V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_fr.xtb b/chromium/services/strings/services_strings_fr.xtb
index c6d54e0febd..ace48dc40cb 100644
--- a/chromium/services/strings/services_strings_fr.xtb
+++ b/chromium/services/strings/services_strings_fr.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="fr">
+<translation id="1553734813273230889">Résolution de proxy WinHttp</translation>
<translation id="8191453843330043793">Résolution de proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_gl.xtb b/chromium/services/strings/services_strings_gl.xtb
index 4ebedc874aa..aaa82c2f79b 100644
--- a/chromium/services/strings/services_strings_gl.xtb
+++ b/chromium/services/strings/services_strings_gl.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="gl">
+<translation id="1553734813273230889">Resolvedor de proxy WinHttp</translation>
<translation id="8191453843330043793">Resolvedor de proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_gu.xtb b/chromium/services/strings/services_strings_gu.xtb
index 2f25d520052..113955ebc10 100644
--- a/chromium/services/strings/services_strings_gu.xtb
+++ b/chromium/services/strings/services_strings_gu.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="gu">
+<translation id="1553734813273230889">WinHttp પ્રૉક્સી રિઝોલ્વર</translation>
<translation id="8191453843330043793">V8 પ્રૉક્સી રિઝોલ્વર</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_hi.xtb b/chromium/services/strings/services_strings_hi.xtb
index 2560f58e966..95e5f52b6f6 100644
--- a/chromium/services/strings/services_strings_hi.xtb
+++ b/chromium/services/strings/services_strings_hi.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="hi">
+<translation id="1553734813273230889">WinHttp प्रॉक्सी रिज़ॉल्वर</translation>
<translation id="8191453843330043793">V8 प्राॅक्‍सी रिज़ॉल्‍वर</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_hr.xtb b/chromium/services/strings/services_strings_hr.xtb
index 44b0bfe5786..2ead67e15f2 100644
--- a/chromium/services/strings/services_strings_hr.xtb
+++ b/chromium/services/strings/services_strings_hr.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="hr">
+<translation id="1553734813273230889">Razrješavanje WinHttp proxyja</translation>
<translation id="8191453843330043793">Razrješavanje V8 proxyja</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_hu.xtb b/chromium/services/strings/services_strings_hu.xtb
index 8ca85fba5c6..3a5b1e1bc07 100644
--- a/chromium/services/strings/services_strings_hu.xtb
+++ b/chromium/services/strings/services_strings_hu.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="hu">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_hy.xtb b/chromium/services/strings/services_strings_hy.xtb
index c31c9c7228b..5f3adb52094 100644
--- a/chromium/services/strings/services_strings_hy.xtb
+++ b/chromium/services/strings/services_strings_hy.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="hy">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 պրոքսիի կարգավորիչ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_id.xtb b/chromium/services/strings/services_strings_id.xtb
index 42fc81a7335..0a5eb1595e3 100644
--- a/chromium/services/strings/services_strings_id.xtb
+++ b/chromium/services/strings/services_strings_id.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="id">
+<translation id="1553734813273230889">Resolver Proxy WinHttp</translation>
<translation id="8191453843330043793">Pemecah Proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_is.xtb b/chromium/services/strings/services_strings_is.xtb
index a1f63d1ac86..517268fc688 100644
--- a/chromium/services/strings/services_strings_is.xtb
+++ b/chromium/services/strings/services_strings_is.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="is">
+<translation id="1553734813273230889">WinHttp-úrlausn staðgengilsþjóns</translation>
<translation id="8191453843330043793">V8 proxy-úrlausn</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_it.xtb b/chromium/services/strings/services_strings_it.xtb
index f410d4c430a..35bd1463fc2 100644
--- a/chromium/services/strings/services_strings_it.xtb
+++ b/chromium/services/strings/services_strings_it.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="it">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_iw.xtb b/chromium/services/strings/services_strings_iw.xtb
index 1815f0155db..58f38284d44 100644
--- a/chromium/services/strings/services_strings_iw.xtb
+++ b/chromium/services/strings/services_strings_iw.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="iw">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ja.xtb b/chromium/services/strings/services_strings_ja.xtb
index 84c0bd8444d..f972cd3b10f 100644
--- a/chromium/services/strings/services_strings_ja.xtb
+++ b/chromium/services/strings/services_strings_ja.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ja">
+<translation id="1553734813273230889">WinHttp プロキシ リゾルバ</translation>
<translation id="8191453843330043793">V8 プロキシ リゾルバ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ka.xtb b/chromium/services/strings/services_strings_ka.xtb
index 9b933fa3e13..af9fdb8d2fc 100644
--- a/chromium/services/strings/services_strings_ka.xtb
+++ b/chromium/services/strings/services_strings_ka.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ka">
+<translation id="1553734813273230889">WinHttp პროქსი-სერვერის მომგვარებელი</translation>
<translation id="8191453843330043793">V8 პროქსი-სერვერის მომგვარებელი</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_kk.xtb b/chromium/services/strings/services_strings_kk.xtb
index aa363fca784..93c2443f639 100644
--- a/chromium/services/strings/services_strings_kk.xtb
+++ b/chromium/services/strings/services_strings_kk.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="kk">
+<translation id="1553734813273230889">WinHttp прокси-серверін анықтау құралы</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_km.xtb b/chromium/services/strings/services_strings_km.xtb
index 4f5d133c7ff..f1b702cbb48 100644
--- a/chromium/services/strings/services_strings_km.xtb
+++ b/chromium/services/strings/services_strings_km.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="km">
+<translation id="1553734813273230889">កម្មវិធីបំប្លែងប្រូកស៊ី WinHttp</translation>
<translation id="8191453843330043793">កម្មវិធីដោះស្រាយប្រូកស៊ី V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_kn.xtb b/chromium/services/strings/services_strings_kn.xtb
index c93296cd559..d26f1f7f32f 100644
--- a/chromium/services/strings/services_strings_kn.xtb
+++ b/chromium/services/strings/services_strings_kn.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="kn">
+<translation id="1553734813273230889">WinHttp ಪ್ರಾಕ್ಸಿ ರೀಸಾಲ್ವರ್</translation>
<translation id="8191453843330043793">V8 ಪ್ರಾಕ್ಸಿ ಪರಿಹಾರಕ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ko.xtb b/chromium/services/strings/services_strings_ko.xtb
index 315eaaa259e..14834c227f7 100644
--- a/chromium/services/strings/services_strings_ko.xtb
+++ b/chromium/services/strings/services_strings_ko.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ko">
+<translation id="1553734813273230889">WinHttp 프록시 리졸버</translation>
<translation id="8191453843330043793">V8 프록시 리졸버</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ky.xtb b/chromium/services/strings/services_strings_ky.xtb
index 9a23128bf49..819217677aa 100644
--- a/chromium/services/strings/services_strings_ky.xtb
+++ b/chromium/services/strings/services_strings_ky.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ky">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Прокси сервери</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_lo.xtb b/chromium/services/strings/services_strings_lo.xtb
index 73983741131..25ef528985c 100644
--- a/chromium/services/strings/services_strings_lo.xtb
+++ b/chromium/services/strings/services_strings_lo.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="lo">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">ຕົວ​ແກ້​ໄຂພ​ຣັອກ​ຊີ V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_lt.xtb b/chromium/services/strings/services_strings_lt.xtb
index 155e23a27fe..6bdcb1d9b95 100644
--- a/chromium/services/strings/services_strings_lt.xtb
+++ b/chromium/services/strings/services_strings_lt.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="lt">
+<translation id="1553734813273230889">Tarpinio serverio vardų vertimo programa „WinHttp“</translation>
<translation id="8191453843330043793">V8 tarpinio serverio vardų vertimo programa</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_lv.xtb b/chromium/services/strings/services_strings_lv.xtb
index 8cf7b2597d1..b44d555fc64 100644
--- a/chromium/services/strings/services_strings_lv.xtb
+++ b/chromium/services/strings/services_strings_lv.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="lv">
+<translation id="1553734813273230889">WinHttp starpniekservera atrisinātājs</translation>
<translation id="8191453843330043793">V8 starpniekservera atrisinātājs</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_mk.xtb b/chromium/services/strings/services_strings_mk.xtb
index fa3e727f905..48db2d795ae 100644
--- a/chromium/services/strings/services_strings_mk.xtb
+++ b/chromium/services/strings/services_strings_mk.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="mk">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ml.xtb b/chromium/services/strings/services_strings_ml.xtb
index bbb843a270e..ef30e5c83df 100644
--- a/chromium/services/strings/services_strings_ml.xtb
+++ b/chromium/services/strings/services_strings_ml.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ml">
+<translation id="1553734813273230889">WinHttp പ്രോക്‌സി റിസോൾവർ</translation>
<translation id="8191453843330043793">V8 പ്രോക്‌സി റിസോൾവർ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_mn.xtb b/chromium/services/strings/services_strings_mn.xtb
index 3dc4e9fdf8a..1e41ebed751 100644
--- a/chromium/services/strings/services_strings_mn.xtb
+++ b/chromium/services/strings/services_strings_mn.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="mn">
+<translation id="1553734813273230889">WinHttp прокси тайлагч</translation>
<translation id="8191453843330043793">V8 Прокси Засварчлагч</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_mr.xtb b/chromium/services/strings/services_strings_mr.xtb
index 7b50d7ad005..e7e24b67957 100644
--- a/chromium/services/strings/services_strings_mr.xtb
+++ b/chromium/services/strings/services_strings_mr.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="mr">
+<translation id="1553734813273230889">WinHttp प्रॉक्सी निराकरणकर्ता</translation>
<translation id="8191453843330043793">V8 प्रॉक्सी निराकरणकर्ता</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ms.xtb b/chromium/services/strings/services_strings_ms.xtb
index b2e60fca149..c0ac163d4df 100644
--- a/chromium/services/strings/services_strings_ms.xtb
+++ b/chromium/services/strings/services_strings_ms.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ms">
+<translation id="1553734813273230889">Pelerai Proksi WinHttp</translation>
<translation id="8191453843330043793">Pelerai Proksi V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_my.xtb b/chromium/services/strings/services_strings_my.xtb
index d2d0e829887..2e237e178fb 100644
--- a/chromium/services/strings/services_strings_my.xtb
+++ b/chromium/services/strings/services_strings_my.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="my">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ne.xtb b/chromium/services/strings/services_strings_ne.xtb
index 4f27a256f35..ad5cb519b97 100644
--- a/chromium/services/strings/services_strings_ne.xtb
+++ b/chromium/services/strings/services_strings_ne.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ne">
+<translation id="1553734813273230889">WinHttp प्रोक्सी रिजल्भर</translation>
<translation id="8191453843330043793">V8 प्रोक्सी समाधान गर्ने</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_nl.xtb b/chromium/services/strings/services_strings_nl.xtb
index be565351e82..bafc80668f7 100644
--- a/chromium/services/strings/services_strings_nl.xtb
+++ b/chromium/services/strings/services_strings_nl.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="nl">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_no.xtb b/chromium/services/strings/services_strings_no.xtb
index 085094515fd..5bf58c262fd 100644
--- a/chromium/services/strings/services_strings_no.xtb
+++ b/chromium/services/strings/services_strings_no.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="no">
+<translation id="1553734813273230889">Resolver for WinHttp-proxy-tjener</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_or.xtb b/chromium/services/strings/services_strings_or.xtb
index 09da055faa3..8f903cc2887 100644
--- a/chromium/services/strings/services_strings_or.xtb
+++ b/chromium/services/strings/services_strings_or.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="or">
+<translation id="1553734813273230889">WinHttp ପ୍ରକ୍ସି ରିଜଲଭର</translation>
<translation id="8191453843330043793">V8 ପ୍ରୋକ୍ସି ରିଜଲ୍‌ଭର୍</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_pa.xtb b/chromium/services/strings/services_strings_pa.xtb
index c09f56e7242..2b87e117076 100644
--- a/chromium/services/strings/services_strings_pa.xtb
+++ b/chromium/services/strings/services_strings_pa.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="pa">
+<translation id="1553734813273230889">WinHttp ਪ੍ਰੌਕਸੀ ਰਿਜ਼ੌਲਵਰ</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_pl.xtb b/chromium/services/strings/services_strings_pl.xtb
index b5ce1d85a2f..7c2f40949a6 100644
--- a/chromium/services/strings/services_strings_pl.xtb
+++ b/chromium/services/strings/services_strings_pl.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="pl">
+<translation id="1553734813273230889">Program do rozpoznawania serwera proxy WinHttp</translation>
<translation id="8191453843330043793">Program do rozpoznawania serwera proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_pt-BR.xtb b/chromium/services/strings/services_strings_pt-BR.xtb
index 63b95e7b3bf..927b16d2801 100644
--- a/chromium/services/strings/services_strings_pt-BR.xtb
+++ b/chromium/services/strings/services_strings_pt-BR.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="pt-BR">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_pt-PT.xtb b/chromium/services/strings/services_strings_pt-PT.xtb
index 4ada91cc188..b5c0f303915 100644
--- a/chromium/services/strings/services_strings_pt-PT.xtb
+++ b/chromium/services/strings/services_strings_pt-PT.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="pt-PT">
+<translation id="1553734813273230889">Resolvedor de proxy WinHttp</translation>
<translation id="8191453843330043793">Resolução de proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ro.xtb b/chromium/services/strings/services_strings_ro.xtb
index 03131f9bb78..c7f61c0dc93 100644
--- a/chromium/services/strings/services_strings_ro.xtb
+++ b/chromium/services/strings/services_strings_ro.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ro">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">Rezolvitorul proxy-ului V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ru.xtb b/chromium/services/strings/services_strings_ru.xtb
index 8977adc1851..37bb30c2a79 100644
--- a/chromium/services/strings/services_strings_ru.xtb
+++ b/chromium/services/strings/services_strings_ru.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ru">
+<translation id="1553734813273230889">Прокси-сервер WinHTTP</translation>
<translation id="8191453843330043793">Прокси-сервер V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_si.xtb b/chromium/services/strings/services_strings_si.xtb
index d07bd0da453..b8be91e9117 100644
--- a/chromium/services/strings/services_strings_si.xtb
+++ b/chromium/services/strings/services_strings_si.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="si">
+<translation id="1553734813273230889">WinHttp ප්‍රොක්සි විසඳුම්කරු</translation>
<translation id="8191453843330043793">V8 ප්රොක්සි විසඳන්නා</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sk.xtb b/chromium/services/strings/services_strings_sk.xtb
index 1ab2c4512b9..0e127a3da0a 100644
--- a/chromium/services/strings/services_strings_sk.xtb
+++ b/chromium/services/strings/services_strings_sk.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sk">
+<translation id="1553734813273230889">Analyzátor proxy servera WinHttp</translation>
<translation id="8191453843330043793">V8 Proxy Resolver</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sl.xtb b/chromium/services/strings/services_strings_sl.xtb
index 683331fb7a4..9baf634b549 100644
--- a/chromium/services/strings/services_strings_sl.xtb
+++ b/chromium/services/strings/services_strings_sl.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sl">
+<translation id="1553734813273230889">Razreševalnik za proxy WinHttp</translation>
<translation id="8191453843330043793">Razreševalnik za proxy mehanizma V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sq.xtb b/chromium/services/strings/services_strings_sq.xtb
index 627bc5f8032..5400262067a 100644
--- a/chromium/services/strings/services_strings_sq.xtb
+++ b/chromium/services/strings/services_strings_sq.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sq">
+<translation id="1553734813273230889">Zgjidhësi i përfaqësuesit WinHttp</translation>
<translation id="8191453843330043793">Zgjidhësi i përfaqësuesit V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sr-Latn.xtb b/chromium/services/strings/services_strings_sr-Latn.xtb
index dd010d17f90..dfb2630a13a 100644
--- a/chromium/services/strings/services_strings_sr-Latn.xtb
+++ b/chromium/services/strings/services_strings_sr-Latn.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sr-Latn">
+<translation id="1553734813273230889">Razrešivač proksija WinHttp</translation>
<translation id="8191453843330043793">Razrešivač proksija V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sr.xtb b/chromium/services/strings/services_strings_sr.xtb
index 19779d18d53..3fb93f13d66 100644
--- a/chromium/services/strings/services_strings_sr.xtb
+++ b/chromium/services/strings/services_strings_sr.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sr">
+<translation id="1553734813273230889">Разрешивач проксија WinHttp</translation>
<translation id="8191453843330043793">Разрешивач проксија V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sv.xtb b/chromium/services/strings/services_strings_sv.xtb
index b046ca7eded..e8c52640ea3 100644
--- a/chromium/services/strings/services_strings_sv.xtb
+++ b/chromium/services/strings/services_strings_sv.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sv">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8-proxytolk</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_sw.xtb b/chromium/services/strings/services_strings_sw.xtb
index 92036ffcb5a..365b94b7281 100644
--- a/chromium/services/strings/services_strings_sw.xtb
+++ b/chromium/services/strings/services_strings_sw.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sw">
+<translation id="1553734813273230889">Kitatuzi cha Seva Mbadala ya WinHttp</translation>
<translation id="8191453843330043793">Kitatuaji cha Seva Mbadala ya V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ta.xtb b/chromium/services/strings/services_strings_ta.xtb
index 3ab227593db..dff672f1433 100644
--- a/chromium/services/strings/services_strings_ta.xtb
+++ b/chromium/services/strings/services_strings_ta.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ta">
+<translation id="1553734813273230889">WinHttp ப்ராக்ஸி ரிசால்வர்</translation>
<translation id="8191453843330043793">V8 புராக்ஸி ரிசால்வர்</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_te.xtb b/chromium/services/strings/services_strings_te.xtb
index 892eddf8f7c..220ba333f33 100644
--- a/chromium/services/strings/services_strings_te.xtb
+++ b/chromium/services/strings/services_strings_te.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="te">
+<translation id="1553734813273230889">WinHttp ప్రాక్సీ రిసాల్వర్</translation>
<translation id="8191453843330043793">V8 ప్రాక్సీ రిసాల్వర్</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_th.xtb b/chromium/services/strings/services_strings_th.xtb
index 8cd2340864e..dc09cac81f9 100644
--- a/chromium/services/strings/services_strings_th.xtb
+++ b/chromium/services/strings/services_strings_th.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="th">
+<translation id="1553734813273230889">ตัวแก้ไขพร็อกซี WinHttp</translation>
<translation id="8191453843330043793">ตัวแก้ไขพร็อกซี V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_tr.xtb b/chromium/services/strings/services_strings_tr.xtb
index 594c04435a2..b5f848b42f9 100644
--- a/chromium/services/strings/services_strings_tr.xtb
+++ b/chromium/services/strings/services_strings_tr.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="tr">
+<translation id="1553734813273230889">WinHttp Proxy Çözümleyici</translation>
<translation id="8191453843330043793">V8 Proxy Çözümleyici</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_uk.xtb b/chromium/services/strings/services_strings_uk.xtb
index a3ad6be8c98..27fdda14d07 100644
--- a/chromium/services/strings/services_strings_uk.xtb
+++ b/chromium/services/strings/services_strings_uk.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="uk">
+<translation id="1553734813273230889">Засіб розпізнавання проксі-сервера WinHttp</translation>
<translation id="8191453843330043793">Засіб розпізнавання проксі-сервера V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_ur.xtb b/chromium/services/strings/services_strings_ur.xtb
index 74d6876e8c7..6325563681f 100644
--- a/chromium/services/strings/services_strings_ur.xtb
+++ b/chromium/services/strings/services_strings_ur.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ur">
+<translation id="1553734813273230889">‏Win HTTP پراکسی حل کنندہ</translation>
<translation id="8191453843330043793">‏V8 پراکسی حل کنندہ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_uz.xtb b/chromium/services/strings/services_strings_uz.xtb
index 57282b3fa4c..df494bdefb9 100644
--- a/chromium/services/strings/services_strings_uz.xtb
+++ b/chromium/services/strings/services_strings_uz.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="uz">
+<translation id="1553734813273230889">WinHttp proksi qidirgich</translation>
<translation id="8191453843330043793">V8 proksi qidirgich</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_vi.xtb b/chromium/services/strings/services_strings_vi.xtb
index a2ad6bdd79f..1f5e38fc850 100644
--- a/chromium/services/strings/services_strings_vi.xtb
+++ b/chromium/services/strings/services_strings_vi.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="vi">
+<translation id="1553734813273230889">Trình phân giải proxy WinHttp</translation>
<translation id="8191453843330043793">Trình phân giải proxy V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_zh-CN.xtb b/chromium/services/strings/services_strings_zh-CN.xtb
index 14ffdc70259..9586d81351d 100644
--- a/chromium/services/strings/services_strings_zh-CN.xtb
+++ b/chromium/services/strings/services_strings_zh-CN.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zh-CN">
+<translation id="1553734813273230889">WinHttp Proxy Resolver</translation>
<translation id="8191453843330043793">V8 代理解析工具</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_zh-HK.xtb b/chromium/services/strings/services_strings_zh-HK.xtb
index 10d2d98cbec..0348152535e 100644
--- a/chromium/services/strings/services_strings_zh-HK.xtb
+++ b/chromium/services/strings/services_strings_zh-HK.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zh-HK">
+<translation id="1553734813273230889">WinHttp Proxy 解析器</translation>
<translation id="8191453843330043793">V8 Proxy 解析工具</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_zh-TW.xtb b/chromium/services/strings/services_strings_zh-TW.xtb
index 0834931d845..9056e2e00dd 100644
--- a/chromium/services/strings/services_strings_zh-TW.xtb
+++ b/chromium/services/strings/services_strings_zh-TW.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zh-TW">
+<translation id="1553734813273230889">WinHttp Proxy 解析器</translation>
<translation id="8191453843330043793">V8 Proxy 解析工具</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/strings/services_strings_zu.xtb b/chromium/services/strings/services_strings_zu.xtb
index c14454807af..cd0653ce6ff 100644
--- a/chromium/services/strings/services_strings_zu.xtb
+++ b/chromium/services/strings/services_strings_zu.xtb
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zu">
+<translation id="1553734813273230889">Isixazululi Sommeleli we-WinHttp</translation>
<translation id="8191453843330043793">Isixazululi sommeleli se-V8</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/services/tracing/BUILD.gn b/chromium/services/tracing/BUILD.gn
index 908db1ad7b6..2a5939ebc4b 100644
--- a/chromium/services/tracing/BUILD.gn
+++ b/chromium/services/tracing/BUILD.gn
@@ -118,6 +118,7 @@ source_set("tests") {
":test_utils",
"//base",
"//base/test:test_support",
+ "//build:chromeos_buildflags",
"//mojo/public/cpp/bindings",
"//services/tracing/public/cpp:buildflags",
"//services/tracing/public/cpp/background_tracing:unit_tests",
diff --git a/chromium/services/tracing/perfetto/consumer_host.cc b/chromium/services/tracing/perfetto/consumer_host.cc
index ce40eef9608..d20cb71f12b 100644
--- a/chromium/services/tracing/perfetto/consumer_host.cc
+++ b/chromium/services/tracing/perfetto/consumer_host.cc
@@ -137,13 +137,14 @@ class ConsumerHost::StreamWriter {
}
}
+ StreamWriter(const StreamWriter&) = delete;
+ StreamWriter& operator=(const StreamWriter&) = delete;
+
private:
mojo::ScopedDataPipeProducerHandle stream_;
TracingSession::ReadBuffersCallback read_buffers_callback_;
base::OnceClosure disconnect_callback_;
scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(StreamWriter);
};
ConsumerHost::TracingSession::TracingSession(
diff --git a/chromium/services/tracing/perfetto/consumer_host.h b/chromium/services/tracing/perfetto/consumer_host.h
index 3bfc532b756..2d4d0ef81a2 100644
--- a/chromium/services/tracing/perfetto/consumer_host.h
+++ b/chromium/services/tracing/perfetto/consumer_host.h
@@ -11,7 +11,7 @@
#include <vector>
#include "base/callback.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
@@ -95,7 +95,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
void MaybeSendEnableTracingAck();
bool IsExpectedPid(base::ProcessId pid) const;
- ConsumerHost* const host_;
+ const raw_ptr<ConsumerHost> host_;
mojo::Remote<mojom::TracingSessionClient> tracing_session_client_;
mojo::Receiver<mojom::TracingSessionHost> receiver_;
bool privacy_filtering_enabled_ = false;
@@ -130,6 +130,10 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
// The owner of ConsumerHost should make sure to destroy
// |service| after destroying this.
explicit ConsumerHost(PerfettoService* service);
+
+ ConsumerHost(const ConsumerHost&) = delete;
+ ConsumerHost& operator=(const ConsumerHost&) = delete;
+
~ConsumerHost() override;
PerfettoService* service() const { return service_; }
@@ -166,7 +170,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
private:
void DestructTracingSession();
- PerfettoService* const service_;
+ const raw_ptr<PerfettoService> service_;
std::unique_ptr<TracingSession> tracing_session_;
SEQUENCE_CHECKER(sequence_checker_);
@@ -176,7 +180,6 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
consumer_endpoint_;
base::WeakPtrFactory<ConsumerHost> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(ConsumerHost);
};
} // namespace tracing
diff --git a/chromium/services/tracing/perfetto/consumer_host_unittest.cc b/chromium/services/tracing/perfetto/consumer_host_unittest.cc
index 480c22ad6d8..ca1b966df34 100644
--- a/chromium/services/tracing/perfetto/consumer_host_unittest.cc
+++ b/chromium/services/tracing/perfetto/consumer_host_unittest.cc
@@ -12,10 +12,10 @@
#include "base/callback_helpers.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -302,7 +302,8 @@ class TracingConsumerTest : public testing::Test,
public mojo::DataPipeDrainer::Client {
public:
void SetUp() override {
- PerfettoTracedProcess::ResetTaskRunnerForTesting();
+ task_environment_ = std::make_unique<base::test::TaskEnvironment>();
+ test_handle_ = tracing::PerfettoTracedProcess::SetupForTesting();
PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
threaded_service_ = std::make_unique<ThreadedPerfettoService>();
@@ -310,7 +311,12 @@ class TracingConsumerTest : public testing::Test,
total_bytes_received_ = 0;
}
- void TearDown() override { threaded_service_.reset(); }
+ void TearDown() override {
+ threaded_service_.reset();
+ task_environment_->RunUntilIdle();
+ test_handle_.reset();
+ task_environment_.reset();
+ }
// mojo::DataPipeDrainer::Client
void OnDataAvailable(const void* data, size_t num_bytes) override {
@@ -420,7 +426,7 @@ class TracingConsumerTest : public testing::Test,
bool IsTracingEnabled() {
// Flush any other pending tasks on the perfetto task runner to ensure that
// any pending data source start callbacks have propagated.
- task_environment_.RunUntilIdle();
+ task_environment_->RunUntilIdle();
return threaded_service_->IsTracingEnabled();
}
@@ -433,7 +439,8 @@ class TracingConsumerTest : public testing::Test,
private:
std::unique_ptr<ThreadedPerfettoService> threaded_service_;
- base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<base::test::TaskEnvironment> task_environment_;
+ std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_;
base::OnceClosure on_data_complete_;
std::unique_ptr<mojo::DataPipeDrainer> drainer_;
std::vector<uint8_t> received_data_;
diff --git a/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc b/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc
index f3538d9eab9..aa0b348e453 100644
--- a/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc
+++ b/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc
@@ -385,12 +385,9 @@ TEST_F(PerfettoIntegrationTest, PerfettoPlatformTest) {
}
TEST_F(PerfettoIntegrationTest, PerfettoClientLibraryTest) {
- // 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);
+ // Check that PerfettoTracedProcess initialized the client library. Functional
+ // client library tests are in TracingServiceTest.
+ EXPECT_TRUE(perfetto::Tracing::IsInitialized());
}
} // namespace
diff --git a/chromium/services/tracing/perfetto/perfetto_service.h b/chromium/services/tracing/perfetto/perfetto_service.h
index 635776b9ffc..765bd233819 100644
--- a/chromium/services/tracing/perfetto/perfetto_service.h
+++ b/chromium/services/tracing/perfetto/perfetto_service.h
@@ -9,7 +9,6 @@
#include <memory>
#include <set>
-#include "base/macros.h"
#include "base/tracing/perfetto_task_runner.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
diff --git a/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h b/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h
index d0559b49e59..01853ce5bef 100644
--- a/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h
+++ b/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h
@@ -182,7 +182,7 @@ constexpr MessageInfo kChromeApplicationStateInfo = {
kChromeApplicationStateInfoIndices, nullptr};
// Proto Message: ChromeRendererSchedulerState
-constexpr int kChromeRendererSchedulerStateIndices[] = {1, -1};
+constexpr int kChromeRendererSchedulerStateIndices[] = {1, 2, 3, -1};
constexpr MessageInfo kChromeRendererSchedulerState = {
kChromeRendererSchedulerStateIndices, nullptr};
@@ -308,13 +308,23 @@ constexpr int kParkableStringUnparkIndices[] = {1, 2, -1};
constexpr MessageInfo kParkableStringUnpark = {kParkableStringUnparkIndices,
nullptr};
+// Proto Message: ChromeSamplingProfilerSampleCollected
+constexpr int kChromeSamplingProfilerSampleCollectedIndices[] = {1, 2, 3, -1};
+constexpr MessageInfo kChromeSamplingProfilerSampleCollected = {
+ kChromeSamplingProfilerSampleCollectedIndices, nullptr};
+
+// Proto Message: RendererMainThreadTaskExecution
+constexpr int kRendererMainThreadTaskExecutionIndices[] = {1, 2, 3, 4, -1};
+constexpr MessageInfo kRendererMainThreadTaskExecution = {
+ kRendererMainThreadTaskExecutionIndices, nullptr};
+
// Proto Message: TrackEvent
constexpr int kTrackEventIndices[] = {
1, 2, 3, 5, 6, 9, 10, 11, 12, 16, 17, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 38, 39, 40, 41, 42, 43, 1001, 1002, 1003, 1004,
1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016,
- 1017, 1018, 1019, 1020, 1021, 1023, 1024, -1};
+ 1017, 1018, 1019, 1020, 1021, 1023, 1024, 1025, 1031, -1};
constexpr MessageInfo const* kTrackEventComplexMessages[] = {
nullptr,
nullptr,
@@ -370,7 +380,9 @@ constexpr MessageInfo const* kTrackEventComplexMessages[] = {
&kRenderViewHost,
&kRenderFrameProxyHost,
&kParkableStringCompressInBackground,
- &kParkableStringUnpark};
+ &kParkableStringUnpark,
+ &kChromeSamplingProfilerSampleCollected,
+ &kRendererMainThreadTaskExecution};
constexpr MessageInfo kTrackEvent = {kTrackEventIndices,
kTrackEventComplexMessages};
diff --git a/chromium/services/tracing/perfetto/privacy_filtering_check.h b/chromium/services/tracing/perfetto/privacy_filtering_check.h
index 1409ff38f54..b30a5728217 100644
--- a/chromium/services/tracing/perfetto/privacy_filtering_check.h
+++ b/chromium/services/tracing/perfetto/privacy_filtering_check.h
@@ -7,8 +7,6 @@
#include <string>
-#include "base/macros.h"
-
namespace tracing {
class PrivacyFilteringCheck {
diff --git a/chromium/services/tracing/perfetto/producer_host.h b/chromium/services/tracing/perfetto/producer_host.h
index 3a31e16e4d8..939147818ce 100644
--- a/chromium/services/tracing/perfetto/producer_host.h
+++ b/chromium/services/tracing/perfetto/producer_host.h
@@ -10,7 +10,7 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/producer.h"
@@ -110,7 +110,7 @@ class ProducerHost : public tracing::mojom::ProducerHost,
private:
mojo::Remote<mojom::ProducerClient> producer_client_;
- base::tracing::PerfettoTaskRunner* task_runner_;
+ raw_ptr<base::tracing::PerfettoTaskRunner> task_runner_;
protected:
// Perfetto guarantees that no OnXX callbacks are invoked on |this|
diff --git a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
index 7fc2cedf8cf..661931c1a79 100644
--- a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
+++ b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/process/launch.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
@@ -20,6 +21,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/trace_event/trace_config.h"
#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
#include "services/tracing/perfetto/perfetto_service.h"
#include "services/tracing/perfetto/producer_host.h"
#include "services/tracing/perfetto/system_test_utils.h"
@@ -76,14 +78,12 @@ class ClearAndRestoreSystemProducerScope {
~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_loop.Quit();
- }));
+ FROM_HERE, base::BindLambdaForTesting([this, &destroy_loop]() {
+ PerfettoTracedProcess::Get()
+ ->SetSystemProducerForTesting(std::move(saved_producer_))
+ .reset();
+ destroy_loop.Quit();
+ }));
destroy_loop.Run();
}
@@ -242,7 +242,13 @@ class SystemPerfettoTest : public TracingUnitTest {
const char* old_tmp_dir_ = nullptr;
};
-TEST_F(SystemPerfettoTest, SystemTraceEndToEnd) {
+#if defined(OS_ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
+#define MAYBE_SystemTraceEndToEnd DISABLED_SystemTraceEndToEnd
+#else
+#define MAYBE_SystemTraceEndToEnd SystemTraceEndToEnd
+#endif
+TEST_F(SystemPerfettoTest, MAYBE_SystemTraceEndToEnd) {
auto system_service = CreateMockSystemService();
// Set up the producer to talk to the system.
@@ -282,7 +288,15 @@ TEST_F(SystemPerfettoTest, SystemTraceEndToEnd) {
PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
}
-TEST_F(SystemPerfettoTest, OneSystemSourceWithMultipleLocalSources) {
+#if defined(OS_ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
+#define MAYBE_OneSystemSourceWithMultipleLocalSources \
+ DISABLED_OneSystemSourceWithMultipleLocalSources
+#else
+#define MAYBE_OneSystemSourceWithMultipleLocalSources \
+ OneSystemSourceWithMultipleLocalSources
+#endif
+TEST_F(SystemPerfettoTest, MAYBE_OneSystemSourceWithMultipleLocalSources) {
auto system_service = CreateMockSystemService();
// Start a trace using the system Perfetto service.
@@ -379,7 +393,16 @@ TEST_F(SystemPerfettoTest, OneSystemSourceWithMultipleLocalSources) {
PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
}
-TEST_F(SystemPerfettoTest, MultipleSystemSourceWithOneLocalSourcesLocalFirst) {
+#if defined(OS_ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
+#define MAYBE_MultipleSystemSourceWithOneLocalSourcesLocalFirst \
+ DISABLED_MultipleSystemSourceWithOneLocalSourcesLocalFirst
+#else
+#define MAYBE_MultipleSystemSourceWithOneLocalSourcesLocalFirst \
+ MultipleSystemSourceWithOneLocalSourcesLocalFirst
+#endif
+TEST_F(SystemPerfettoTest,
+ MAYBE_MultipleSystemSourceWithOneLocalSourcesLocalFirst) {
auto system_service = CreateMockSystemService();
base::RunLoop local_no_more_packets_runloop;
@@ -495,7 +518,14 @@ TEST_F(SystemPerfettoTest, MultipleSystemSourceWithOneLocalSourcesLocalFirst) {
PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
}
-TEST_F(SystemPerfettoTest, MultipleSystemAndLocalSources) {
+#if defined(OS_ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
+#define MAYBE_MultipleSystemAndLocalSources \
+ DISABLED_MultipleSystemAndLocalSources
+#else
+#define MAYBE_MultipleSystemAndLocalSources MultipleSystemAndLocalSources
+#endif
+TEST_F(SystemPerfettoTest, MAYBE_MultipleSystemAndLocalSources) {
auto system_service = CreateMockSystemService();
// Start a trace using the system Perfetto service.
@@ -604,7 +634,15 @@ TEST_F(SystemPerfettoTest, MultipleSystemAndLocalSources) {
PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
}
-TEST_F(SystemPerfettoTest, MultipleSystemAndLocalSourcesLocalFirst) {
+#if defined(OS_ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
+#define MAYBE_MultipleSystemAndLocalSourcesLocalFirst \
+ DISABLED_MultipleSystemAndLocalSourcesLocalFirst
+#else
+#define MAYBE_MultipleSystemAndLocalSourcesLocalFirst \
+ MultipleSystemAndLocalSourcesLocalFirst
+#endif
+TEST_F(SystemPerfettoTest, MAYBE_MultipleSystemAndLocalSourcesLocalFirst) {
auto system_service = CreateMockSystemService();
// We construct it up front so it connects to the service before the local
@@ -709,9 +747,17 @@ TEST_F(SystemPerfettoTest, MultipleSystemAndLocalSourcesLocalFirst) {
PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
}
+#if defined(OS_CHROMEOS)
+// Flaky on all CrOS platforms: crbug.com/1262132#c18
+#define MAYBE_SystemTraceWhileLocalStartupTracing \
+ DISABLED_SystemTraceWhileLocalStartupTracing
+#else
+#define MAYBE_SystemTraceWhileLocalStartupTracing \
+ SystemTraceWhileLocalStartupTracing
+#endif
// Attempts to start a system trace while a local startup trace is active. The
// system trace should only be started after the local trace is completed.
-TEST_F(SystemPerfettoTest, SystemTraceWhileLocalStartupTracing) {
+TEST_F(SystemPerfettoTest, MAYBE_SystemTraceWhileLocalStartupTracing) {
// We're using mojom::kTraceEventDataSourceName for the local producer to
// emulate starting the real TraceEventDataSource which owns startup tracing.
auto mock_trace_event_ds = TestDataSource::CreateAndRegisterDataSource(
@@ -765,8 +811,8 @@ TEST_F(SystemPerfettoTest, SystemTraceWhileLocalStartupTracing) {
}
}));
auto local_producer_host = std::make_unique<MockProducerHost>(
- GetPerfettoProducerName(), mojom::kTraceEventDataSourceName, local_service(),
- **local_producer);
+ GetPerfettoProducerName(), mojom::kTraceEventDataSourceName,
+ local_service(), **local_producer);
local_data_source_enabled_runloop.Run();
local_consumer->WaitForAllDataSourcesStarted();
@@ -813,7 +859,8 @@ TEST_F(SystemPerfettoTest, SystemTraceWhileLocalStartupTracing) {
}
#if defined(OS_ANDROID)
-TEST_F(SystemPerfettoTest, SystemToLowAPILevel) {
+// Failing on android-pie-arm64-dbg, see crbug.com/1262132.
+TEST_F(SystemPerfettoTest, DISABLED_SystemToLowAPILevel) {
if (base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_P) {
LOG(INFO) << "Skipping SystemToLowAPILevel test, this phone supports the "
@@ -887,7 +934,8 @@ TEST_F(SystemPerfettoTest, SystemToLowAPILevel) {
EXPECT_EQ(0u, run_test(/* check_sdk_level = */ true));
}
-TEST_F(SystemPerfettoTest, EnabledOnDebugBuilds) {
+// Flaky on Android: crbug.com/1262132#c17
+TEST_F(SystemPerfettoTest, DISABLED_EnabledOnDebugBuilds) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing);
if (base::android::BuildInfo::GetInstance()->is_debug_android()) {
@@ -898,7 +946,13 @@ TEST_F(SystemPerfettoTest, EnabledOnDebugBuilds) {
}
#endif // defined(OS_ANDROID)
-TEST_F(SystemPerfettoTest, RespectsFeatureList) {
+#if defined(OS_ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
+#define MAYBE_RespectsFeatureList DISABLED_RespectsFeatureList
+#else
+#define MAYBE_RespectsFeatureList RespectsFeatureList
+#endif
+TEST_F(SystemPerfettoTest, MAYBE_RespectsFeatureList) {
#if defined(OS_ANDROID)
if (base::android::BuildInfo::GetInstance()->is_debug_android()) {
// The feature list is ignored on debug android builds so we should have a
@@ -920,7 +974,8 @@ TEST_F(SystemPerfettoTest, RespectsFeatureList) {
}
#if defined(OS_ANDROID)
-TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
+// Flaky on Android: crbug.com/1262132#c17
+TEST_F(SystemPerfettoTest, DISABLED_RespectsFeaturePreAndroidPie) {
if (base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_P) {
return;
@@ -997,7 +1052,7 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
}
#endif // defined(OS_ANDROID)
-TEST_F(SystemPerfettoTest, EnablePerfettoSystemTracingDefaultState) {
+TEST_F(SystemPerfettoTest, DISABLED_EnablePerfettoSystemTracingDefaultState) {
#if defined(OS_CHROMEOS)
EXPECT_EQ(features::kEnablePerfettoSystemTracing.default_state,
base::FEATURE_ENABLED_BY_DEFAULT);
@@ -1007,8 +1062,8 @@ TEST_F(SystemPerfettoTest, EnablePerfettoSystemTracingDefaultState) {
#endif
}
-// Failing on Android, see https://crbug.com/1254159.
#if defined(ANDROID)
+// Flaky on Android: crbug.com/1262132#c17
#define MAYBE_SetupSystemTracing DISABLED_SetupSystemTracing
#else
#define MAYBE_SetupSystemTracing SetupSystemTracing
diff --git a/chromium/services/tracing/perfetto/test_utils.cc b/chromium/services/tracing/perfetto/test_utils.cc
index b3fc2bd8d5d..a221737ea10 100644
--- a/chromium/services/tracing/perfetto/test_utils.cc
+++ b/chromium/services/tracing/perfetto/test_utils.cc
@@ -441,9 +441,10 @@ void TracingUnitTest::SetUp() {
setup_called_ = true;
// Also tell PerfettoTracedProcess to use the current task environment.
- PerfettoTracedProcess::ResetTaskRunnerForTesting(
+ test_handle_ = PerfettoTracedProcess::SetupForTesting(
base::ThreadTaskRunnerHandle::Get());
- PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
+ PerfettoTracedProcess::Get()->OnThreadPoolAvailable(
+ /* enable_consumer */ true);
// Wait for any posted construction tasks to execute.
RunUntilIdle();
@@ -463,6 +464,7 @@ void TracingUnitTest::TearDown() {
PerfettoTracedProcess::Get()->GetTaskRunner()->ResetTaskRunnerForTesting(
nullptr);
PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
+ test_handle_.reset();
}
} // namespace tracing
diff --git a/chromium/services/tracing/perfetto/test_utils.h b/chromium/services/tracing/perfetto/test_utils.h
index dcb48ac317b..1fcae50ec13 100644
--- a/chromium/services/tracing/perfetto/test_utils.h
+++ b/chromium/services/tracing/perfetto/test_utils.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/memory/raw_ptr.h"
#include "base/test/task_environment.h"
#include "base/test/trace_test_utils.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -57,7 +58,7 @@ class TestDataSource : public PerfettoTracedProcess::DataSourceBase {
TestDataSource(const std::string& data_source_name, size_t send_packet_count);
size_t send_packet_count_;
- tracing::PerfettoProducer* producer_ = nullptr;
+ raw_ptr<tracing::PerfettoProducer> producer_ = nullptr;
perfetto::DataSourceConfig config_;
base::OnceClosure start_tracing_callback_ = base::OnceClosure();
};
@@ -75,7 +76,7 @@ class MockProducerClient : public ProducerClient {
MockProducerClient* operator*() { return client_; }
private:
- MockProducerClient* const client_;
+ const raw_ptr<MockProducerClient> client_;
};
~MockProducerClient() override;
@@ -170,8 +171,8 @@ class MockConsumer : public perfetto::Consumer {
size_t received_test_packets_ = 0;
PacketReceivedCallback packet_received_callback_;
std::vector<DataSourceStatus> data_sources_;
- base::RunLoop* on_started_runloop_ = nullptr;
- base::RunLoop* on_stopped_runloop_ = nullptr;
+ raw_ptr<base::RunLoop> on_started_runloop_ = nullptr;
+ raw_ptr<base::RunLoop> on_stopped_runloop_ = nullptr;
perfetto::TraceConfig trace_config_;
};
@@ -241,6 +242,7 @@ class TracingUnitTest : public testing::Test {
private:
std::unique_ptr<base::test::TaskEnvironment> task_environment_;
std::unique_ptr<base::test::TracingEnvironment> tracing_environment_;
+ std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_;
bool setup_called_ = false;
bool teardown_called_ = false;
};
diff --git a/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h b/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h
index a23c0eb6ec9..09b0d2f484e 100644
--- a/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h
+++ b/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/time/time.h"
diff --git a/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc b/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc
index e9cdaee32b1..97218bf009c 100644
--- a/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc
+++ b/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc
@@ -4,6 +4,7 @@
#include "services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/task/thread_pool.h"
@@ -78,7 +79,7 @@ class BackgroundTracingAgentImplTest : public testing::Test {
provider_set_;
mojo::UniqueReceiverSet<tracing::mojom::BackgroundTracingAgentClient>
client_set_;
- BackgroundTracingAgentClientRecorder* recorder_ = nullptr;
+ raw_ptr<BackgroundTracingAgentClientRecorder> recorder_ = nullptr;
};
TEST_F(BackgroundTracingAgentImplTest, TestInitialize) {
diff --git a/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_provider_impl.h b/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_provider_impl.h
index c646b498818..d88a0ad47db 100644
--- a/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_provider_impl.h
+++ b/chromium/services/tracing/public/cpp/background_tracing/background_tracing_agent_provider_impl.h
@@ -6,7 +6,6 @@
#define SERVICES_TRACING_PUBLIC_CPP_BACKGROUND_TRACING_BACKGROUND_TRACING_AGENT_PROVIDER_IMPL_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "services/tracing/public/mojom/background_tracing_agent.mojom.h"
diff --git a/chromium/services/tracing/public/cpp/base_agent.h b/chromium/services/tracing/public/cpp/base_agent.h
index 1e31926c644..c5e161c08e4 100644
--- a/chromium/services/tracing/public/cpp/base_agent.h
+++ b/chromium/services/tracing/public/cpp/base_agent.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
namespace tracing {
diff --git a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.h b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.h
index 6c22e251a03..eb8a5b28e46 100644
--- a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.h
+++ b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.h
@@ -6,7 +6,6 @@
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_JAVA_HEAP_PROFILER_HPROF_BUFFER_ANDROID_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_data_type_android.h"
namespace tracing {
diff --git a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.cc b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.cc
index 856954afd6a..aa0e6634576 100644
--- a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.cc
@@ -24,12 +24,12 @@ Instance::Instance(const Instance& other) = default;
Instance::~Instance() = default;
-void Instance::AddReferenceFrom(const std::string& name, uint64_t object_id) {
- referred_by.push_back({name, object_id});
+void Instance::AddReferenceFrom(const std::string& name, uint64_t obj_id) {
+ referred_by.push_back({name, obj_id});
}
-void Instance::AddReferenceTo(const std::string& name, uint64_t object_id) {
- referred_to.push_back({name, object_id});
+void Instance::AddReferenceTo(const std::string& name, uint64_t obj_id) {
+ referred_to.push_back({name, obj_id});
}
ClassInstance::ClassInstance(uint64_t object_id,
diff --git a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.h b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.h
index 246e1e50d4a..d829157277a 100644
--- a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.h
+++ b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_instances_android.h
@@ -31,8 +31,8 @@ struct COMPONENT_EXPORT(TRACING_CPP) Instance {
Instance(const Instance& other);
~Instance();
- void AddReferenceFrom(const std::string& name, uint64_t object_id);
- void AddReferenceTo(const std::string& name, uint64_t object_id);
+ void AddReferenceFrom(const std::string& name, uint64_t obj_id);
+ void AddReferenceTo(const std::string& name, uint64_t obj_id);
// Only set in first pass for ClassObject and PrimitiveArrayInstances.
std::string type_name;
diff --git a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_parser_android.cc b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_parser_android.cc
index 4c6307799e2..d251211af45 100644
--- a/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_parser_android.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_parser_android.cc
@@ -132,7 +132,6 @@ HprofParser::ParseResult HprofParser::ParseClassObjectDumpSubtag() {
uint32_t type_index = hprof_buffer_->GetOneByte();
DataType type = GetTypeFromIndex(type_index);
- ObjectId object_id;
if (type == DataType::OBJECT) {
object_id = hprof_buffer_->GetId();
} else {
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h
index eef0abcb338..4497ad20559 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/basic_types.h"
@@ -156,7 +157,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoProducer {
// subprocess to start tracing after it connects).
base::TimeDelta startup_tracing_timeout_ = base::Seconds(60);
- base::tracing::PerfettoTaskRunner* const task_runner_;
+ const raw_ptr<base::tracing::PerfettoTaskRunner> task_runner_;
std::atomic<bool> startup_tracing_active_{false};
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h
index bf3f924b917..5c940d1b29e 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h
@@ -10,7 +10,7 @@
#include "base/callback_forward.h"
#include "base/component_export.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
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 62a09c810ab..e72bcee90ea 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
@@ -8,8 +8,8 @@
#include "base/command_line.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/trace_event/trace_config.h"
#include "base/trace_event/trace_log.h"
#include "base/tracing/perfetto_platform.h"
@@ -63,6 +63,13 @@ const char* MaybeSocket() {
return nullptr;
#endif // defined(OS_POSIX)
}
+
+void OnPerfettoLogMessage(perfetto::base::LogMessageCallbackArgs args) {
+ // Perfetto levels start at 0, base's at -1.
+ int severity = static_cast<int>(args.level) - 1;
+ ::logging::LogMessage(args.filename, args.line, severity).stream()
+ << args.message;
+}
} // namespace
PerfettoTracedProcess::DataSourceBase::DataSourceBase(const std::string& name)
@@ -186,42 +193,59 @@ PerfettoTracedProcess::SetSystemProducerForTesting(
return old_for_testing;
}
-// static
-void PerfettoTracedProcess::DeleteSoonForTesting(
- std::unique_ptr<PerfettoTracedProcess> perfetto_traced_process) {
- GetTaskRunner()->GetOrCreateTaskRunner()->DeleteSoon(
- 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);
+ // This is called on Perfetto's internal TracingMuxerImpl thread, so we need
+ // to hop over to the tracing sequence.
+ GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](base::OnceCallback<void(
+ mojo::PendingRemote<mojom::PerfettoService>)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(
+ PerfettoTracedProcess::Get()->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_);
+ PerfettoTracedProcess::Get()->pending_producer_callback_ =
+ std::move(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(
+ // This is called on Perfetto's internal TracingMuxerImpl thread, so we need
+ // to hop over to the tracing sequence.
+ GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
- [](ConsumerConnectionFactory factory,
- base::OnceCallback<void(mojo::PendingRemote<mojom::ConsumerHost>)>
+ [](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));
+ auto* self = PerfettoTracedProcess::Get();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_);
+ self->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));
+ },
+ self->consumer_connection_factory_, std::move(callback)));
},
- consumer_connection_factory_, std::move(callback)));
+ std::move(callback)));
}
// We never destroy the taskrunner as we may need it for cleanup
@@ -235,16 +259,24 @@ base::tracing::PerfettoTaskRunner* PerfettoTracedProcess::GetTaskRunner() {
}
// static
-void PerfettoTracedProcess::ResetTaskRunnerForTesting(
+std::unique_ptr<PerfettoTracedProcess::TestHandle>
+PerfettoTracedProcess::SetupForTesting(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ // Make sure Perfetto was properly torn down in any prior tests.
+ DCHECK(!perfetto::Tracing::IsInitialized());
GetTaskRunner()->ResetTaskRunnerForTesting(task_runner);
+ Get()->ClearDataSourcesForTesting(); // IN-TEST
// On the first call within the process's lifetime, this will call
// PerfettoTracedProcess::Get(), ensuring PerfettoTracedProcess is created.
- InitTracingPostThreadPoolStartAndFeatureList();
+ InitTracingPostThreadPoolStartAndFeatureList(
+ /* enable_consumer */ true);
// Disassociate the PerfettoTracedProcess from any prior task runner.
DETACH_FROM_SEQUENCE(PerfettoTracedProcess::Get()->sequence_checker_);
PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
FROM_HERE, base::BindOnce([]() {
+ // Lock the sequence checker onto the new task runner.
+ DCHECK_CALLED_ON_VALID_SEQUENCE(
+ PerfettoTracedProcess::Get()->sequence_checker_);
PerfettoTracedProcess::Get()
->producer_client()
->ResetSequenceForTesting();
@@ -254,6 +286,7 @@ void PerfettoTracedProcess::ResetTaskRunnerForTesting(
->ResetSequenceForTesting();
}
}));
+ return std::make_unique<TestHandle>();
}
void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) {
@@ -306,7 +339,7 @@ bool PerfettoTracedProcess::SetupStartupTracing(
return true;
}
-void PerfettoTracedProcess::SetupClientLibrary() {
+void PerfettoTracedProcess::SetupClientLibrary(bool enable_consumer) {
perfetto::TracingInitArgs init_args;
init_args.platform = platform_.get();
init_args.custom_backend = tracing_backend_.get();
@@ -314,16 +347,25 @@ void PerfettoTracedProcess::SetupClientLibrary() {
// TODO(eseckler): Not yet supported on Android to avoid binary size regression
// of the consumer IPC messages. We'll need a way to exclude them.
#if defined(OS_POSIX) && !defined(OS_ANDROID)
- if (ShouldSetupSystemTracing()) {
+ // We currently only use the client library system backend for the consumer
+ // side, which is only allowed in the browser process. Furthermore, on
+ // non-Android platforms, sandboxed processes need to delegate the socket
+ // connections to the browser, but this delegation hasn't been hooked up in
+ // the client library yet.
+ if (ShouldSetupSystemTracing() && enable_consumer) {
init_args.backends |= perfetto::kSystemBackend;
init_args.tracing_policy = this;
}
#endif
+ // Proxy perfetto log messages into Chrome logs, so they are retained on all
+ // platforms. In particular, on Windows, Perfetto's stderr log messages are
+ // not reliabe.
+ init_args.log_message_callback = &OnPerfettoLogMessage;
perfetto::Tracing::Initialize(init_args);
}
-void PerfettoTracedProcess::OnThreadPoolAvailable() {
- SetupClientLibrary();
+void PerfettoTracedProcess::OnThreadPoolAvailable(bool enable_consumer) {
+ SetupClientLibrary(enable_consumer);
// Create our task runner now, so that ProducerClient/SystemProducer are
// notified about future data source registrations and schedule any necessary
@@ -478,4 +520,10 @@ SystemProducer* PerfettoTracedProcess::system_producer() const {
return system_producer_.get();
}
+PerfettoTracedProcess::TestHandle::~TestHandle() {
+ // TODO(skyostil): We only uninitialize Perfetto for now, but there may also
+ // be other tracing-related state which should not leak between tests.
+ perfetto::Tracing::ResetForTesting();
+}
+
} // namespace tracing
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 f855e2ecdd2..04688e44b87 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
@@ -6,10 +6,11 @@
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_TRACED_PROCESS_H_
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "base/trace_event/trace_event.h"
#include "base/tracing/perfetto_task_runner.h"
@@ -121,7 +122,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
private:
uint64_t data_source_id_ = 0;
std::string name_;
- PerfettoProducer* producer_ = nullptr;
+ raw_ptr<PerfettoProducer> producer_ = nullptr;
};
#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
@@ -166,6 +167,9 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
// Returns the process-wide instance of the PerfettoTracedProcess.
static PerfettoTracedProcess* Get();
+ PerfettoTracedProcess(const PerfettoTracedProcess&) = delete;
+ PerfettoTracedProcess& operator=(const PerfettoTracedProcess&) = delete;
+
// 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& (*)();
@@ -203,7 +207,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
bool privacy_filtering_enabled);
// Called on the process's main thread once the thread pool is ready.
- void OnThreadPoolAvailable();
+ void OnThreadPoolAvailable(bool enable_consumer);
// Set a callback that returns whether a system tracing session is allowed.
// The callback will be executed on the sequence that set it. Only a single
@@ -235,10 +239,22 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
// Can be called on any thread, but only after OnThreadPoolAvailable().
void ActivateSystemTriggers(const std::vector<std::string>& triggers);
- // Be careful when using ResetTaskRunnerForTesting. There is a PostTask in the
+ // Sets the task runner used by the tracing infrastructure in this process.
+ // The returned handle will automatically tear down tracing when destroyed, so
+ // it should be kept valid until the test terminates.
+ //
+ // Be careful when using SetupForTesting. There is a PostTask in the
// constructor of PerfettoTracedProcess, so before this class is constructed
// is the only safe time to call this.
- static void ResetTaskRunnerForTesting(
+ struct COMPONENT_EXPORT(TRACING_CPP) TestHandle {
+ TestHandle() = default;
+ ~TestHandle();
+ TestHandle(const TestHandle&) = delete;
+ TestHandle(TestHandle&&) = default;
+ TestHandle& operator=(const TestHandle&) = delete;
+ TestHandle& operator=(TestHandle&&) = default;
+ };
+ static std::unique_ptr<TestHandle> SetupForTesting(
scoped_refptr<base::SequencedTaskRunner> task_runner = nullptr);
// Sets the ProducerClient (or SystemProducer) and returns the old pointer. If
@@ -250,7 +266,6 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
std::unique_ptr<SystemProducer> producer);
void ClearDataSourcesForTesting();
- static void DeleteSoonForTesting(std::unique_ptr<PerfettoTracedProcess>);
base::tracing::PerfettoPlatform* perfetto_platform_for_testing() const {
return platform_.get();
@@ -273,7 +288,9 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
// Initialize the Perfetto client library (i.e., perfetto::Tracing) for this
// process.
- void SetupClientLibrary();
+ // |enable_consumer| should be true if the system consumer can be enabled.
+ // Currently this is only the case if this is running in the browser process.
+ void SetupClientLibrary(bool enable_consumer);
// perfetto::TracingPolicy implementation:
void ShouldAllowConsumerSession(
@@ -315,7 +332,6 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
pending_producer_callback_;
SEQUENCE_CHECKER(sequence_checker_);
- DISALLOW_COPY_AND_ASSIGN(PerfettoTracedProcess);
};
#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc
index 6996509c9e0..3328c0f5a47 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc
@@ -6,6 +6,7 @@
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/post_task.h"
#include "base/tracing/tracing_tls.h"
@@ -82,12 +83,19 @@ class ProducerEndpoint : public perfetto::ProducerEndpoint,
producer_host_->RegisterDataSource(descriptor);
}
- void UnregisterDataSource(const std::string& name) override {
+ void UpdateDataSource(
+ const perfetto::DataSourceDescriptor& descriptor) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // TODO(skyostil): Implement data source unregistering.
NOTREACHED();
}
+ void UnregisterDataSource(const std::string& name) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement data source unregistering. Data sources are
+ // currently only unregistered in tests, and because the tracing service is
+ // also torn down at the same time, we can ignore unregistrations here.
+ }
+
void RegisterTraceWriter(uint32_t writer_id,
uint32_t target_buffer) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -320,7 +328,7 @@ class ProducerEndpoint : public perfetto::ProducerEndpoint,
SEQUENCE_CHECKER(sequence_checker_);
- perfetto::Producer* const producer_;
+ const raw_ptr<perfetto::Producer> producer_;
base::flat_map<perfetto::DataSourceInstanceID, StartDataSourceCallback>
ds_start_callbacks_;
@@ -638,7 +646,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint,
}
SEQUENCE_CHECKER(sequence_checker_);
- perfetto::Consumer* const consumer_;
+ const raw_ptr<perfetto::Consumer> consumer_;
mojo::Remote<tracing::mojom::ConsumerHost> consumer_host_;
mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_;
mojo::Receiver<tracing::mojom::TracingSessionClient> tracing_session_client_{
diff --git a/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.h b/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.h
index abb2ea5c25f..ff5aa4e52f0 100644
--- a/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.h
+++ b/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.h
@@ -13,7 +13,6 @@
#include "base/atomicops.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_client.cc b/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
index 1cdc17d55db..838ec119b75 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -337,6 +337,10 @@ void ProducerClient::RegisterDataSource(const perfetto::DataSourceDescriptor&) {
NOTREACHED();
}
+void ProducerClient::UpdateDataSource(const perfetto::DataSourceDescriptor&) {
+ NOTREACHED();
+}
+
void ProducerClient::UnregisterDataSource(const std::string& name) {
NOTREACHED();
}
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_client.h b/chromium/services/tracing/public/cpp/perfetto/producer_client.h
index 32e8b51366d..d8be9edad33 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_client.h
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_client.h
@@ -14,7 +14,7 @@
#include "base/atomicops.h"
#include "base/callback_forward.h"
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
@@ -100,6 +100,7 @@ class COMPONENT_EXPORT(TRACING_CPP) ProducerClient
perfetto::SharedMemory* shared_memory() const override;
void NotifyFlushComplete(perfetto::FlushRequestID) override;
void RegisterDataSource(const perfetto::DataSourceDescriptor&) override;
+ void UpdateDataSource(const perfetto::DataSourceDescriptor&) override;
void UnregisterDataSource(const std::string& name) override;
void NotifyDataSourceStopped(perfetto::DataSourceInstanceID) override;
void NotifyDataSourceStarted(perfetto::DataSourceInstanceID) override;
@@ -133,7 +134,8 @@ class COMPONENT_EXPORT(TRACING_CPP) ProducerClient
uint32_t data_sources_tracing_ = 0;
std::unique_ptr<mojo::Receiver<mojom::ProducerClient>> receiver_;
mojo::Remote<mojom::ProducerHost> producer_host_;
- base::tracing::PerfettoTaskRunner* in_process_arbiter_task_runner_ = nullptr;
+ raw_ptr<base::tracing::PerfettoTaskRunner> in_process_arbiter_task_runner_ =
+ nullptr;
// First value is the flush ID, the second is the number of
// replies we're still waiting for.
std::pair<uint64_t, size_t> pending_replies_for_latest_flush_;
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 776ad78bcbe..fa4e09ff2b3 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc
@@ -170,7 +170,6 @@ DataSourceTester::DataSourceTester(
{
features_.InitAndDisableFeature(features::kEnablePerfettoSystemTracing);
#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
- tracing::PerfettoTracedProcess::ResetTaskRunnerForTesting();
auto perfetto_wrapper = std::make_unique<base::tracing::PerfettoTaskRunner>(
base::ThreadTaskRunnerHandle::Get());
@@ -179,11 +178,7 @@ DataSourceTester::DataSourceTester(
#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
}
-DataSourceTester::~DataSourceTester() {
-#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
- tracing::PerfettoTracedProcess::ResetTaskRunnerForTesting();
-#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
-}
+DataSourceTester::~DataSourceTester() = default;
void DataSourceTester::BeginTrace(
const base::trace_event::TraceConfig& trace_config) {
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 702e1a3029b..78a2eb72a75 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/test/scoped_feature_list.h"
#include "base/tracing/perfetto_task_runner.h"
@@ -99,7 +100,7 @@ class TestTraceWriter : public perfetto::TraceWriter {
TestTraceWriter& operator=(TestTraceWriter&&) = delete;
private:
- TestProducerClient* producer_client_;
+ raw_ptr<TestProducerClient> producer_client_;
};
// Wrapper class around TestProducerClient useful for testing a trace data
@@ -141,7 +142,7 @@ class DataSourceTester {
finalized_packets_;
#else // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
std::unique_ptr<tracing::TestProducerClient> producer_;
- tracing::PerfettoTracedProcess::DataSourceBase* data_source_;
+ raw_ptr<tracing::PerfettoTracedProcess::DataSourceBase> data_source_;
#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
};
diff --git a/chromium/services/tracing/public/cpp/perfetto/shared_memory.h b/chromium/services/tracing/public/cpp/perfetto/shared_memory.h
index 6c2e4496b2c..0aaec650cce 100644
--- a/chromium/services/tracing/public/cpp/perfetto/shared_memory.h
+++ b/chromium/services/tracing/public/cpp/perfetto/shared_memory.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/component_export.h"
-#include "base/macros.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory.h"
diff --git a/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h b/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h
index 1f877b9145c..e3835f3a1bd 100644
--- a/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h
+++ b/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -51,6 +50,9 @@ class COMPONENT_EXPORT(TRACING_CPP) SystemTraceWriter {
trace_type_(trace_type),
task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+ SystemTraceWriter(const SystemTraceWriter&) = delete;
+ SystemTraceWriter& operator=(const SystemTraceWriter&) = delete;
+
void WriteData(const StringType& data) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
buffered_data_.push_back(data);
@@ -146,8 +148,6 @@ class COMPONENT_EXPORT(TRACING_CPP) SystemTraceWriter {
base::OnceClosure on_flush_complete_callback_;
base::WeakPtrFactory<SystemTraceWriter> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(SystemTraceWriter);
};
} // namespace tracing
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 e4a822b7982..1425a758014 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
@@ -734,7 +734,7 @@ void TraceEventDataSource::OnStopTracingDone() {
}
// static
-TrackEventThreadLocalEventSink* TraceEventDataSource::GetOrPrepareEventSink() {
+TrackEventThreadLocalEventSink* TraceEventDataSource::GetOrPrepareEventSink(bool create_if_needed) {
// Avoid re-entrancy, which can happen during PostTasks (the taskqueue can
// emit trace events). We discard the events in this case, as any PostTasking
// to deal with these events later would break the event ordering that the
@@ -768,10 +768,11 @@ TrackEventThreadLocalEventSink* TraceEventDataSource::GetOrPrepareEventSink() {
if (new_session_flags.session_id != thread_local_event_sink->session_id()) {
delete thread_local_event_sink;
thread_local_event_sink = nullptr;
+ ThreadLocalEventSinkSlot()->Set(nullptr);
}
}
- if (!thread_local_event_sink) {
+ if (!thread_local_event_sink && create_if_needed) {
thread_local_event_sink = GetInstance()->CreateThreadLocalEventSink();
ThreadLocalEventSinkSlot()->Set(thread_local_event_sink);
}
@@ -819,14 +820,13 @@ void TraceEventDataSource::SetupStartupTracing(
config_for_trace_log.SetTraceBufferSizeInKb(0);
config_for_trace_log.SetTraceBufferSizeInEvents(0);
+ RegisterWithTraceLog(config_for_trace_log);
+
+#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
uint8_t modes = base::trace_event::TraceLog::RECORDING_MODE;
if (!trace_config.event_filters().empty()) {
modes |= base::trace_event::TraceLog::FILTERING_MODE;
}
-
- RegisterWithTraceLog(config_for_trace_log);
-
-#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
base::trace_event::TraceLog::GetInstance()->SetEnabled(trace_config, modes);
#endif
}
@@ -1213,6 +1213,7 @@ void TraceEventDataSource::Flush(
void TraceEventDataSource::ClearIncrementalState() {
TrackEventThreadLocalEventSink::ClearIncrementalState();
EmitTrackDescriptor();
+ base::trace_event::TraceLog::GetInstance()->OnIncrementalStateCleared();
}
std::unique_ptr<perfetto::TraceWriter>
@@ -1313,7 +1314,7 @@ base::trace_event::TracePacketHandle TraceEventDataSource::OnAddTracePacket() {
// static
void TraceEventDataSource::OnAddEmptyPacket() {
- auto* thread_local_event_sink = GetOrPrepareEventSink();
+ auto* thread_local_event_sink = GetOrPrepareEventSink(false);
if (thread_local_event_sink) {
// GetThreadIsInTraceEventTLS() is handled by the sink for trace packets.
thread_local_event_sink->AddEmptyPacket();
@@ -1489,8 +1490,11 @@ void TraceEventDataSource::EmitTrackDescriptor() {
process->set_pid(process_id);
process->set_start_timestamp_ns(
process_creation_time_ticks_.since_origin().InNanoseconds());
- if (!privacy_filtering_enabled && !process_name.empty()) {
+ if (!privacy_filtering_enabled) {
process->set_process_name(process_name);
+ for (const auto& label : TraceLog::GetInstance()->process_labels()) {
+ process->add_process_labels(label.second);
+ }
}
ChromeProcessDescriptor* chrome_process =
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 e03731095d6..4c4a6806f3f 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
@@ -11,7 +11,7 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/statistics_recorder.h"
@@ -56,6 +56,9 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventMetadataSource
public:
static TraceEventMetadataSource* GetInstance();
+ TraceEventMetadataSource(const TraceEventMetadataSource&) = delete;
+ TraceEventMetadataSource& operator=(const TraceEventMetadataSource&) = delete;
+
using JsonMetadataGeneratorFunction =
base::RepeatingCallback<absl::optional<base::Value>()>;
@@ -141,8 +144,6 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventMetadataSource
std::unique_ptr<base::trace_event::TraceConfig> parsed_chrome_config_
GUARDED_BY(lock_);
bool emit_metadata_at_start_ GUARDED_BY(lock_) = false;
-
- DISALLOW_COPY_AND_ASSIGN(TraceEventMetadataSource);
};
// This class acts as a bridge between the TraceLog and
@@ -167,6 +168,9 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource :
static TraceEventDataSource* GetInstance();
+ TraceEventDataSource(const TraceEventDataSource&) = delete;
+ TraceEventDataSource& operator=(const TraceEventDataSource&) = delete;
+
// Destroys and recreates the global instance for testing.
static void ResetForTesting();
@@ -232,7 +236,8 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource :
std::unique_ptr<perfetto::TraceWriter> CreateTraceWriterLocked();
TrackEventThreadLocalEventSink* CreateThreadLocalEventSink();
- static TrackEventThreadLocalEventSink* GetOrPrepareEventSink();
+ // Returns the event sink for the current thread, creates it if none unless |!create_if_needed|.
+ static TrackEventThreadLocalEventSink* GetOrPrepareEventSink(bool create_if_needed = true);
// Callback from TraceLog / typed macros, can be called from any thread.
static void OnAddLegacyTraceEvent(
@@ -282,7 +287,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource :
// base::AutoLock to protect code paths which may post tasks.
// TODO(eseckler): Use GUARDED_BY annotations on all fields below.
base::Lock lock_; // Protects subsequent members.
- PerfettoProducer* producer_ GUARDED_BY(lock_) = nullptr;
+ raw_ptr<PerfettoProducer> producer_ GUARDED_BY(lock_) = nullptr;
uint32_t target_buffer_ = 0;
std::unique_ptr<perfetto::TraceWriter> trace_writer_;
bool is_enabled_ = false;
@@ -304,8 +309,6 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource :
int process_id_ = base::kNullProcessId;
base::ActionCallback user_action_callback_ =
base::BindRepeating(&TraceEventDataSource::OnUserActionSampleCallback);
-
- DISALLOW_COPY_AND_ASSIGN(TraceEventDataSource);
};
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
index 859fb423919..c421ace0d5c 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -14,11 +14,13 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/json/json_reader.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/metrics_hashes.h"
#include "base/metrics/user_metrics.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/common/task_annotator.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -1281,7 +1283,7 @@ TEST_F(TraceEventDataSourceTest, EventWithConvertableArgs) {
}
private:
- int* num_calls_;
+ raw_ptr<int> num_calls_;
const char* arg_value_;
};
@@ -1309,11 +1311,16 @@ TEST_F(TraceEventDataSourceTest, EventWithConvertableArgs) {
TEST_F(TraceEventDataSourceTest, TaskExecutionEvent) {
StartTraceEventDataSource(/*privacy_filtering_enabled=*/false, "toplevel");
- base::PendingTask task;
- task.posted_from =
- base::Location("my_func", "my_file", 0, /*program_counter=*/&task);
- { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask1", task); }
- { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask1", task); }
+ base::TaskAnnotator task_annotator;
+ for (int i = 0; i < 2; ++i) {
+ base::PendingTask task;
+ task.task = base::DoNothing();
+ task.posted_from =
+ base::Location("my_func", "my_file", 0, /*program_counter=*/&task);
+ // TaskAnnotator::RunTask is responsible for emitting the task execution
+ // event.
+ task_annotator.RunTask("ThreadControllerImpl::RunTask1", task);
+ }
size_t packet_index = ExpectStandardPreamble();
size_t category_iid = 1;
@@ -1367,10 +1374,15 @@ TEST_F(TraceEventDataSourceTest, TaskExecutionEvent) {
TEST_F(TraceEventDataSourceTest, TaskExecutionEventWithoutFunction) {
StartTraceEventDataSource(/*privacy_filtering_enabled=*/false, "toplevel");
+ base::TaskAnnotator task_annotator;
base::PendingTask task;
+ task.task = base::DoNothing();
task.posted_from = base::Location(/*function_name=*/nullptr, "my_file", 0,
/*program_counter=*/&task);
- { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask1", task); }
+
+ // TaskAnnotator::RunTask is responsible for emitting the task execution
+ // event.
+ task_annotator.RunTask("ThreadControllerImpl::RunTask1", task);
size_t packet_index = ExpectStandardPreamble();
size_t category_iid = 1;
@@ -2007,8 +2019,6 @@ TEST_F(TraceEventDataSourceNoInterningTest, MAYBE_InterningScopedToPackets) {
#define MAYBE_StartupTracingTimeout StartupTracingTimeout
#endif
TEST_F(TraceEventDataSourceTest, MAYBE_StartupTracingTimeout) {
- PerfettoTracedProcess::ResetTaskRunnerForTesting(
- base::SequencedTaskRunnerHandle::Get());
constexpr char kStartupTestEvent1[] = "startup_registry";
auto* data_source = TraceEventDataSource::GetInstance();
PerfettoTracedProcess::Get()->AddDataSource(data_source);
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc
index 25f13212b05..77542ed72d4 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc
@@ -6,7 +6,6 @@
#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 {
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_string_lookup.cc b/chromium/services/tracing/public/cpp/perfetto/trace_string_lookup.cc
index 610172c890a..5a869918263 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_string_lookup.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_string_lookup.cc
@@ -20,6 +20,7 @@ struct ProcessType {
constexpr ProcessType kProcessTypes[] = {
{"Browser", ChromeProcessDescriptor::PROCESS_BROWSER},
{"Renderer", ChromeProcessDescriptor::PROCESS_RENDERER},
+ {"Extension Renderer", ChromeProcessDescriptor::PROCESS_RENDERER_EXTENSION},
{"GPU Process", ChromeProcessDescriptor::PROCESS_GPU},
{"HeadlessBrowser", ChromeProcessDescriptor::PROCESS_BROWSER},
{"PPAPI Process", ChromeProcessDescriptor::PROCESS_PPAPI_PLUGIN},
@@ -147,6 +148,7 @@ constexpr ThreadType kThreadTypes[] = {
{"NetworkConfigWatcher",
ChromeThreadDescriptor::THREAD_NETWORKCONFIGWATCHER},
{"wasapi_render_thread", ChromeThreadDescriptor::THREAD_WASAPI_RENDER},
+ {"LoaderLockSampler", ChromeThreadDescriptor::THREAD_LOADER_LOCK_SAMPLER},
};
ChromeProcessDescriptor::ProcessType GetProcessType(const std::string& name) {
diff --git a/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h b/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
index 03634a931e9..6615705c33e 100644
--- a/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
+++ b/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
@@ -6,6 +6,7 @@
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACED_VALUE_PROTO_WRITER_H_
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "base/trace_event/trace_event_impl.h"
#include "third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h"
@@ -32,7 +33,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoProtoAppender
private:
std::vector<protozero::ContiguousMemoryRange> ranges_;
- perfetto::protos::pbzero::DebugAnnotation* annotation_proto_;
+ raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
};
void COMPONENT_EXPORT(TRACING_CPP) RegisterTracedValueProtoWriter();
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 301d52abb72..8506f6f30d0 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
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include "base/memory/raw_ptr.h"
#include "base/trace_event/traced_value.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h"
@@ -65,7 +66,7 @@ class ProtoInputStream : public google::protobuf::io::ZeroCopyInputStream {
}
private:
- const protozero::ScatteredHeapBuffer* buffer_;
+ raw_ptr<const protozero::ScatteredHeapBuffer> buffer_;
size_t slices_read_ = 0;
bool has_backed_up_ = false;
};
diff --git a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
index ea0dbcff101..21170f4e382 100644
--- a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
@@ -147,6 +147,9 @@ class LazyLegacyEventInitializer {
}
private:
+ // `track_event_` and `legacy_event_` are not a raw_ptr<...> for performance
+ // reasons (based on analysis of sampling profiler data and
+ // tab_search:top100:2020).
TrackEvent* track_event_;
TrackEvent::LegacyEvent* legacy_event_ = nullptr;
};
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.cc b/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.cc
index da304826958..cdb97ae917b 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.cc
+++ b/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.cc
@@ -6,7 +6,7 @@
#include "base/check.h"
#include "base/no_destructor.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc
index 7f82abd5c5f..dddee2b7e26 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
@@ -40,8 +40,7 @@ double BusyLoopFor(base::TimeDelta duration) {
class ReachedCodeDataSourceTest : public testing::Test {
public:
void SetUp() override {
- PerfettoTracedProcess::ResetTaskRunnerForTesting();
- PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner();
+ test_handle_ = tracing::PerfettoTracedProcess::SetupForTesting();
auto perfetto_wrapper = std::make_unique<base::tracing::PerfettoTaskRunner>(
task_environment_.GetMainThreadTaskRunner());
@@ -70,7 +69,7 @@ class ReachedCodeDataSourceTest : public testing::Test {
private:
base::test::TaskEnvironment task_environment_;
-
+ std::unique_ptr<tracing::PerfettoTracedProcess::TestHandle> test_handle_;
std::unique_ptr<TestProducerClient> producer_;
};
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h b/chromium/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h
index f0bf9eb3d74..02b10262588 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h
+++ b/chromium/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_STACK_SAMPLER_ANDROID_H_
#define SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_STACK_SAMPLER_ANDROID_H_
+#include "base/memory/raw_ptr.h"
#include "base/profiler/module_cache.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/stack_sampler.h"
@@ -34,7 +35,7 @@ class StackSamplerAndroid : public base::StackSampler {
private:
base::SamplingProfilerThreadToken thread_token_;
- base::ModuleCache* module_cache_;
+ raw_ptr<base::ModuleCache> module_cache_;
StackUnwinderAndroid unwinder_;
};
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc b/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc
index c89ac2b0feb..606753c1cbc 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc
+++ b/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc
@@ -11,6 +11,7 @@
#include <syscall.h>
#include <unistd.h>
#include "base/containers/cxx20_erase.h"
+#include "base/memory/raw_ptr.h"
#include "link.h"
#include <algorithm>
@@ -83,7 +84,7 @@ class ScopedEventSignaller {
~ScopedEventSignaller() { event_->Signal(); }
private:
- AsyncSafeWaitableEvent* event_;
+ raw_ptr<AsyncSafeWaitableEvent> event_;
};
// Helper class to unwind stack. See Unwind() method for details.
@@ -230,7 +231,7 @@ class UnwindHelper {
}
// If false then only chrome unwinder and stack scanning are used to unwind.
- CFIBacktraceAndroid* cfi_unwinder_; // not const because of cache
+ raw_ptr<CFIBacktraceAndroid> cfi_unwinder_; // not const because of cache
// Set to the stack pointer of the copied stack in case of unwinding other
// thread. Otherwise stack pointer of the unwind method.
@@ -251,7 +252,7 @@ class UnwindHelper {
std::vector<const tracing::StackUnwinderAndroid::JniMarker*> jni_markers_;
// Output stack trace and depth:
- const void** out_trace_;
+ raw_ptr<const void*> out_trace_;
size_t depth_ = 0;
};
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android.cc b/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android.cc
index 56088c5ea4d..7ff291c09bf 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android.cc
+++ b/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android.cc
@@ -30,7 +30,7 @@ base::UnwindResult UnwinderArm64::TryUnwind(
uintptr_t pc = reinterpret_cast<uintptr_t>(out_trace[i]);
stack->push_back(base::Frame(pc, module_cache()->GetModuleForAddress(pc)));
}
- return base::UnwindResult::COMPLETED;
+ return base::UnwindResult::kCompleted;
}
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc b/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc
index f5d1925bba8..7183ba62315 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc
+++ b/chromium/services/tracing/public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc
@@ -46,7 +46,7 @@ TEST(UnwinderArm64Test, UnwindValidStack) {
UnwinderArm64 unwinder;
unwinder.Initialize(&module_cache);
std::vector<base::Frame> stack;
- EXPECT_EQ(base::UnwindResult::COMPLETED,
+ EXPECT_EQ(base::UnwindResult::kCompleted,
unwinder.TryUnwind(&register_context, stack_top, &stack));
ASSERT_EQ(kMaxFrameCount, stack.size());
@@ -73,7 +73,7 @@ TEST(UnwinderArm64Test, UnwindInvalidFirstFrame) {
UnwinderArm64 unwinder;
unwinder.Initialize(&module_cache);
std::vector<base::Frame> stack;
- EXPECT_EQ(base::UnwindResult::COMPLETED,
+ EXPECT_EQ(base::UnwindResult::kCompleted,
unwinder.TryUnwind(&register_context, stack_top, &stack));
// One extra frame is added when scanning starts.
@@ -104,7 +104,7 @@ TEST(UnwinderArm64Test, UnwindInvalidFp) {
UnwinderArm64 unwinder;
unwinder.Initialize(&module_cache);
std::vector<base::Frame> stack;
- EXPECT_EQ(base::UnwindResult::COMPLETED,
+ EXPECT_EQ(base::UnwindResult::kCompleted,
unwinder.TryUnwind(&register_context, stack_top, &stack));
// One extra frame is added when scanning starts.
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 3bac04e85d7..95af89f61c1 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
@@ -14,6 +14,7 @@
#include "base/debug/stack_trace.h"
#include "base/hash/hash.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
@@ -206,7 +207,7 @@ class TracingSamplerProfilerDataSource
private:
// TODO(eseckler): Use GUARDED_BY annotations for all members below.
base::Lock lock_; // Protects subsequent members.
- tracing::PerfettoProducer* producer_ GUARDED_BY(lock_) = nullptr;
+ raw_ptr<tracing::PerfettoProducer> producer_ GUARDED_BY(lock_) = nullptr;
std::set<TracingSamplerProfiler*> profilers_;
bool is_startup_tracing_ = false;
bool is_started_ = false;
@@ -371,45 +372,23 @@ TracingSamplerProfiler::TracingProfileBuilder::GetModuleCache() {
using SampleDebugProto =
perfetto::protos::pbzero::ChromeSamplingProfilerSampleCollected;
-void RecordSampleCompletedEvent(size_t frame_count,
- SampleDebugProto::WriteStatus write_status) {
- TRACE_EVENT_INSTANT(
- TRACE_DISABLED_BY_DEFAULT("cpu_profiler"),
- "TracingProfileBuilder::OnSampleCompleted",
- [&](perfetto::EventContext ctx) {
- auto* sample_event =
- ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>()
- ->set_chrome_sampling_profiler_sample_completed();
- sample_event->set_frame_count(frame_count);
- sample_event->set_write_status(write_status);
- });
-}
-
void TracingSamplerProfiler::TracingProfileBuilder::OnSampleCompleted(
std::vector<base::Frame> frames,
base::TimeTicks sample_timestamp) {
- const size_t frame_size = frames.size();
base::AutoLock l(trace_writer_lock_);
if (!trace_writer_) {
if (buffered_samples_.size() < kMaxBufferedSamples) {
buffered_samples_.emplace_back(
BufferedSample(sample_timestamp, std::move(frames)));
}
- RecordSampleCompletedEvent(frame_size,
- SampleDebugProto::WRITE_STATUS_BUFFERING_SAMPLE);
return;
}
if (!buffered_samples_.empty()) {
for (const auto& sample : buffered_samples_) {
- RecordSampleCompletedEvent(
- frame_size, SampleDebugProto::WRITE_STATUS_WRITING_BUFFERED);
WriteSampleToTrace(sample);
}
buffered_samples_.clear();
}
- // TODO(b/201276114): Remove this event once the bug is fixed.
- RecordSampleCompletedEvent(frame_size,
- SampleDebugProto::WRITE_STATUS_WRITING_TO_TRACE);
WriteSampleToTrace(BufferedSample(sample_timestamp, std::move(frames)));
if (sample_callback_for_testing_) {
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 921120cd538..7b6fbd76244 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
@@ -13,7 +13,7 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/debug/debugging_buildflags.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/stack_sampling_profiler.h"
@@ -113,20 +113,32 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
private:
struct BufferedSample {
BufferedSample(base::TimeTicks, std::vector<base::Frame>&&);
+
+ BufferedSample(const BufferedSample&) = delete;
+ BufferedSample& operator=(const BufferedSample&) = delete;
+
BufferedSample(BufferedSample&& other);
+
~BufferedSample();
base::TimeTicks timestamp;
std::vector<base::Frame> sample;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedSample);
};
void WriteSampleToTrace(const BufferedSample& sample);
+ // TODO(ssid): Consider using an interning scheme to reduce memory usage
+ // and increase the sample size.
+#if defined(OS_ANDROID) || defined(OS_IOS)
// We usually sample at 50ms, and expect that tracing should have started in
- // 10s.
+ // 10s (5s for 2 threads). Approximately 100 frames and 200 samples would use
+ // 300KiB.
constexpr static size_t kMaxBufferedSamples = 200;
+#else
+ // 2000 samples are enough to store samples for 100 seconds (50s for 2
+ // threads), and consumes about 3MiB of memory.
+ constexpr static size_t kMaxBufferedSamples = 2000;
+#endif
std::vector<BufferedSample> buffered_samples_;
base::ModuleCache module_cache_;
@@ -144,6 +156,9 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
// destroyed prior to process shutdown.
static std::unique_ptr<TracingSamplerProfiler> CreateOnMainThread();
+ TracingSamplerProfiler(const TracingSamplerProfiler&) = delete;
+ TracingSamplerProfiler& operator=(const TracingSamplerProfiler&) = delete;
+
// Sets up tracing sampling profiler on a child thread. The profiler will be
// stored in SequencedLocalStorageSlot and will be destroyed with the thread
// task runner.
@@ -204,7 +219,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
base::Lock lock_;
std::unique_ptr<base::StackSamplingProfiler> profiler_; // under |lock_|
- TracingProfileBuilder* profile_builder_ = nullptr;
+ raw_ptr<TracingProfileBuilder> profile_builder_ = nullptr;
base::RepeatingClosure sample_callback_for_testing_;
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
@@ -212,8 +227,6 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
// and stop at the same time that stack sampling does.
std::unique_ptr<LoaderLockSamplingThread> loader_lock_sampling_thread_;
#endif
-
- DISALLOW_COPY_AND_ASSIGN(TracingSamplerProfiler);
};
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/system_tracing_service_unittest.cc b/chromium/services/tracing/public/cpp/system_tracing_service_unittest.cc
index 7124dee969b..ebf46222ea1 100644
--- a/chromium/services/tracing/public/cpp/system_tracing_service_unittest.cc
+++ b/chromium/services/tracing/public/cpp/system_tracing_service_unittest.cc
@@ -40,7 +40,7 @@ class SystemTracingServiceTest : public testing::Test {
system_service_->producer().c_str(), 1));
// Use the current thread as the Perfetto task runner.
- tracing::PerfettoTracedProcess::ResetTaskRunnerForTesting(
+ test_handle_ = tracing::PerfettoTracedProcess::SetupForTesting(
base::ThreadTaskRunnerHandle::Get());
}
@@ -52,12 +52,14 @@ class SystemTracingServiceTest : public testing::Test {
} else {
ASSERT_EQ(0, unsetenv(kProducerSockEnvName));
}
+ task_environment_.RunUntilIdle();
}
protected:
base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<MockSystemService> system_service_;
+ std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_;
const char* saved_producer_sock_env_ = nullptr;
};
diff --git a/chromium/services/tracing/public/cpp/trace_event_agent.h b/chromium/services/tracing/public/cpp/trace_event_agent.h
index 3875fc4610c..b505185d7ed 100644
--- a/chromium/services/tracing/public/cpp/trace_event_agent.h
+++ b/chromium/services/tracing/public/cpp/trace_event_agent.h
@@ -26,6 +26,9 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventAgent : public BaseAgent {
public:
static TraceEventAgent* GetInstance();
+ TraceEventAgent(const TraceEventAgent&) = delete;
+ TraceEventAgent& operator=(const TraceEventAgent&) = delete;
+
void GetCategories(std::set<std::string>* category_set) override;
using MetadataGeneratorFunction =
@@ -44,7 +47,6 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventAgent : public BaseAgent {
std::vector<MetadataGeneratorFunction> metadata_generator_functions_;
THREAD_CHECKER(thread_checker_);
- DISALLOW_COPY_AND_ASSIGN(TraceEventAgent);
};
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/trace_startup.cc b/chromium/services/tracing/public/cpp/trace_startup.cc
index 04952821313..e0a92efcd7b 100644
--- a/chromium/services/tracing/public/cpp/trace_startup.cc
+++ b/chromium/services/tracing/public/cpp/trace_startup.cc
@@ -89,14 +89,14 @@ bool EnableStartupTracingForProcess(
privacy_filtering_enabled);
}
-void InitTracingPostThreadPoolStartAndFeatureList() {
+void InitTracingPostThreadPoolStartAndFeatureList(bool enable_consumer) {
if (g_tracing_initialized_after_threadpool_and_featurelist)
return;
g_tracing_initialized_after_threadpool_and_featurelist = true;
DCHECK(base::ThreadPoolInstance::Get());
DCHECK(base::FeatureList::GetInstance());
- PerfettoTracedProcess::Get()->OnThreadPoolAvailable();
+ PerfettoTracedProcess::Get()->OnThreadPoolAvailable(enable_consumer);
if (ShouldSetupSystemTracing()) {
// Ensure that data sources are created and registered.
diff --git a/chromium/services/tracing/public/cpp/trace_startup.h b/chromium/services/tracing/public/cpp/trace_startup.h
index e47d1597cbf..b3f075c773a 100644
--- a/chromium/services/tracing/public/cpp/trace_startup.h
+++ b/chromium/services/tracing/public/cpp/trace_startup.h
@@ -45,8 +45,10 @@ bool COMPONENT_EXPORT(TRACING_CPP)
// Initialize tracing components that require task runners. Will switch
// IsTracingInitialized() to return true.
+// |enable_consumer| should be true if the system consumer can be enabled.
+// Currently this is only the case if this is running in the browser process.
void COMPONENT_EXPORT(TRACING_CPP)
- InitTracingPostThreadPoolStartAndFeatureList();
+ InitTracingPostThreadPoolStartAndFeatureList(bool enable_consumer);
// If tracing is enabled, grabs the current trace config & mode and tells the
// child to begin tracing right away via startup tracing command line flags.
diff --git a/chromium/services/tracing/public/cpp/traced_process_impl.h b/chromium/services/tracing/public/cpp/traced_process_impl.h
index 4e03ce3f4c1..3a2603ce4de 100644
--- a/chromium/services/tracing/public/cpp/traced_process_impl.h
+++ b/chromium/services/tracing/public/cpp/traced_process_impl.h
@@ -29,6 +29,9 @@ class COMPONENT_EXPORT(TRACING_CPP) TracedProcessImpl
public:
static TracedProcessImpl* GetInstance();
+ TracedProcessImpl(const TracedProcessImpl&) = delete;
+ TracedProcessImpl& operator=(const TracedProcessImpl&) = delete;
+
void ResetTracedProcessReceiver();
void OnTracedProcessRequest(
mojo::PendingReceiver<mojom::TracedProcess> receiver);
@@ -63,7 +66,6 @@ class COMPONENT_EXPORT(TRACING_CPP) TracedProcessImpl
scoped_refptr<base::SequencedTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
- DISALLOW_COPY_AND_ASSIGN(TracedProcessImpl);
};
} // namespace tracing
diff --git a/chromium/services/tracing/tracing_service.h b/chromium/services/tracing/tracing_service.h
index 9651aec1db0..5af65141c48 100644
--- a/chromium/services/tracing/tracing_service.h
+++ b/chromium/services/tracing/tracing_service.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_TRACING_TRACING_SERVICE_H_
#define SERVICES_TRACING_TRACING_SERVICE_H_
+#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -33,7 +34,7 @@ class TracingService : public mojom::TracingService {
private:
mojo::Receiver<mojom::TracingService> receiver_{this};
- PerfettoService* perfetto_service_;
+ raw_ptr<PerfettoService> perfetto_service_;
};
} // namespace tracing
diff --git a/chromium/services/tracing/tracing_service_unittest.cc b/chromium/services/tracing/tracing_service_unittest.cc
index d58ea7bb112..3ecf9477527 100644
--- a/chromium/services/tracing/tracing_service_unittest.cc
+++ b/chromium/services/tracing/tracing_service_unittest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/files/file_util.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.h"
@@ -45,6 +44,9 @@ class TracingServiceTest : public TracingUnitTest {
public:
TracingServiceTest() : service_(&perfetto_service_) {}
+ TracingServiceTest(const TracingServiceTest&) = delete;
+ TracingServiceTest& operator=(const TracingServiceTest&) = delete;
+
void SetUp() override {
TracingUnitTest::SetUp();
perfetto_service()->SetActiveServicePidsInitialized();
@@ -117,8 +119,6 @@ class TracingServiceTest : public TracingUnitTest {
std::unique_ptr<mojo::Receiver<tracing::mojom::TracedProcess>>
traced_process_receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(TracingServiceTest);
};
class TestTracingClient : public mojom::TracingSessionClient {
diff --git a/chromium/services/video_capture/broadcasting_receiver.cc b/chromium/services/video_capture/broadcasting_receiver.cc
index 30498d1efa3..18b211b00b3 100644
--- a/chromium/services/video_capture/broadcasting_receiver.cc
+++ b/chromium/services/video_capture/broadcasting_receiver.cc
@@ -222,7 +222,15 @@ BroadcastingReceiver::BufferContext::CloneBufferHandle(
}
break;
case media::VideoCaptureBufferType::kGpuMemoryBuffer:
+#if defined(OS_WIN)
+ // On windows with MediaFoundationD3D11VideoCapture if the
+ // texture capture path fails, a ShMem buffer might be produced instead.
+ DCHECK(buffer_handle_->is_shared_buffer_handle());
+ CloneSharedBufferHandle(buffer_handle_->get_shared_buffer_handle(),
+ &result);
+#else
NOTREACHED() << "Unexpected GpuMemoryBuffer handle type";
+#endif
break;
}
return result;
diff --git a/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc b/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc
index 45d83c00401..ca8e07bcfc1 100644
--- a/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc
+++ b/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc
@@ -122,7 +122,7 @@ void DeviceFactoryMediaToMojoAdapter::CreateDevice(
device_entry.receiver->set_disconnect_handler(base::BindOnce(
&DeviceFactoryMediaToMojoAdapter::OnClientConnectionErrorOrClose,
base::Unretained(this), device_id));
- std::move(callback).Run(mojom::DeviceAccessResultCode::SUCCESS);
+ std::move(callback).Run(media::VideoCaptureError::kNone);
return;
}
@@ -175,16 +175,17 @@ void DeviceFactoryMediaToMojoAdapter::CreateAndAddNewDevice(
const std::string& device_id,
mojo::PendingReceiver<mojom::Device> device_receiver,
CreateDeviceCallback callback) {
- std::unique_ptr<media::VideoCaptureDevice> media_device =
+ media::VideoCaptureErrorOrDevice device_status =
capture_system_->CreateDevice(device_id);
- if (media_device == nullptr) {
- std::move(callback).Run(
- mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND);
+ if (!device_status.ok()) {
+ std::move(callback).Run(device_status.error());
return;
}
// Add entry to active_devices to keep track of it
ActiveDeviceEntry device_entry;
+ std::unique_ptr<media::VideoCaptureDevice> media_device =
+ device_status.ReleaseDevice();
#if BUILDFLAG(IS_CHROMEOS_ASH)
device_entry.device = std::make_unique<DeviceMediaToMojoAdapter>(
@@ -201,7 +202,7 @@ void DeviceFactoryMediaToMojoAdapter::CreateAndAddNewDevice(
base::Unretained(this), device_id));
active_devices_by_id_[device_id] = std::move(device_entry);
- std::move(callback).Run(mojom::DeviceAccessResultCode::SUCCESS);
+ std::move(callback).Run(media::VideoCaptureError::kNone);
}
void DeviceFactoryMediaToMojoAdapter::OnClientConnectionErrorOrClose(
diff --git a/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc b/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc
index e3a59f1e507..7b1c482a513 100644
--- a/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc
+++ b/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc
@@ -5,6 +5,7 @@
#include "services/video_capture/device_media_to_mojo_adapter.h"
#include "base/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "build/chromeos_buildflags.h"
@@ -48,7 +49,7 @@ class DeviceMediaToMojoAdapterTest : public ::testing::Test {
}
protected:
- media::MockDevice* mock_device_ptr_;
+ raw_ptr<media::MockDevice> mock_device_ptr_;
std::unique_ptr<DeviceMediaToMojoAdapter> adapter_;
std::unique_ptr<MockVideoFrameHandler> mock_video_frame_handler_;
mojo::PendingRemote<mojom::VideoFrameHandler> video_frame_handler_;
diff --git a/chromium/services/video_capture/lacros/device_factory_adapter_lacros.cc b/chromium/services/video_capture/lacros/device_factory_adapter_lacros.cc
index cbd3ab5425f..1e8bb1e4270 100644
--- a/chromium/services/video_capture/lacros/device_factory_adapter_lacros.cc
+++ b/chromium/services/video_capture/lacros/device_factory_adapter_lacros.cc
@@ -48,19 +48,18 @@ void DeviceFactoryAdapterLacros::CreateDevice(
auto wrapped_callback = base::BindOnce(
[](CreateDeviceCallback callback,
crosapi::mojom::DeviceAccessResultCode code) {
- video_capture::mojom::DeviceAccessResultCode video_capture_result_code;
+ media::VideoCaptureError video_capture_result_code;
switch (code) {
case crosapi::mojom::DeviceAccessResultCode::NOT_INITIALIZED:
- video_capture_result_code =
- video_capture::mojom::DeviceAccessResultCode::NOT_INITIALIZED;
+ video_capture_result_code = media::VideoCaptureError::
+ kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice;
break;
case crosapi::mojom::DeviceAccessResultCode::SUCCESS:
- video_capture_result_code =
- video_capture::mojom::DeviceAccessResultCode::SUCCESS;
+ video_capture_result_code = media::VideoCaptureError::kNone;
break;
case crosapi::mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND:
- video_capture_result_code = video_capture::mojom::
- DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND;
+ video_capture_result_code = media::VideoCaptureError::
+ kServiceDeviceLauncherServiceRespondedWithDeviceNotFound;
break;
default:
NOTREACHED() << "Unexpected device access result code";
diff --git a/chromium/services/video_capture/public/mojom/device_factory.mojom b/chromium/services/video_capture/public/mojom/device_factory.mojom
index 69ffd6f863c..86c92290d22 100644
--- a/chromium/services/video_capture/public/mojom/device_factory.mojom
+++ b/chromium/services/video_capture/public/mojom/device_factory.mojom
@@ -10,12 +10,6 @@ import "services/video_capture/public/mojom/devices_changed_observer.mojom";
import "services/video_capture/public/mojom/producer.mojom";
import "services/video_capture/public/mojom/virtual_device.mojom";
-enum DeviceAccessResultCode {
- NOT_INITIALIZED,
- SUCCESS,
- ERROR_DEVICE_NOT_FOUND
-};
-
// Enables access to a set of video capture devices.
// Typical operation is to first call GetDeviceInfos() to obtain
// information about available devices. The |device_id| of the infos can
@@ -38,7 +32,7 @@ interface DeviceFactory {
// |device_receiver| has been (asynchronously) discarded a subsequent call to
// CreateDevice() would succeed if it were to deny access while still in use.
CreateDevice(string device_id, pending_receiver<Device> device_receiver)
- => (DeviceAccessResultCode result_code);
+ => (media.mojom.VideoCaptureError result_code);
// Creates a new virtual capture device, which will be exposed by the device
// factory using the given |device_info|. The returned |virtual_device| is to
diff --git a/chromium/services/video_capture/public/mojom/video_source.mojom b/chromium/services/video_capture/public/mojom/video_source.mojom
index 7033ccb9db1..90a1662a856 100644
--- a/chromium/services/video_capture/public/mojom/video_source.mojom
+++ b/chromium/services/video_capture/public/mojom/video_source.mojom
@@ -8,10 +8,14 @@ import "media/capture/mojom/image_capture.mojom";
import "media/capture/mojom/video_capture_types.mojom";
import "services/video_capture/public/mojom/video_frame_handler.mojom";
-enum CreatePushSubscriptionResultCode {
+enum CreatePushSubscriptionSuccessCode {
kCreatedWithRequestedSettings,
kCreatedWithDifferentSettings,
- kFailed,
+};
+
+union CreatePushSubscriptionResultCode{
+ CreatePushSubscriptionSuccessCode success_code;
+ media.mojom.VideoCaptureError error_code;
};
// In a PushVideoStreamSubscription, the provider pushes frames to the
diff --git a/chromium/services/video_capture/push_video_stream_subscription_impl.cc b/chromium/services/video_capture/push_video_stream_subscription_impl.cc
index 6b8bf8dc121..b8171793b4f 100644
--- a/chromium/services/video_capture/push_video_stream_subscription_impl.cc
+++ b/chromium/services/video_capture/push_video_stream_subscription_impl.cc
@@ -46,23 +46,29 @@ void PushVideoStreamSubscriptionImpl::OnDeviceStartSucceededWithSettings(
// Creation callback has already been run from a previous device start.
return;
}
- mojom::CreatePushSubscriptionResultCode result_code =
+ mojom::CreatePushSubscriptionSuccessCode success_code =
settings == requested_settings_
- ? mojom::CreatePushSubscriptionResultCode::
+ ? mojom::CreatePushSubscriptionSuccessCode::
kCreatedWithRequestedSettings
- : mojom::CreatePushSubscriptionResultCode::
+ : mojom::CreatePushSubscriptionSuccessCode::
kCreatedWithDifferentSettings;
- std::move(creation_callback_).Run(result_code, settings);
+ std::move(creation_callback_)
+ .Run(
+ mojom::CreatePushSubscriptionResultCode::NewSuccessCode(success_code),
+ settings);
status_ = Status::kNotYetActivated;
}
-void PushVideoStreamSubscriptionImpl::OnDeviceStartFailed() {
+void PushVideoStreamSubscriptionImpl::OnDeviceStartFailed(
+ media::VideoCaptureError error) {
+ DCHECK_NE(error, media::VideoCaptureError::kNone);
+
if (status_ != Status::kCreationCallbackNotYetRun) {
// Creation callback has already been run from a previous device start.
return;
}
std::move(creation_callback_)
- .Run(mojom::CreatePushSubscriptionResultCode::kFailed,
+ .Run(mojom::CreatePushSubscriptionResultCode::NewErrorCode(error),
requested_settings_);
status_ = Status::kClosed;
}
diff --git a/chromium/services/video_capture/push_video_stream_subscription_impl.h b/chromium/services/video_capture/push_video_stream_subscription_impl.h
index 3a65e54957e..ae68b62cbab 100644
--- a/chromium/services/video_capture/push_video_stream_subscription_impl.h
+++ b/chromium/services/video_capture/push_video_stream_subscription_impl.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_VIDEO_CAPTURE_PUSH_VIDEO_STREAM_SUBSCRIPTION_IMPL_H_
#define SERVICES_VIDEO_CAPTURE_PUSH_VIDEO_STREAM_SUBSCRIPTION_IMPL_H_
+#include "base/memory/raw_ptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -40,7 +41,7 @@ class PushVideoStreamSubscriptionImpl
void OnDeviceStartSucceededWithSettings(
const media::VideoCaptureParams& settings);
- void OnDeviceStartFailed();
+ void OnDeviceStartFailed(media::VideoCaptureError error);
// mojom::PushVideoStreamSubscription implementation.
void Activate() override;
@@ -68,8 +69,8 @@ class PushVideoStreamSubscriptionImpl
mojo::PendingRemote<mojom::VideoFrameHandler> subscriber_;
const media::VideoCaptureParams requested_settings_;
mojom::VideoSource::CreatePushSubscriptionCallback creation_callback_;
- BroadcastingReceiver* const broadcaster_;
- mojo::Remote<mojom::Device>* const device_;
+ const raw_ptr<BroadcastingReceiver> broadcaster_;
+ const raw_ptr<mojo::Remote<mojom::Device>> device_;
Status status_;
// Client id handed out by |broadcaster_| when registering |this| as its
diff --git a/chromium/services/video_capture/receiver_mojo_to_media_adapter.h b/chromium/services/video_capture/receiver_mojo_to_media_adapter.h
index b190a1bbfc6..e876968907f 100644
--- a/chromium/services/video_capture/receiver_mojo_to_media_adapter.h
+++ b/chromium/services/video_capture/receiver_mojo_to_media_adapter.h
@@ -5,7 +5,7 @@
#ifndef SERVICES_VIDEO_CAPTURE_RECEIVER_MOJO_TO_MEDIA_ADAPTER_H_
#define SERVICES_VIDEO_CAPTURE_RECEIVER_MOJO_TO_MEDIA_ADAPTER_H_
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "media/capture/video/video_frame_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/video_capture/public/cpp/video_frame_access_handler.h"
diff --git a/chromium/services/video_capture/video_source_impl.cc b/chromium/services/video_capture/video_source_impl.cc
index b572ea1e678..daeb07bb945 100644
--- a/chromium/services/video_capture/video_source_impl.cc
+++ b/chromium/services/video_capture/video_source_impl.cc
@@ -101,36 +101,32 @@ void VideoSourceImpl::StartDeviceWithSettings(
}
void VideoSourceImpl::OnCreateDeviceResponse(
- mojom::DeviceAccessResultCode result_code) {
+ media::VideoCaptureError result_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- switch (result_code) {
- case mojom::DeviceAccessResultCode::SUCCESS: {
- broadcaster_video_frame_handler_.reset();
- device_->Start(
- device_start_settings_,
- broadcaster_video_frame_handler_.BindNewPipeAndPassRemote());
- device_status_ = DeviceStatus::kStarted;
- if (push_subscriptions_.empty()) {
- StopDeviceAsynchronously();
- return;
- }
- for (auto& entry : push_subscriptions_) {
- auto& subscription = entry.second;
- subscription->OnDeviceStartSucceededWithSettings(
- device_start_settings_);
- }
+
+ if (result_code == media::VideoCaptureError::kNone) {
+ // Device was created successfully.
+ broadcaster_video_frame_handler_.reset();
+ device_->Start(device_start_settings_,
+ broadcaster_video_frame_handler_.BindNewPipeAndPassRemote());
+ device_status_ = DeviceStatus::kStarted;
+ if (push_subscriptions_.empty()) {
+ StopDeviceAsynchronously();
return;
}
- case mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND: // Fall through
- case mojom::DeviceAccessResultCode::NOT_INITIALIZED:
- for (auto& entry : push_subscriptions_) {
- auto& subscription = entry.second;
- subscription->OnDeviceStartFailed();
- }
- push_subscriptions_.clear();
- device_status_ = DeviceStatus::kNotStarted;
- return;
+ for (auto& entry : push_subscriptions_) {
+ auto& subscription = entry.second;
+ subscription->OnDeviceStartSucceededWithSettings(device_start_settings_);
+ }
+ return;
+ }
+ for (auto& entry : push_subscriptions_) {
+ auto& subscription = entry.second;
+ subscription->OnDeviceStartFailed(result_code);
}
+ push_subscriptions_.clear();
+ device_status_ = DeviceStatus::kNotStarted;
+ return;
}
void VideoSourceImpl::OnPushSubscriptionClosedOrDisconnectedOrDiscarded(
diff --git a/chromium/services/video_capture/video_source_impl.h b/chromium/services/video_capture/video_source_impl.h
index ff80d710317..4a9b0162b57 100644
--- a/chromium/services/video_capture/video_source_impl.h
+++ b/chromium/services/video_capture/video_source_impl.h
@@ -8,6 +8,7 @@
#include <map>
#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -57,14 +58,14 @@ class VideoSourceImpl : public mojom::VideoSource {
void OnClientDisconnected();
void StartDeviceWithSettings(
const media::VideoCaptureParams& requested_settings);
- void OnCreateDeviceResponse(mojom::DeviceAccessResultCode result_code);
+ void OnCreateDeviceResponse(media::VideoCaptureError result_code);
void OnPushSubscriptionClosedOrDisconnectedOrDiscarded(
PushVideoStreamSubscriptionImpl* subscription,
base::OnceClosure done_cb);
void StopDeviceAsynchronously();
void OnStopDeviceComplete();
- mojom::DeviceFactory* const device_factory_;
+ const raw_ptr<mojom::DeviceFactory> device_factory_;
const std::string device_id_;
mojo::ReceiverSet<mojom::VideoSource> receivers_;
base::RepeatingClosure on_last_binding_closed_cb_;
diff --git a/chromium/services/video_capture/video_source_provider_impl.h b/chromium/services/video_capture/video_source_provider_impl.h
index 39bb2475c86..6b8b415aa81 100644
--- a/chromium/services/video_capture/video_source_provider_impl.h
+++ b/chromium/services/video_capture/video_source_provider_impl.h
@@ -7,6 +7,7 @@
#include <map>
+#include "base/memory/raw_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"
@@ -55,7 +56,7 @@ class VideoSourceProviderImpl : public mojom::VideoSourceProvider {
void OnClientDisconnectedOrClosed();
void OnVideoSourceLastClientDisconnected(const std::string& device_id);
- DeviceFactory* const device_factory_;
+ const raw_ptr<DeviceFactory> device_factory_;
base::RepeatingClosure on_last_client_disconnected_cb_;
int client_count_ = 0;
int closed_but_not_yet_disconnected_client_count_ = 0;
diff --git a/chromium/services/video_capture/virtual_device_enabled_device_factory.cc b/chromium/services/video_capture/virtual_device_enabled_device_factory.cc
index 57fc67fce9a..654e319a820 100644
--- a/chromium/services/video_capture/virtual_device_enabled_device_factory.cc
+++ b/chromium/services/video_capture/virtual_device_enabled_device_factory.cc
@@ -147,7 +147,7 @@ void VirtualDeviceEnabledDeviceFactory::CreateDevice(
base::BindOnce(&VirtualDeviceEnabledDeviceFactory::
OnVirtualDeviceConsumerConnectionErrorOrClose,
base::Unretained(this), device_id));
- std::move(callback).Run(mojom::DeviceAccessResultCode::SUCCESS);
+ std::move(callback).Run(media::VideoCaptureError::kNone);
return;
}
diff --git a/chromium/services/viz/privileged/mojom/compositing/BUILD.gn b/chromium/services/viz/privileged/mojom/compositing/BUILD.gn
index 417ca186edc..ee3bcd1bf40 100644
--- a/chromium/services/viz/privileged/mojom/compositing/BUILD.gn
+++ b/chromium/services/viz/privileged/mojom/compositing/BUILD.gn
@@ -29,15 +29,17 @@ mojom("compositing") {
"//ui/latency/mojom",
]
- traits_public_deps = [ "//ui/base:features" ]
+ parser_deps = [ "//components/viz/common" ]
+
+ traits_public_deps = [
+ "//components/viz/common",
+ "//ui/base:features",
+ ]
enabled_features = []
if (use_ozone) {
enabled_features += [ "use_ozone" ]
}
- if (use_x11) {
- enabled_features += [ "use_x11" ]
- }
cpp_typemaps = [
{
diff --git a/chromium/services/viz/privileged/mojom/compositing/DEPS b/chromium/services/viz/privileged/mojom/compositing/DEPS
index 131cc87bdec..b81a4a4e7bc 100644
--- a/chromium/services/viz/privileged/mojom/compositing/DEPS
+++ b/chromium/services/viz/privileged/mojom/compositing/DEPS
@@ -1,5 +1,4 @@
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 409115f9578..9f7583e4240 100644
--- a/chromium/services/viz/privileged/mojom/compositing/display_private.mojom
+++ b/chromium/services/viz/privileged/mojom/compositing/display_private.mojom
@@ -68,6 +68,10 @@ interface DisplayPrivate {
[EnableIf=is_android]
PreserveChildSurfaceControls();
+ // Lets client control whether it wants `DidCompleteSwapWithSize` callbacks.
+ [EnableIf=is_android]
+ SetSwapCompletionCallbackEnabled(bool enable);
+
// Adds an observer that gets notified about vsync parameter changes. See
// VSyncParameterObserver for details.
//
diff --git a/chromium/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom b/chromium/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
index 0656992a640..8f7fc598da7 100644
--- a/chromium/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
+++ b/chromium/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
@@ -8,6 +8,7 @@ import "media/capture/mojom/video_capture_buffer.mojom";
import "media/capture/mojom/video_capture_types.mojom";
import "media/mojo/mojom/media_types.mojom";
import "mojo/public/mojom/base/time.mojom";
+import "mojo/public/mojom/base/token.mojom";
import "mojo/public/mojom/base/shared_memory.mojom";
import "services/viz/public/mojom/compositing/frame_sink_id.mojom";
import "services/viz/public/mojom/compositing/subtree_capture_id.mojom";
@@ -28,6 +29,18 @@ interface FrameSinkVideoConsumerFrameCallbacks {
ProvideFeedback(media.mojom.VideoCaptureFeedback feedback);
};
+// Provided with FrameSinkVideoConsumer::ChangeTarget() to indicate what
+// target should be selected for capture.
+union VideoCaptureSubTarget {
+ SubtreeCaptureId subtree_capture_id;
+ mojo_base.mojom.Token region_capture_crop_id;
+};
+
+struct VideoCaptureTarget {
+ FrameSinkId frame_sink_id;
+ VideoCaptureSubTarget? sub_target;
+};
+
// Interface for a consumer that receives frames and notifications related to
// capture of the source content. An instance that implements this interface is
// provided to FrameSinkVideoCapturer.Start().
@@ -42,7 +55,7 @@ interface FrameSinkVideoConsumer {
// |content_rect| is the region of the frame that contains the captured
// content, with the rest of the frame having been letterboxed to adhere to
// resolution constraints.
- OnFrameCaptured(mojo_base.mojom.ReadOnlySharedMemoryRegion data,
+ OnFrameCaptured(media.mojom.VideoBufferHandle data,
media.mojom.VideoFrameInfo info,
gfx.mojom.Rect content_rect,
pending_remote<FrameSinkVideoConsumerFrameCallbacks>
@@ -56,6 +69,14 @@ interface FrameSinkVideoConsumer {
OnLog(string message);
};
+// Used to express the preference on the type of VideoBufferHandles that the
+// consumer would like to obtain from the capturer. By default, the video
+// buffers are returned via read only shared memory.
+enum BufferFormatPreference {
+ kDefault = 0,
+ kPreferGpuMemoryBuffer,
+};
+
// Interface to an implementation that captures the frames of a
// CompositorFrameSink's surface as a video stream. During operation, the
// "target" frame sink can be changed, as needed, to continue capturing the
@@ -72,11 +93,10 @@ interface FrameSinkVideoConsumer {
// again to resume capture; or the mojo binding can be dropped to auto-terminate
// the capturer.
interface FrameSinkVideoCapturer {
- // Specifies the pixel format and color space to use.
+ // Specifies the pixel format to use.
//
- // Default, if never called: PIXEL_FORMAT_I420, COLOR_SPACE_HD_REC709
- SetFormat(media.mojom.VideoPixelFormat format,
- gfx.mojom.ColorSpace color_space);
+ // Default, if never called: PIXEL_FORMAT_I420.
+ SetFormat(media.mojom.VideoPixelFormat format);
// Specifies the maximum rate of capture in terms of a minimum time period
// (min_period = 1/max_frame_rate).
@@ -119,16 +139,25 @@ interface FrameSinkVideoCapturer {
SetAutoThrottlingEnabled(bool enabled);
// Targets a different compositor frame sink. This may be called anytime,
- // before or after Start(). If |frame_sink_id| is null, capture will suspend
- // until a new frame sink target is set. If the given |subtree_capture_id| is
- // valid, the capturer will capture a render pass associated with a layer
- // subtree under the target frame sink, which is identifiable by that
- // |subtree_capture_id|. Otherwise, the capturer captures the root render pass
- // of the target frame sink.
- ChangeTarget(FrameSinkId? frame_sink_id, SubtreeCaptureId subtree_capture_id);
+ // before or after Start(). If |target| is null, capture will suspend
+ // until a new frame sink target is set. If |target| is provided, the
+ // frame sink identifier associated with it must be valid.
+ // If the |sub_target| is a valid subtree capture id, the capturer will
+ // capture a render pass associated with a layer subtree under the target
+ // frame sink, which is identifiable by that
+ // |subtree_capture_id|. Else, if the |sub_target| is a valid region capture
+ // crop id, only the region associated with that crop id will be captured.
+ // Otherwise, the capturer captures the root render pass of the target frame
+ // sink.
+ ChangeTarget(VideoCaptureTarget? target);
// Starts emitting video frames to the given |consumer|.
- Start(pending_remote<FrameSinkVideoConsumer> consumer);
+ // The caller can express if the |consumer| prefers to receive video buffers
+ // via read only shared memory or via GPU memory buffers by controlling
+ // |buffer_format_preference| parameter. If a consumer only supports read only
+ // shared memory, `BufferFormatPreference::kDefault` value should be used.
+ Start(pending_remote<FrameSinkVideoConsumer> consumer,
+ BufferFormatPreference buffer_format_preference);
// Stops capturing "soon." Meaning, no new frame captures will be started, but
// there may already be some in-flight for delivery. Wait for the "end of
@@ -139,7 +168,7 @@ interface FrameSinkVideoCapturer {
// resolve occasional "picture loss" issues consumer-side.
RequestRefreshFrame();
- // Creates an overlay to be renderered within each captured video frame. The
+ // Creates an overlay to be rendered within each captured video frame. The
// |stacking_index| is an arbitrary value that determines whether to render
// this overlay before/after other overlays. Greater values mean "after" and
// "on top of" those with lesser values. Specifying the same index as an
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 98e91d5df4b..d795357ece4 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,7 +5,6 @@
#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"
@@ -57,8 +56,7 @@ bool StructTraits<viz::mojom::RendererSettingsDataView, viz::RendererSettings>::
#endif
#if defined(USE_OZONE)
- if (features::IsUsingOzonePlatform() &&
- !data.ReadOverlayStrategies(&out->overlay_strategies))
+ if (!data.ReadOverlayStrategies(&out->overlay_strategies))
return false;
#endif
diff --git a/chromium/services/viz/privileged/mojom/gl/BUILD.gn b/chromium/services/viz/privileged/mojom/gl/BUILD.gn
index cf529d5827d..323931587ec 100644
--- a/chromium/services/viz/privileged/mojom/gl/BUILD.gn
+++ b/chromium/services/viz/privileged/mojom/gl/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/sanitizers/sanitizers.gni")
+import("//media/gpu/args.gni")
import("//mojo/public/tools/bindings/mojom.gni")
mojom("gl") {
@@ -23,7 +24,7 @@ mojom("gl") {
]
if (is_chromeos_ash) {
public_deps += [
- "//components/arc/mojom:media",
+ "//ash/components/arc/mojom:media",
"//components/chromeos_camera/common",
]
}
@@ -41,6 +42,10 @@ mojom("gl") {
enabled_features += [ "use_clang_profiling_inside_sandbox" ]
}
+ if (is_chromeos_ash && (use_vaapi || use_v4l2_codec)) {
+ enabled_features += [ "enable_arc_media" ]
+ }
+
cpp_typemaps = [
{
types = [
diff --git a/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom b/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom
index dd24181bfea..9dbf440837b 100644
--- a/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom
+++ b/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom
@@ -5,13 +5,13 @@
module viz.mojom;
[EnableIf=is_chromeos_ash]
-import "components/arc/mojom/protected_buffer_manager.mojom";
+import "ash/components/arc/mojom/protected_buffer_manager.mojom";
[EnableIf=is_chromeos_ash]
-import "components/arc/mojom/video_decode_accelerator.mojom";
+import "ash/components/arc/mojom/video_decode_accelerator.mojom";
[EnableIf=is_chromeos_ash]
-import "components/arc/mojom/video_encode_accelerator.mojom";
+import "ash/components/arc/mojom/video_encode_accelerator.mojom";
[EnableIf=is_chromeos_ash]
-import "components/arc/mojom/video_protected_buffer_allocator.mojom";
+import "ash/components/arc/mojom/video_protected_buffer_allocator.mojom";
[EnableIf=is_chromeos_ash]
import "components/chromeos_camera/common/mjpeg_decode_accelerator.mojom";
[EnableIf=is_chromeos_ash]
@@ -61,22 +61,22 @@ interface GpuService {
CloseChannel(int32 client_id);
// Create a new ARC VideoDecodeAccelerator and binds it to |vda|.
- [EnableIf=is_chromeos_ash]
+ [EnableIf=enable_arc_media]
CreateArcVideoDecodeAccelerator(
pending_receiver<arc.mojom.VideoDecodeAccelerator> vda);
// Create a new ARC VideoEncodeAccelerator and binds it to |vea|.
- [EnableIf=is_chromeos_ash]
+ [EnableIf=enable_arc_media]
CreateArcVideoEncodeAccelerator(
pending_receiver<arc.mojom.VideoEncodeAccelerator> vea);
// Create a new ARC VideoProtectedBufferAllocator and binds it to |pba|.
- [EnableIf=is_chromeos_ash]
+ [EnableIf=enable_arc_media ]
CreateArcVideoProtectedBufferAllocator(
pending_receiver<arc.mojom.VideoProtectedBufferAllocator> pba);
// Create a new ARC ProtectedBufferManager and binds it to |pbm|.
- [EnableIf=is_chromeos_ash]
+ [EnableIf=enable_arc_media ]
CreateArcProtectedBufferManager(
pending_receiver<arc.mojom.ProtectedBufferManager> pbm);
diff --git a/chromium/services/viz/privileged/mojom/viz_main.mojom b/chromium/services/viz/privileged/mojom/viz_main.mojom
index fd293eaf3a9..f5a445aaea9 100644
--- a/chromium/services/viz/privileged/mojom/viz_main.mojom
+++ b/chromium/services/viz/privileged/mojom/viz_main.mojom
@@ -60,6 +60,11 @@ interface VizMain {
CreateInfoCollectionGpuService(
pending_receiver<InfoCollectionGpuService> info_collection_gpu_service);
+ // Pass the process ID of the browser process to the viz process. Used for
+ // Android performance hinting.
+ [EnableIf=is_android]
+ SetHostProcessId(int32 pid);
+
// Initiates the devtools enabled stream connection for the Viz Debugger.
// This is only called if the flag --enable-viz-devtools is used.
[EnableIf=use_viz_debugger]
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
index 624a6bd24a2..5c06a61985a 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
@@ -10,6 +10,7 @@
#include "services/viz/public/cpp/compositing/selection_mojom_traits.h"
#include "services/viz/public/cpp/compositing/surface_id_mojom_traits.h"
#include "services/viz/public/cpp/crash_keys.h"
+#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
#include "ui/gfx/mojom/display_color_spaces_mojom_traits.h"
#include "ui/gfx/mojom/selection_bound_mojom_traits.h"
#include "ui/latency/mojom/latency_info_mojom_traits.h"
@@ -42,6 +43,7 @@ bool StructTraits<viz::mojom::CompositorFrameMetadataDataView,
return false;
out->may_contain_video = data.may_contain_video();
out->may_throttle_if_undrawn_frames = data.may_throttle_if_undrawn_frames();
+ out->has_shared_element_resources = data.has_shared_element_resources();
out->is_resourceless_software_draw_with_scroll_or_animation =
data.is_resourceless_software_draw_with_scroll_or_animation();
out->send_frame_token_to_embedder = data.send_frame_token_to_embedder();
@@ -57,7 +59,7 @@ bool StructTraits<viz::mojom::CompositorFrameMetadataDataView,
// Preferred_frame_interval must be nullopt or non-negative.
if (out->preferred_frame_interval &&
- *out->preferred_frame_interval < base::TimeDelta()) {
+ out->preferred_frame_interval->is_negative()) {
return false;
}
@@ -68,7 +70,8 @@ bool StructTraits<viz::mojom::CompositorFrameMetadataDataView,
data.ReadBeginFrameAck(&out->begin_frame_ack) &&
data.ReadDisplayTransformHint(&out->display_transform_hint) &&
data.ReadDelegatedInkMetadata(&out->delegated_ink_metadata) &&
- data.ReadTransitionDirectives(&out->transition_directives);
+ data.ReadTransitionDirectives(&out->transition_directives) &&
+ data.ReadCaptureBounds(&out->capture_bounds);
}
} // namespace mojo
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h
index b0a27e461a4..be2f79d1ed7 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h
@@ -10,9 +10,11 @@
#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "components/viz/common/surfaces/region_capture_bounds.h"
#include "services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.h"
#include "services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.h"
#include "services/viz/public/cpp/compositing/frame_deadline_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/region_capture_bounds_mojom_traits.h"
#include "services/viz/public/cpp/compositing/surface_range_mojom_traits.h"
#include "services/viz/public/mojom/compositing/compositor_frame_metadata.mojom-shared.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -31,7 +33,7 @@ struct StructTraits<viz::mojom::CompositorFrameMetadataDataView,
return metadata.device_scale_factor;
}
- static gfx::Vector2dF root_scroll_offset(
+ static gfx::PointF root_scroll_offset(
const viz::CompositorFrameMetadata& metadata) {
return metadata.root_scroll_offset;
}
@@ -59,6 +61,11 @@ struct StructTraits<viz::mojom::CompositorFrameMetadataDataView,
return metadata.may_throttle_if_undrawn_frames;
}
+ static bool has_shared_element_resources(
+ const viz::CompositorFrameMetadata& metadata) {
+ return metadata.has_shared_element_resources;
+ }
+
static bool is_resourceless_software_draw_with_scroll_or_animation(
const viz::CompositorFrameMetadata& metadata) {
return metadata.is_resourceless_software_draw_with_scroll_or_animation;
@@ -141,6 +148,11 @@ struct StructTraits<viz::mojom::CompositorFrameMetadataDataView,
return metadata.transition_directives;
}
+ static const viz::RegionCaptureBounds& capture_bounds(
+ const viz::CompositorFrameMetadata& metadata) {
+ return metadata.capture_bounds;
+ }
+
static bool Read(viz::mojom::CompositorFrameMetadataDataView data,
viz::CompositorFrameMetadata* out);
};
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.cc
index 63302f52043..bbed130be47 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.cc
@@ -12,6 +12,7 @@
#include "components/viz/common/quads/compositor_render_pass.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "services/viz/public/cpp/compositing/compositor_render_pass_id_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h"
#include "services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom-shared.h"
namespace mojo {
@@ -26,6 +27,11 @@ EnumTraits<viz::mojom::CompositorFrameTransitionDirectiveType,
return viz::mojom::CompositorFrameTransitionDirectiveType::kSave;
case viz::CompositorFrameTransitionDirective::Type::kAnimate:
return viz::mojom::CompositorFrameTransitionDirectiveType::kAnimate;
+ case viz::CompositorFrameTransitionDirective::Type::kAnimateRenderer:
+ return viz::mojom::CompositorFrameTransitionDirectiveType::
+ kAnimateRenderer;
+ case viz::CompositorFrameTransitionDirective::Type::kRelease:
+ return viz::mojom::CompositorFrameTransitionDirectiveType::kRelease;
}
NOTREACHED();
return viz::mojom::CompositorFrameTransitionDirectiveType::kSave;
@@ -43,6 +49,12 @@ bool EnumTraits<viz::mojom::CompositorFrameTransitionDirectiveType,
case viz::mojom::CompositorFrameTransitionDirectiveType::kAnimate:
*out = viz::CompositorFrameTransitionDirective::Type::kAnimate;
return true;
+ case viz::mojom::CompositorFrameTransitionDirectiveType::kAnimateRenderer:
+ *out = viz::CompositorFrameTransitionDirective::Type::kAnimateRenderer;
+ return true;
+ case viz::mojom::CompositorFrameTransitionDirectiveType::kRelease:
+ *out = viz::CompositorFrameTransitionDirective::Type::kRelease;
+ return true;
}
return false;
}
@@ -145,7 +157,8 @@ bool StructTraits<
data,
viz::CompositorFrameTransitionDirective::SharedElement* out) {
return data.ReadConfig(&out->config) &&
- data.ReadRenderPassId(&out->render_pass_id);
+ data.ReadRenderPassId(&out->render_pass_id) &&
+ data.ReadSharedElementResourceId(&out->shared_element_resource_id);
}
// static
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.h
index d858b8388f1..7e699406e02 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_transition_directive_mojom_traits.h
@@ -69,6 +69,11 @@ struct StructTraits<
return element.config;
}
+ static viz::SharedElementResourceId shared_element_resource_id(
+ const viz::CompositorFrameTransitionDirective::SharedElement& element) {
+ return element.shared_element_resource_id;
+ }
+
static bool Read(
viz::mojom::CompositorFrameTransitionDirectiveSharedElementDataView data,
viz::CompositorFrameTransitionDirective::SharedElement* out);
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc
index d98c1d9cbaf..b944683fdfe 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc
@@ -29,6 +29,7 @@ bool StructTraits<viz::mojom::CompositorRenderPassDataView,
!data.ReadSubtreeCaptureId(&(*out)->subtree_capture_id) ||
!data.ReadSubtreeSize(&(*out)->subtree_size) ||
!data.ReadCopyRequests(&(*out)->copy_requests) ||
+ !data.ReadSharedElementResourceId(&(*out)->shared_element_resource_id) ||
!data.ReadId(&(*out)->id)) {
return false;
}
@@ -41,6 +42,7 @@ bool StructTraits<viz::mojom::CompositorRenderPassDataView,
(*out)->subtree_size.height() > (*out)->output_rect.size().height()) {
return false;
}
+
(*out)->has_transparent_background = data.has_transparent_background();
(*out)->has_per_quad_damage = data.has_per_quad_damage();
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h
index 0b0ce8875e6..0bbec222288 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h
@@ -71,6 +71,12 @@ struct StructTraits<viz::mojom::CompositorRenderPassDataView,
const std::unique_ptr<viz::CompositorRenderPass>& input) {
return input->subtree_size;
}
+
+ static viz::SharedElementResourceId shared_element_resource_id(
+ const std::unique_ptr<viz::CompositorRenderPass>& input) {
+ return input->shared_element_resource_id;
+ }
+
static bool has_transparent_background(
const std::unique_ptr<viz::CompositorRenderPass>& input) {
return input->has_transparent_background;
diff --git a/chromium/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
index 3bcc9d39366..494429cf31e 100644
--- a/chromium/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
@@ -294,7 +294,7 @@ bool StructTraits<viz::mojom::CopyOutputResultDataView,
base::BindOnce(&Release, std::move(releaser)));
*out_p = std::make_unique<viz::CopyOutputTextureResult>(
- rect,
+ viz::CopyOutputResult::Format::RGBA, rect,
viz::CopyOutputResult::TextureResult(*mailbox, *sync_token,
*color_space),
std::move(release_callbacks));
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 94678265cec..21a8f0e7b7a 100644
--- a/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
+++ b/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
@@ -10,6 +10,7 @@
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
+#include "components/viz/common/surfaces/region_capture_bounds.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
#include "components/viz/test/compositor_frame_helpers.h"
#include "gpu/ipc/common/mailbox_holder_mojom_traits.h"
@@ -210,8 +211,9 @@ class VizSerializationPerfTest : public testing::Test {
pass_in->SetAll(root_id, arbitrary_rect1, arbitrary_rect2,
arbitrary_matrix1, arbitrary_filters2, arbitrary_filters1,
arbitrary_rrectf1, SubtreeCaptureId(),
- arbitrary_rect1.size(), arbitrary_bool1, arbitrary_bool1,
- arbitrary_bool1, arbitrary_bool1, arbitrary_bool7);
+ arbitrary_rect1.size(), SharedElementResourceId(),
+ arbitrary_bool1, arbitrary_bool1, arbitrary_bool1,
+ arbitrary_bool1, arbitrary_bool7);
// Texture quads
for (uint32_t i = 0; i < 10; ++i) {
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 55a8c6909ea..007660804c7 100644
--- a/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
+++ b/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
@@ -17,6 +17,7 @@
#include "components/viz/common/resources/resource_settings.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/common/surfaces/region_capture_bounds.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/common/surfaces/surface_range.h"
@@ -360,7 +361,7 @@ TEST_F(StructTraitsTest, CopyOutputRequest_TextureRequest) {
run_loop_for_release.QuitClosure(), sync_token));
output->SendResult(std::make_unique<CopyOutputTextureResult>(
- result_rect,
+ result_format, result_rect,
CopyOutputResult::TextureResult(mailbox, sync_token,
gfx::ColorSpace::CreateSRGB()),
std::move(release_callbacks)));
@@ -523,7 +524,7 @@ TEST_F(StructTraitsTest, CompositorFrame) {
// CompositorFrameMetadata constants.
const float device_scale_factor = 2.6f;
- const gfx::Vector2dF root_scroll_offset(1234.5f, 6789.1f);
+ const gfx::PointF root_scroll_offset(1234.5f, 6789.1f);
const float page_scale_factor = 1337.5f;
const gfx::SizeF scrollable_viewport_size(1337.7f, 1234.5f);
const BeginFrameAck begin_frame_ack(5, 10, false);
@@ -668,7 +669,7 @@ TEST_F(StructTraitsTest, ReturnedResource) {
TEST_F(StructTraitsTest, CompositorFrameMetadata) {
const float device_scale_factor = 2.6f;
- const gfx::Vector2dF root_scroll_offset(1234.5f, 6789.1f);
+ const gfx::PointF root_scroll_offset(1234.5f, 6789.1f);
const float page_scale_factor = 1337.5f;
const gfx::SizeF scrollable_viewport_size(1337.7f, 1234.5f);
const bool may_contain_video = true;
@@ -768,9 +769,9 @@ TEST_F(StructTraitsTest, RenderPass) {
input->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root,
filters, backdrop_filters, backdrop_filter_bounds,
subtree_capture_id, output_rect.size(),
- has_transparent_background, cache_render_pass,
- has_damage_from_contributing_content, generate_mipmap,
- has_per_quad_damage);
+ SharedElementResourceId(), has_transparent_background,
+ cache_render_pass, has_damage_from_contributing_content,
+ generate_mipmap, has_per_quad_damage);
input->copy_requests.push_back(CopyOutputRequest::CreateStubForTesting());
const gfx::Rect copy_output_area(24, 42, 75, 57);
input->copy_requests.back()->set_area(copy_output_area);
@@ -915,9 +916,9 @@ TEST_F(StructTraitsTest, RenderPassWithEmptySharedQuadStateList) {
input->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root,
cc::FilterOperations(), cc::FilterOperations(),
backdrop_filter_bounds, subtree_capture_id, output_rect.size(),
- has_transparent_background, cache_render_pass,
- has_damage_from_contributing_content, generate_mipmap,
- has_per_quad_damage);
+ SharedElementResourceId(), has_transparent_background,
+ cache_render_pass, has_damage_from_contributing_content,
+ generate_mipmap, has_per_quad_damage);
// Unlike the previous test, don't add any quads to the list; we need to
// verify that the serialization code can deal with that.
@@ -1337,7 +1338,7 @@ TEST_F(StructTraitsTest, CopyOutputResult_Texture) {
mailbox.SetName(mailbox_name);
std::unique_ptr<CopyOutputResult> input =
std::make_unique<CopyOutputTextureResult>(
- result_rect,
+ CopyOutputResult::Format::RGBA, result_rect,
CopyOutputResult::TextureResult(mailbox, sync_token,
result_color_space),
std::move(release_callbacks));
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 75c8a50339e..82e6478328a 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 "components/viz/common/quads/shared_element_draw_quad.h"
#include "services/viz/public/cpp/compositing/compositor_render_pass_id_mojom_traits.h"
#include "services/viz/public/cpp/compositing/resource_id_mojom_traits.h"
#include "services/viz/public/cpp/crash_keys.h"
@@ -55,6 +56,10 @@ viz::DrawQuad* AllocateAndConstruct(
quad = list->AllocateAndConstruct<viz::YUVVideoDrawQuad>();
quad->material = viz::DrawQuad::Material::kYuvVideoContent;
return quad;
+ case viz::mojom::DrawQuadStateDataView::Tag::SHARED_ELEMENT_QUAD_STATE:
+ quad = list->AllocateAndConstruct<viz::SharedElementDrawQuad>();
+ quad->material = viz::DrawQuad::Material::kSharedElement;
+ return quad;
}
NOTREACHED();
return nullptr;
@@ -169,7 +174,6 @@ bool StructTraits<viz::mojom::TextureQuadStateDataView, viz::DrawQuad>::Read(
quad->nearest_neighbor = data.nearest_neighbor();
quad->secure_output_only = data.secure_output_only();
quad->is_video_frame = data.is_video_frame();
- quad->hw_protected_validation_id = data.hw_protected_validation_id();
if (!data.ReadDamageRect(&quad->damage_rect))
return false;
@@ -197,6 +201,14 @@ bool StructTraits<viz::mojom::TileQuadStateDataView, viz::DrawQuad>::Read(
}
// static
+bool StructTraits<viz::mojom::SharedElementQuadStateDataView, viz::DrawQuad>::
+ Read(viz::mojom::SharedElementQuadStateDataView data, viz::DrawQuad* out) {
+ viz::SharedElementDrawQuad* shared_element_quad =
+ static_cast<viz::SharedElementDrawQuad*>(out);
+ return data.ReadResourceId(&shared_element_quad->resource_id);
+}
+
+// static
bool StructTraits<viz::mojom::VideoHoleQuadStateDataView, viz::DrawQuad>::Read(
viz::mojom::VideoHoleQuadStateDataView data,
viz::DrawQuad* out) {
diff --git a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
index 45636dac67a..eb23a4b5ebe 100644
--- a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
@@ -7,11 +7,13 @@
#include "base/check.h"
#include "base/containers/span.h"
+#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/unguessable_token.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/picture_draw_quad.h"
+#include "components/viz/common/quads/shared_element_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/stream_video_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
@@ -20,8 +22,10 @@
#include "components/viz/common/quads/video_hole_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
+#include "components/viz/common/shared_element_resource_id.h"
#include "services/viz/public/cpp/compositing/filter_operation_mojom_traits.h"
#include "services/viz/public/cpp/compositing/filter_operations_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h"
#include "services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h"
#include "services/viz/public/cpp/compositing/surface_range_mojom_traits.h"
#include "services/viz/public/mojom/compositing/quads.mojom-shared.h"
@@ -134,6 +138,9 @@ struct UnionTraits<viz::mojom::DrawQuadStateDataView, viz::DrawQuad> {
return viz::mojom::DrawQuadStateDataView::Tag::VIDEO_HOLE_QUAD_STATE;
case viz::DrawQuad::Material::kYuvVideoContent:
return viz::mojom::DrawQuadStateDataView::Tag::YUV_VIDEO_QUAD_STATE;
+ case viz::DrawQuad::Material::kSharedElement:
+ return viz::mojom::DrawQuadStateDataView::Tag::
+ SHARED_ELEMENT_QUAD_STATE;
}
NOTREACHED();
return viz::mojom::DrawQuadStateDataView::Tag::DEBUG_BORDER_QUAD_STATE;
@@ -179,6 +186,11 @@ struct UnionTraits<viz::mojom::DrawQuadStateDataView, viz::DrawQuad> {
return quad;
}
+ static const viz::DrawQuad& shared_element_quad_state(
+ const viz::DrawQuad& quad) {
+ return quad;
+ }
+
static bool Read(viz::mojom::DrawQuadStateDataView data, viz::DrawQuad* out) {
switch (data.tag()) {
case viz::mojom::DrawQuadStateDataView::Tag::DEBUG_BORDER_QUAD_STATE:
@@ -199,6 +211,8 @@ struct UnionTraits<viz::mojom::DrawQuadStateDataView, viz::DrawQuad> {
return data.ReadVideoHoleQuadState(out);
case viz::mojom::DrawQuadStateDataView::Tag::YUV_VIDEO_QUAD_STATE:
return data.ReadYuvVideoQuadState(out);
+ case viz::mojom::DrawQuadStateDataView::Tag::SHARED_ELEMENT_QUAD_STATE:
+ return data.ReadSharedElementQuadState(out);
}
NOTREACHED();
return false;
@@ -206,6 +220,19 @@ struct UnionTraits<viz::mojom::DrawQuadStateDataView, viz::DrawQuad> {
};
template <>
+struct StructTraits<viz::mojom::SharedElementQuadStateDataView, viz::DrawQuad> {
+ static const viz::SharedElementResourceId& resource_id(
+ const viz::DrawQuad& input) {
+ const viz::SharedElementDrawQuad* quad =
+ viz::SharedElementDrawQuad::MaterialCast(&input);
+ return quad->resource_id;
+ }
+
+ static bool Read(viz::mojom::SharedElementQuadStateDataView data,
+ viz::DrawQuad* out);
+};
+
+template <>
struct StructTraits<viz::mojom::VideoHoleQuadStateDataView, viz::DrawQuad> {
static const base::UnguessableToken& overlay_plane_id(
const viz::DrawQuad& input) {
@@ -471,12 +498,6 @@ struct StructTraits<viz::mojom::TextureQuadStateDataView, viz::DrawQuad> {
return quad->overlay_priority_hint;
}
- static uint32_t hw_protected_validation_id(const viz::DrawQuad& input) {
- const viz::TextureDrawQuad* quad =
- viz::TextureDrawQuad::MaterialCast(&input);
- return quad->hw_protected_validation_id;
- }
-
static const absl::optional<gfx::Rect>& damage_rect(
const viz::DrawQuad& input) {
const viz::TextureDrawQuad* quad =
@@ -664,7 +685,7 @@ struct ArrayTraits<viz::QuadList> {
: it(it), last_shared_quad_state(nullptr) {}
viz::QuadList::ConstIterator it;
- const viz::SharedQuadState* last_shared_quad_state;
+ raw_ptr<const viz::SharedQuadState> last_shared_quad_state;
};
static ConstIterator GetBegin(const viz::QuadList& input) {
diff --git a/chromium/services/viz/public/cpp/compositing/region_capture_bounds_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/region_capture_bounds_mojom_traits.h
new file mode 100644
index 00000000000..e8806c93180
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/region_capture_bounds_mojom_traits.h
@@ -0,0 +1,75 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_REGION_CAPTURE_BOUNDS_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_REGION_CAPTURE_BOUNDS_MOJOM_TRAITS_H_
+
+#include <utility>
+#include <vector>
+
+#include "components/viz/common/surfaces/region_capture_bounds.h"
+#include "mojo/public/cpp/base/token_mojom_traits.h"
+#include "services/viz/public/mojom/compositing/region_capture_bounds.mojom-shared.h"
+
+namespace mojo {
+// Intermediary struct for mapping RegionCaptureBounds map key value pairs.
+struct CropIdBoundsPair {
+ base::Token crop_id;
+ gfx::Rect bounds;
+};
+template <>
+struct StructTraits<viz::mojom::CropIdBoundsPairDataView, CropIdBoundsPair> {
+ static base::Token crop_id(const CropIdBoundsPair& pair) {
+ return pair.crop_id;
+ }
+
+ static gfx::Rect bounds(const CropIdBoundsPair& pair) { return pair.bounds; }
+
+ static bool Read(viz::mojom::CropIdBoundsPairDataView data,
+ CropIdBoundsPair* out) {
+ base::Token crop_id;
+ gfx::Rect bounds;
+ if (!data.ReadCropId(&crop_id)) {
+ return false;
+ }
+ if (!data.ReadBounds(&bounds)) {
+ return false;
+ }
+ *out = CropIdBoundsPair{std::move(crop_id), std::move(bounds)};
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<viz::mojom::RegionCaptureBoundsDataView,
+ viz::RegionCaptureBounds> {
+ static std::vector<CropIdBoundsPair> bounds(
+ const viz::RegionCaptureBounds& capture_bounds) {
+ std::vector<CropIdBoundsPair> out;
+ out.reserve(capture_bounds.bounds().size());
+ for (const auto& pair : capture_bounds.bounds()) {
+ out.push_back(CropIdBoundsPair{pair.first, pair.second});
+ }
+ return out;
+ }
+
+ static bool Read(viz::mojom::RegionCaptureBoundsDataView data,
+ viz::RegionCaptureBounds* out) {
+ std::vector<CropIdBoundsPair> token_rects;
+ if (!data.ReadBounds(&token_rects)) {
+ return false;
+ }
+
+ base::flat_map<viz::RegionCaptureCropId, gfx::Rect> bounds;
+ for (const auto& pair : token_rects) {
+ bounds.emplace(pair.crop_id, pair.bounds);
+ }
+ *out = viz::RegionCaptureBounds(std::move(bounds));
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_REGION_CAPTURE_BOUNDS_MOJOM_TRAITS_H_
diff --git a/chromium/services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h
new file mode 100644
index 00000000000..f86f6ecb35d
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_SHARED_ELEMENT_RESOURCE_ID_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_SHARED_ELEMENT_RESOURCE_ID_MOJOM_TRAITS_H_
+
+#include "services/viz/public/mojom/compositing/shared_element_resource_id.mojom-shared.h"
+
+#include "components/viz/common/shared_element_resource_id.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<viz::mojom::SharedElementResourceIdDataView,
+ viz::SharedElementResourceId> {
+ static uint32_t id(const viz::SharedElementResourceId& resource_id) {
+ return resource_id.id();
+ }
+
+ static bool Read(viz::mojom::SharedElementResourceIdDataView data,
+ viz::SharedElementResourceId* out) {
+ *out = viz::SharedElementResourceId(data.id());
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_SHARED_ELEMENT_RESOURCE_ID_MOJOM_TRAITS_H_
diff --git a/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc
index 53cbd1aaeb3..0235fef4723 100644
--- a/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc
@@ -32,10 +32,15 @@ bool StructTraits<viz::mojom::TransferableResourceDataView,
out->read_lock_fences_enabled = data.read_lock_fences_enabled();
out->is_software = data.is_software();
out->is_overlay_candidate = data.is_overlay_candidate();
+
#if defined(OS_ANDROID)
out->is_backed_by_surface_texture = data.is_backed_by_surface_texture();
+#endif
+
+#if defined(OS_ANDROID) || defined(OS_WIN)
out->wants_promotion_hint = data.wants_promotion_hint();
#endif
+
return true;
}
diff --git a/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.h
index 4f5f60a3a72..057dedb085f 100644
--- a/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.h
@@ -67,7 +67,7 @@ struct StructTraits<viz::mojom::TransferableResourceDataView,
}
static bool wants_promotion_hint(const viz::TransferableResource& resource) {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// TransferableResource has this in an #ifdef, but mojo doesn't let us.
// TODO(https://crbug.com/671901)
return resource.wants_promotion_hint;
diff --git a/chromium/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h
new file mode 100644
index 00000000000..85e466de9c9
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h
@@ -0,0 +1,104 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VIDEO_CAPTURE_TARGET_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VIDEO_CAPTURE_TARGET_MOJOM_TRAITS_H_
+
+#include <utility>
+
+#include "build/build_config.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
+#include "mojo/public/cpp/base/token_mojom_traits.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom-shared.h"
+#include "services/viz/public/cpp/compositing/frame_sink_id_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h"
+
+namespace mojo {
+
+template <>
+struct UnionTraits<viz::mojom::VideoCaptureSubTargetDataView,
+ viz::VideoCaptureSubTarget> {
+ static bool IsNull(const viz::VideoCaptureSubTarget& data) {
+ return absl::holds_alternative<absl::monostate>(data);
+ }
+
+ static void SetToNull(viz::VideoCaptureSubTarget* data) {
+ *data = viz::VideoCaptureSubTarget();
+ }
+
+ static const viz::RegionCaptureCropId& region_capture_crop_id(
+ const viz::VideoCaptureSubTarget& data) {
+ return absl::get<viz::RegionCaptureCropId>(data);
+ }
+
+ static viz::SubtreeCaptureId subtree_capture_id(
+ const viz::VideoCaptureSubTarget& data) {
+ return absl::get<viz::SubtreeCaptureId>(data);
+ }
+
+ using Tag = viz::mojom::VideoCaptureSubTargetDataView::Tag;
+ static Tag GetTag(const viz::VideoCaptureSubTarget& data) {
+ if (absl::holds_alternative<viz::RegionCaptureCropId>(data)) {
+ return Tag::REGION_CAPTURE_CROP_ID;
+ }
+ DCHECK(absl::holds_alternative<viz::SubtreeCaptureId>(data));
+ return Tag::SUBTREE_CAPTURE_ID;
+ }
+
+ static bool Read(viz::mojom::VideoCaptureSubTargetDataView data,
+ viz::VideoCaptureSubTarget* out) {
+ switch (data.tag()) {
+ case Tag::REGION_CAPTURE_CROP_ID: {
+ viz::RegionCaptureCropId crop_id;
+ if (!data.ReadRegionCaptureCropId(&crop_id) || crop_id.is_zero())
+ return false;
+
+ *out = crop_id;
+ return true;
+ }
+ case Tag::SUBTREE_CAPTURE_ID: {
+ viz::SubtreeCaptureId capture_id;
+ if (!data.ReadSubtreeCaptureId(&capture_id) || !capture_id.is_valid())
+ return false;
+
+ *out = capture_id;
+ return true;
+ }
+ }
+
+ NOTREACHED();
+ return false;
+ }
+};
+
+template <>
+struct StructTraits<viz::mojom::VideoCaptureTargetDataView,
+ viz::VideoCaptureTarget> {
+ static viz::FrameSinkId frame_sink_id(const viz::VideoCaptureTarget& input) {
+ return input.frame_sink_id;
+ }
+
+ static const viz::VideoCaptureSubTarget& sub_target(
+ const viz::VideoCaptureTarget& input) {
+ return input.sub_target;
+ }
+
+ static bool Read(viz::mojom::VideoCaptureTargetDataView data,
+ viz::VideoCaptureTarget* out) {
+ viz::VideoCaptureTarget target;
+ if (!data.ReadSubTarget(&target.sub_target) ||
+ !data.ReadFrameSinkId(&target.frame_sink_id))
+ return false;
+
+ if (!target.frame_sink_id.is_valid())
+ return false;
+
+ *out = std::move(target);
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VIDEO_CAPTURE_TARGET_MOJOM_TRAITS_H_
diff --git a/chromium/services/viz/public/cpp/gpu/BUILD.gn b/chromium/services/viz/public/cpp/gpu/BUILD.gn
index 7a95c61fb1b..59c2d323d71 100644
--- a/chromium/services/viz/public/cpp/gpu/BUILD.gn
+++ b/chromium/services/viz/public/cpp/gpu/BUILD.gn
@@ -67,8 +67,4 @@ source_set("tests") {
"//ui/gfx/geometry",
"//ui/gfx/geometry/mojom",
]
-
- if (use_x11) {
- deps += [ "//ui/gfx/x" ]
- }
}
diff --git a/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.cc b/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.cc
index cc34bf69924..562165c62ba 100644
--- a/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.cc
+++ b/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.cc
@@ -8,8 +8,8 @@
#include "base/bind.h"
#include "base/check_op.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/single_thread_task_runner.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "mojo/public/cpp/system/buffer.h"
diff --git a/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.h b/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.h
index cd999abd436..22847985036 100644
--- a/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.h
+++ b/chromium/services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.h
@@ -9,7 +9,6 @@
#include <set>
#include <vector>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/unsafe_shared_memory_pool.h"
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 22d80baf765..71e90c6fb62 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
@@ -11,9 +11,10 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
-#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/trace_event/memory_dump_provider.h"
#include "components/viz/common/gpu/context_provider.h"
@@ -148,7 +149,7 @@ class ContextProviderCommandBuffer
const command_buffer_metrics::ContextType context_type_;
scoped_refptr<gpu::GpuChannelHost> channel_;
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
+ raw_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
// |shared_image_interface_| must be torn down after |command_buffer_| to
@@ -162,7 +163,7 @@ class ContextProviderCommandBuffer
std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
// Owned by either gles2_impl_ or raster_interface_, not both.
- gpu::ImplementationBase* impl_;
+ raw_ptr<gpu::ImplementationBase> impl_;
std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_;
std::unique_ptr<gpu::gles2::GLES2TraceImplementation> trace_impl_;
std::unique_ptr<gpu::raster::RasterInterface> raster_interface_;
diff --git a/chromium/services/viz/public/cpp/gpu/gpu.cc b/chromium/services/viz/public/cpp/gpu/gpu.cc
index 5647cf39de8..78462d5402c 100644
--- a/chromium/services/viz/public/cpp/gpu/gpu.cc
+++ b/chromium/services/viz/public/cpp/gpu/gpu.cc
@@ -10,6 +10,8 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
+#include "base/metrics/histogram_macros.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -101,6 +103,9 @@ class Gpu::EstablishRequest
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
: parent_(parent), main_task_runner_(main_task_runner) {}
+ EstablishRequest(const EstablishRequest&) = delete;
+ EstablishRequest& operator=(const EstablishRequest&) = delete;
+
const scoped_refptr<gpu::GpuChannelHost>& gpu_channel() {
return gpu_channel_;
}
@@ -195,17 +200,15 @@ class Gpu::EstablishRequest
virtual ~EstablishRequest() = default;
- Gpu* const parent_;
+ const raw_ptr<Gpu> parent_;
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
- base::WaitableEvent* establish_event_ = nullptr;
+ raw_ptr<base::WaitableEvent> establish_event_ = nullptr;
base::Lock lock_;
bool received_ = false;
bool finished_ = false;
scoped_refptr<gpu::GpuChannelHost> gpu_channel_;
-
- DISALLOW_COPY_AND_ASSIGN(EstablishRequest);
};
void Gpu::GpuPtrIO::ConnectionError() {
@@ -331,6 +334,7 @@ scoped_refptr<gpu::GpuChannelHost> Gpu::EstablishGpuChannelSync() {
if (channel)
return channel;
+ SCOPED_UMA_HISTOGRAM_TIMER("GPU.EstablishGpuChannelSyncTime");
SendEstablishGpuChannelRequest();
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::SIGNALED);
diff --git a/chromium/services/viz/public/cpp/gpu/gpu.h b/chromium/services/viz/public/cpp/gpu/gpu.h
index 53823536a2f..02b42561ac1 100644
--- a/chromium/services/viz/public/cpp/gpu/gpu.h
+++ b/chromium/services/viz/public/cpp/gpu/gpu.h
@@ -8,9 +8,8 @@
#include <stdint.h>
#include <vector>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
#include "build/chromeos_buildflags.h"
#include "components/viz/common/gpu/context_provider.h"
#include "gpu/ipc/client/gpu_channel_host.h"
diff --git a/chromium/services/viz/public/mojom/BUILD.gn b/chromium/services/viz/public/mojom/BUILD.gn
index 355cd7e0431..7411af80294 100644
--- a/chromium/services/viz/public/mojom/BUILD.gn
+++ b/chromium/services/viz/public/mojom/BUILD.gn
@@ -1,10 +1,8 @@
# 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/config/chromeos/ui_mode.gni")
import("//mojo/public/tools/bindings/mojom.gni")
-
mojom("mojom") {
generate_java = true
sources = [
@@ -29,10 +27,12 @@ mojom("mojom") {
"compositing/local_surface_id.mojom",
"compositing/paint_filter.mojom",
"compositing/quads.mojom",
+ "compositing/region_capture_bounds.mojom",
"compositing/resource_id.mojom",
"compositing/resource_settings.mojom",
"compositing/returned_resource.mojom",
"compositing/selection.mojom",
+ "compositing/shared_element_resource_id.mojom",
"compositing/shared_quad_state.mojom",
"compositing/subtree_capture_id.mojom",
"compositing/surface_id.mojom",
@@ -47,7 +47,6 @@ mojom("mojom") {
"hit_test/hit_test_region_list.mojom",
"hit_test/input_target_client.mojom",
]
-
public_deps = [
":resource_format",
"//gpu/ipc/common:interfaces",
@@ -59,15 +58,12 @@ mojom("mojom") {
"//ui/gl/mojom",
"//ui/latency/mojom",
]
-
if (is_chromeos_ash) {
public_deps += [ "//components/chromeos_camera/common" ]
}
-
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"
-
shared_cpp_typemaps = [
{
types = [
@@ -106,6 +102,20 @@ mojom("mojom") {
{
types = [
{
+ mojom = "viz.mojom.RegionCaptureBounds"
+ cpp = "::viz::RegionCaptureBounds"
+ },
+ {
+ mojom = "map"
+ cpp = "base::flat_map"
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/region_capture_bounds_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
+ {
+ types = [
+ {
mojom = "viz.mojom.ReturnedResource"
cpp = "::viz::ReturnedResource"
move_only = true
@@ -173,8 +183,25 @@ mojom("mojom") {
traits_headers = [ "//services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h" ]
traits_public_deps = [ "//components/viz/common" ]
},
+ {
+ types = [
+ {
+ mojom = "viz.mojom.VideoCaptureTarget"
+ cpp = "::viz::VideoCaptureTarget"
+ },
+ {
+ mojom = "viz.mojom.VideoCaptureSubTarget"
+ cpp = "::viz::VideoCaptureSubTarget"
+ nullable_is_same_type = true
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h" ]
+ traits_public_deps = [
+ "//components/viz/common",
+ "//ui/gfx/geometry/mojom",
+ ]
+ },
]
-
cpp_typemaps = shared_cpp_typemaps
cpp_typemaps += [
{
@@ -416,6 +443,16 @@ mojom("mojom") {
{
types = [
{
+ mojom = "viz.mojom.SharedElementResourceId"
+ cpp = "::viz::SharedElementResourceId"
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/shared_element_resource_id_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
+ {
+ types = [
+ {
mojom = "viz.mojom.BufferUsageAndFormat"
cpp = "::std::pair<::gfx::BufferUsage, gfx::BufferFormat>"
},
@@ -468,7 +505,6 @@ mojom("mojom") {
]
},
]
-
blink_cpp_typemaps = shared_cpp_typemaps
blink_cpp_typemaps += [
{
@@ -570,7 +606,6 @@ mojom("mojom") {
},
]
}
-
mojom("resource_format") {
generate_java = true
sources = [ "compositing/resource_format.mojom" ]
diff --git a/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom b/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom
index 31d37377b1c..f78225cee35 100644
--- a/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom
+++ b/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom
@@ -9,6 +9,7 @@ import "services/viz/public/mojom/compositing/begin_frame_args.mojom";
import "services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom";
import "ui/gfx/mojom/delegated_ink_metadata.mojom";
import "services/viz/public/mojom/compositing/frame_deadline.mojom";
+import "services/viz/public/mojom/compositing/region_capture_bounds.mojom";
import "services/viz/public/mojom/compositing/selection.mojom";
import "services/viz/public/mojom/compositing/surface_id.mojom";
import "services/viz/public/mojom/compositing/surface_range.mojom";
@@ -22,7 +23,7 @@ import "ui/latency/mojom/latency_info.mojom";
// compositor in the GPU process.
struct CompositorFrameMetadata {
float device_scale_factor;
- gfx.mojom.Vector2dF root_scroll_offset;
+ gfx.mojom.PointF root_scroll_offset;
float page_scale_factor;
gfx.mojom.SizeF scrollable_viewport_size;
gfx.mojom.ContentColorUsage content_color_usage;
@@ -67,4 +68,13 @@ struct CompositorFrameMetadata {
// Transition directives represent a list of directives for animating a
// transition between different compositor frames / render passes.
array<CompositorFrameTransitionDirective> transition_directives;
+
+ // Contains a map of region capture crop identifiers to gfx::Rects
+ // representing their coordinates in the root render pass system.
+ RegionCaptureBounds capture_bounds;
+
+ // Indicates if this frame is embedding SharedElementResourceIds which need to
+ // be replaced by corresponding live render passes or cached textures in the
+ // Viz process.
+ bool has_shared_element_resources;
};
diff --git a/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom b/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom
index ca6fa9ca8ce..8a950134efd 100644
--- a/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom
+++ b/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom
@@ -93,6 +93,12 @@ interface CompositorFrameSink {
// the value has been set to anything other than kUnspecified, subsequent calls
// are silently ignored.
InitializeCompositorFrameSinkType(CompositorFrameSinkType type);
+
+ // Informs the display compositor the IDs of the thread involved in frame
+ // production. This is used on Android PerformanceHint API to dynamically
+ // adjust performance to allow power saving.
+ [EnableIf=is_android]
+ SetThreadIds(array<int32> thread_ids);
};
interface CompositorFrameSinkClient {
diff --git a/chromium/services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom b/chromium/services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom
index 7def89d46e9..02e96e78106 100644
--- a/chromium/services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom
+++ b/chromium/services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom
@@ -6,10 +6,13 @@ module viz.mojom;
import "mojo/public/mojom/base/time.mojom";
import "services/viz/public/mojom/compositing/compositor_render_pass_id.mojom";
+import "services/viz/public/mojom/compositing/shared_element_resource_id.mojom";
enum CompositorFrameTransitionDirectiveType {
kSave,
- kAnimate
+ kAnimate,
+ kAnimateRenderer,
+ kRelease
};
enum CompositorFrameTransitionDirectiveEffect {
@@ -37,6 +40,7 @@ struct CompositorFrameTransitionDirectiveConfig {
struct CompositorFrameTransitionDirectiveSharedElement {
CompositorRenderPassId render_pass_id;
CompositorFrameTransitionDirectiveConfig config;
+ SharedElementResourceId shared_element_resource_id;
};
// See components/viz/common/quads/compositor_frame_transition_directive.h
diff --git a/chromium/services/viz/public/mojom/compositing/compositor_render_pass.mojom b/chromium/services/viz/public/mojom/compositing/compositor_render_pass.mojom
index 05669c045aa..43a5756f674 100644
--- a/chromium/services/viz/public/mojom/compositing/compositor_render_pass.mojom
+++ b/chromium/services/viz/public/mojom/compositing/compositor_render_pass.mojom
@@ -8,6 +8,7 @@ import "services/viz/public/mojom/compositing/compositor_render_pass_id.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/shared_element_resource_id.mojom";
import "services/viz/public/mojom/compositing/subtree_capture_id.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/gfx/mojom/rrect_f.mojom";
@@ -24,6 +25,7 @@ struct CompositorRenderPass {
gfx.mojom.RRectF? backdrop_filter_bounds;
SubtreeCaptureId subtree_capture_id;
gfx.mojom.Size subtree_size;
+ SharedElementResourceId shared_element_resource_id;
bool has_transparent_background;
bool cache_render_pass = false;
bool has_damage_from_contributing_content = false;
diff --git a/chromium/services/viz/public/mojom/compositing/frame_sink_bundle.mojom b/chromium/services/viz/public/mojom/compositing/frame_sink_bundle.mojom
index b39118be798..7374299759b 100644
--- a/chromium/services/viz/public/mojom/compositing/frame_sink_bundle.mojom
+++ b/chromium/services/viz/public/mojom/compositing/frame_sink_bundle.mojom
@@ -71,6 +71,11 @@ interface FrameSinkBundle {
DidAllocateSharedBitmap(
uint32 sink_id, mojo_base.mojom.ReadOnlySharedMemoryRegion region,
gpu.mojom.Mailbox id);
+
+ // Corresponds to a single message of the same name on CompositorFrameSink
+ // for the identified sink.
+ [EnableIf=is_android]
+ SetThreadIds(uint32 sink_id, array<int32> thread_ids);
};
// A set of ReturnedResources belonging to a specific frame sink.
diff --git a/chromium/services/viz/public/mojom/compositing/quads.mojom b/chromium/services/viz/public/mojom/compositing/quads.mojom
index 20f16397f12..12d4219dfbc 100644
--- a/chromium/services/viz/public/mojom/compositing/quads.mojom
+++ b/chromium/services/viz/public/mojom/compositing/quads.mojom
@@ -7,6 +7,7 @@ module viz.mojom;
import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/viz/public/mojom/compositing/compositor_render_pass_id.mojom";
import "services/viz/public/mojom/compositing/resource_id.mojom";
+import "services/viz/public/mojom/compositing/shared_element_resource_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";
@@ -96,7 +97,6 @@ struct TextureQuadState {
bool secure_output_only;
bool is_video_frame;
ProtectedVideoState protected_video_type;
- uint32 hw_protected_validation_id;
gfx.mojom.Rect? damage_rect;
OverlayPriority overlay_priority_hint;
};
@@ -132,6 +132,10 @@ struct VideoHoleQuadState {
mojo_base.mojom.UnguessableToken overlay_plane_id;
};
+struct SharedElementQuadState {
+ SharedElementResourceId resource_id;
+};
+
union DrawQuadState {
DebugBorderQuadState debug_border_quad_state;
CompositorRenderPassQuadState render_pass_quad_state;
@@ -142,6 +146,7 @@ union DrawQuadState {
TileQuadState tile_quad_state;
YUVVideoQuadState yuv_video_quad_state;
VideoHoleQuadState video_hole_quad_state;
+ SharedElementQuadState shared_element_quad_state;
};
struct DrawQuad {
diff --git a/chromium/services/viz/public/mojom/compositing/region_capture_bounds.mojom b/chromium/services/viz/public/mojom/compositing/region_capture_bounds.mojom
new file mode 100644
index 00000000000..8d9528f1852
--- /dev/null
+++ b/chromium/services/viz/public/mojom/compositing/region_capture_bounds.mojom
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module viz.mojom;
+
+import "ui/gfx/geometry/mojom/geometry.mojom";
+import "mojo/public/mojom/base/token.mojom";
+
+// NOTE: we use a CropIdBoundsPair instead of a map below due to our need
+// to serialize to blink objects, where WTF::HashMap only allows a very
+// limited set of objects to be used as a key. The pair includes a crop id
+// corresponding to an HTMLElement that has region capture data, and its
+// associated bounds translated to the coordinate space of the outputted
+// pixels.
+struct CropIdBoundsPair {
+ // The crop id is represented over mojom as a base::Token, although
+ // in practice it is generated as a GUID. Since these are consumed only
+ // internally in Chrome, we use base::Token for the representation.
+ mojo_base.mojom.Token crop_id;
+ gfx.mojom.Rect bounds;
+};
+
+// RegionCaptureBounds are used for passing in region capture crop ids mapped
+// to a gfx::Rect representing the region of the viewport that should be cropped
+// to for tab capture. Per the specification (draft) at:
+// https://eladalon1983.github.io/region-capture/, these crop identifiers are
+// GUIDs generated by calling the mediaDevices.produceCropId() API on HTML
+// elements.
+// The crop ID and bounds are stored internally in Blink and are passed to and
+// tracked by the compositor/viz. If a previously-generated crop ID is selected
+// via mediaStreamTrack.cropTo(), the frame sink video capturer uses the crop
+// IDs associated with the compositor render passes to determine what section of
+// the frame should be cropped out when applying copy output requests.
+struct RegionCaptureBounds {
+ array<CropIdBoundsPair> bounds;
+};
diff --git a/chromium/services/viz/public/mojom/compositing/shared_element_resource_id.mojom b/chromium/services/viz/public/mojom/compositing/shared_element_resource_id.mojom
new file mode 100644
index 00000000000..f062bc0cb35
--- /dev/null
+++ b/chromium/services/viz/public/mojom/compositing/shared_element_resource_id.mojom
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module viz.mojom;
+
+// An identifier for a texture representing the content of a shared element. The
+// id is created in the renderer process and used to embed this content in
+// CompositorFrames. Viz scopes the access to this resource to the renderer
+// process which created it.
+//
+// This ID is created by the renderer process and shared with the Viz process in
+// CompositorFrames. Its usage is scoped to a single CompositorFrameSink IPC
+// interface. This means that the ID is created and used by a single renderer
+// process. The content cached for one renderer process can not be embedded in
+// frames generated by a different renderer process.
+//
+// TODO(khushalsagar): This ID must be unguessable if shared between renderer
+// processes.
+struct SharedElementResourceId {
+ uint32 id;
+};