summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform')
-rw-r--r--chromium/third_party/blink/renderer/platform/BUILD.gn236
-rw-r--r--chromium/third_party/blink/renderer/platform/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/platform/PRESUBMIT.py10
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/timing_function.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/timing_function.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc61
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination.cc144
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_source_provider_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_frame.cc78
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_frame.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.cc122
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.h70
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/panner.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/panner.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h92
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc189
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.h134
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_state.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h129
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/to_v8.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/union_base.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_binding.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_binding_macros.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc96
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h65
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h99
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc61
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h336
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_value_or_script_wrappable_adapter.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/content_decryption_module_result.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/context_lifecycle_notifier.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/context_lifecycle_observer.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/context_lifecycle_observer.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/crypto_result.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/cursor.cc316
-rw-r--r--chromium/third_party/blink/renderer/platform/cursor.h131
-rw-r--r--chromium/third_party/blink/renderer/platform/cursors.cc290
-rw-r--r--chromium/third_party/blink/renderer/platform/cursors.h88
-rw-r--r--chromium/third_party/blink/renderer/platform/disk_data_allocator.cc206
-rw-r--r--chromium/third_party/blink/renderer/platform/disk_data_allocator.h116
-rw-r--r--chromium/third_party/blink/renderer/platform/disk_data_allocator_test.cc266
-rw-r--r--chromium/third_party/blink/renderer/platform/disk_data_allocator_test_utils.h66
-rw-r--r--chromium/third_party/blink/renderer/platform/encrypted_media_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/platform.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/url_conversion.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_failing_url_loader_factory.cc88
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_font.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_gesture_event.cc155
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_http_body.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_input_event.cc83
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_isolate.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_media_stream_audio_sink.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_media_stream_source.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_media_stream_track.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_mouse_event.cc69
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_mouse_wheel_event.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_pointer_event.cc101
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_prerender.cc132
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc99
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc128
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_rtc_peer_connection_handler_client.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_rtc_stats.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc93
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_touch_event.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_error.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_load_timing.cc216
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_request.cc131
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_request_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_response.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/file_metadata.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc75
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_data.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_data_cache.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc74
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h50
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_global_context.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_selector.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_selector_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm62
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm129
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc258
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h120
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support_test.cc466
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc156
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc92
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc223
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h59
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc264
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h91
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_point.h53
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_rect.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_rect.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_size.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_unit.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_unit_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/length.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/length_functions.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/length_size.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/region.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/region.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc452
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h180
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc116
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc99
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc129
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc127
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc544
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h84
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc230
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/README.md2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc729
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h94
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc1827
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc125
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc641
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc374
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h70
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc36
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/generated_image.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/generated_image.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc219
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc86
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc43
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc82
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc110
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc180
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h46
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc312
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.h68
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc274
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h64
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h55
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc135
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc196
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h83
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc49
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h52
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h50
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/README.md7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h59
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc117
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h37
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc412
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc63
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc103
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h88
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc143
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h49
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc422
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc342
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h161
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc80
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc189
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h58
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc61
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc64
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc459
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_hint.h74
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc80
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h88
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc36
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc155
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc149
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h60
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h84
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/texture_holder.h85
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc100
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc102
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BUILD.gn52
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/asm/BUILD.gn24
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/card_table_test.cc181
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h315
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h (renamed from chromium/third_party/blink/renderer/platform/heap/heap_linked_stack.h)51
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h203
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/concurrent_marking_test.cc501
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/garbage_collected.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/gc_info.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/gc_info.h118
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/gc_info_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap.cc297
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap.h201
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_allocator.h371
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc149
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_page.cc235
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_page.h409
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h164
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc141
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test.cc464
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_traits_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc466
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_verifier.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_verifier.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc160
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_visitor.h123
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/member.h68
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/minor_gc_test.cc295
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/page_memory.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/page_memory.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_node.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_node.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state.cc319
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state.h97
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state_scopes.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/threading_traits.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/trace_traits.h408
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.cc63
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.h61
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/visitor.h142
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/weakness_marking_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/worklist.h77
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/worklist_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/heap_observer_list.h91
-rw-r--r--chromium/third_party/blink/renderer/platform/heap_observer_list_test.cc165
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/image-encoders/image_encoder_utils.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc73
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc192
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_notifier.h185
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_observer.h81
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/DEPS9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc82
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc60
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc362
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc84
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc175
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc202
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h164
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc60
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc353
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/media/web_audio_source_provider_client.h40
-rw-r--r--chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc75
-rw-r--r--chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/audio_service_audio_processor_proxy.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_constraints.cc (renamed from chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc)246
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_constraints.h326
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h158
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc (renamed from chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_track.cc)52
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h126
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc56
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/big_string.typemap11
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni22
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/geometry.typemap44
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.cc73
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.h68
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc180
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h94
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h94
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc179
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc176
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h95
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_test.cc181
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h96
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc214
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/kurl.typemap18
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/security_origin.typemap17
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/network/BUILD.gn21
-rw-r--r--chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_header_set.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_names.json54
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/network/mime/content_type.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/network/mime/content_type.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc137
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h84
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc105
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.cc191
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h93
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer_test.cc140
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h94
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h174
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc90
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h65
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc132
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc80
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map.h75
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink_test.cc126
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/platform.gni5
-rw-r--r--chromium/third_party/blink/renderer/platform/prerender.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/prerender.h108
-rw-r--r--chromium/third_party/blink/renderer/platform/prerender_client.h54
-rw-r--r--chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5485
-rw-r--r--chromium/third_party/blink/renderer/platform/runtime_enabled_features_test.cc275
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn18
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/features.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/features.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/worker_pool.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc87
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc174
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc376
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_status.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc118
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h56
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc588
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc113
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h37
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/worker_pool.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc121
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/supplementable.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc102
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/text/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/text/icu_error.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_icu.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_mac.mm3
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_mac_test.mm12
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_win.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/text/locale_win_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_direction.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/theme_types.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/timer_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transform_operation.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/reporting_disposition.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc114
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.h40
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc137
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc91
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc61
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/frame_widget.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/frame_widget.h81
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/widget_base.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/widget_base.h75
-rw-r--r--chromium/third_party/blink/renderer/platform/widget/widget_base_client.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/BUILD.gn18
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.cc54
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h218
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/atomic_operations_test.cc139
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc137
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/bit_field.h153
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/bit_field_test.cc105
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/construct_traits.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/cross_thread_functional.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/deque.h53
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_map.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_set.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_table.h164
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_traits.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h511
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc463
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h166
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc98
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/lru_cache.h148
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/lru_cache_test.cc110
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_interval.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h221
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/sanitizers.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/stack_util.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/testing/run_all_tests.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector.h153
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h597
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list_test.cc508
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h71
898 files changed, 31159 insertions, 17717 deletions
diff --git a/chromium/third_party/blink/renderer/platform/BUILD.gn b/chromium/third_party/blink/renderer/platform/BUILD.gn
index 2cdb42f959b..6658b51a7d0 100644
--- a/chromium/third_party/blink/renderer/platform/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/buildflag_header.gni")
import("//build/compiled_action.gni")
+import("//build/config/compiler/compiler.gni")
import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
@@ -66,14 +67,10 @@ blink_python_runner("color_data") {
script = "../build/scripts/gperf.py"
color_data_gperf = "color_data.gperf"
- inputs = [
- color_data_gperf,
- ]
+ inputs = [ color_data_gperf ]
output_file = "$blink_platform_output_dir/color_data.cc"
- outputs = [
- output_file,
- ]
+ outputs = [ output_file ]
args = [
gperf_exe,
@@ -88,9 +85,7 @@ blink_python_runner("color_data") {
compiled_action("character_data") {
tool = ":character_data_generator"
- outputs = [
- "$blink_platform_output_dir/character_property_data.cc",
- ]
+ outputs = [ "$blink_platform_output_dir/character_property_data.cc" ]
args = rebase_path(outputs, root_build_dir)
}
@@ -150,6 +145,7 @@ group("blink_platform_public_deps") {
"//gpu/command_buffer/client:client",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/common:common",
+ "//gpu/command_buffer/common:gles2_utils",
"//net",
"//services/device/public/mojom:generic_sensor_blink",
"//services/device/public/mojom:mojom_blink",
@@ -185,6 +181,9 @@ group("blink_platform_public_deps") {
declare_args() {
runtime_call_stats_count_everything = false
+
+ # Enable TRACE_EVENT instrumentation for Blink bindings. Disabled by default as it increases binary size.
+ enable_blink_bindings_tracing = false
}
buildflag_header("bindings_buildflags") {
@@ -192,8 +191,9 @@ buildflag_header("bindings_buildflags") {
header_dir = "third_party/blink/renderer/platform/bindings"
flags = [
- "RAW_HEAP_SNAPSHOTS=$v8_enable_raw_heap_snapshots",
+ "RAW_HEAP_SNAPSHOTS=$enable_additional_blink_object_names",
"RCS_COUNT_EVERYTHING=$runtime_call_stats_count_everything",
+ "BLINK_BINDINGS_TRACE_ENABLED=$enable_blink_bindings_tracing",
]
}
@@ -225,9 +225,7 @@ config("blink_platform_pch") {
}
source_set("platform_export") {
- sources = [
- "platform_export.h",
- ]
+ sources = [ "platform_export.h" ]
visibility = [] # Allow re-assignment of list.
visibility = [
@@ -362,8 +360,6 @@ jumbo_component("platform") {
"audio/mac/vector_math_mac.h",
"audio/media_multi_channel_resampler.cc",
"audio/media_multi_channel_resampler.h",
- "audio/multi_channel_resampler.cc",
- "audio/multi_channel_resampler.h",
"audio/panner.cc",
"audio/panner.h",
"audio/pffft/fft_frame_pffft.cc",
@@ -394,6 +390,8 @@ jumbo_component("platform") {
"bindings/active_script_wrappable_base.h",
"bindings/binding_security_for_platform.cc",
"bindings/binding_security_for_platform.h",
+ "bindings/blink_isolate/blink_isolate.cc",
+ "bindings/blink_isolate/blink_isolate.h",
"bindings/callback_function_base.cc",
"bindings/callback_function_base.h",
"bindings/callback_interface_base.cc",
@@ -406,6 +404,7 @@ jumbo_component("platform") {
"bindings/dom_data_store.h",
"bindings/dom_wrapper_world.cc",
"bindings/dom_wrapper_world.h",
+ "bindings/enumeration_base.h",
"bindings/exception_code.h",
"bindings/exception_messages.cc",
"bindings/exception_messages.h",
@@ -430,7 +429,6 @@ jumbo_component("platform") {
"bindings/script_state.h",
"bindings/script_wrappable.cc",
"bindings/script_wrappable.h",
- "bindings/shared_persistent.h",
"bindings/string_resource.cc",
"bindings/string_resource.h",
"bindings/to_v8.h",
@@ -438,17 +436,21 @@ jumbo_component("platform") {
"bindings/trace_wrapper_v8_reference.h",
"bindings/trace_wrapper_v8_string.cc",
"bindings/trace_wrapper_v8_string.h",
+ "bindings/union_base.h",
"bindings/v0_custom_element_binding.cc",
"bindings/v0_custom_element_binding.h",
"bindings/v8_binding.cc",
"bindings/v8_binding.h",
"bindings/v8_binding_macros.h",
"bindings/v8_cross_origin_callback_info.h",
+ "bindings/v8_cross_origin_property_support.cc",
+ "bindings/v8_cross_origin_property_support.h",
"bindings/v8_dom_activity_logger.cc",
"bindings/v8_dom_activity_logger.h",
"bindings/v8_dom_wrapper.cc",
"bindings/v8_dom_wrapper.h",
"bindings/v8_global_value_map.h",
+ "bindings/v8_interface_bridge.h",
"bindings/v8_object_constructor.cc",
"bindings/v8_object_constructor.h",
"bindings/v8_per_context_data.cc",
@@ -457,6 +459,8 @@ jumbo_component("platform") {
"bindings/v8_per_isolate_data.h",
"bindings/v8_private_property.cc",
"bindings/v8_private_property.h",
+ "bindings/v8_set_return_value.cc",
+ "bindings/v8_set_return_value.h",
"bindings/v8_throw_exception.cc",
"bindings/v8_throw_exception.h",
"bindings/v8_value_cache.cc",
@@ -466,6 +470,9 @@ jumbo_component("platform") {
"bindings/wrapper_type_info.cc",
"bindings/wrapper_type_info.h",
"content_decryption_module_result.h",
+ "context_lifecycle_notifier.h",
+ "context_lifecycle_observer.cc",
+ "context_lifecycle_observer.h",
"cookie/canonical_cookie.cc",
"cookie/canonical_cookie.h",
"cookie/canonical_cookie_mojom_traits.cc",
@@ -474,13 +481,14 @@ jumbo_component("platform") {
"crypto.cc",
"crypto.h",
"crypto_result.h",
- "cursor.cc",
- "cursor.h",
+ "cursors.cc",
+ "cursors.h",
"data_resource_helper.cc",
"data_resource_helper.h",
+ "disk_data_allocator.cc",
+ "disk_data_allocator.h",
"exported/file_path_conversion.cc",
"exported/interface_registry.cc",
- "exported/mediastream/media_stream_audio_track.cc",
"exported/mediastream/web_media_element_source_utils.cc",
"exported/mediastream/web_platform_media_stream_source.cc",
"exported/mediastream/web_platform_media_stream_track.cc",
@@ -500,21 +508,19 @@ jumbo_component("platform") {
"exported/web_crypto_key.cc",
"exported/web_crypto_key_algorithm.cc",
"exported/web_crypto_result.cc",
- "exported/web_cursor_info.cc",
"exported/web_data.cc",
"exported/web_drag_data.cc",
"exported/web_encrypted_media_client.cc",
"exported/web_encrypted_media_key_information.cc",
"exported/web_encrypted_media_request.cc",
+ "exported/web_failing_url_loader_factory.cc",
"exported/web_font.cc",
"exported/web_font_description.cc",
- "exported/web_gesture_event.cc",
"exported/web_http_body.cc",
"exported/web_http_load_info.cc",
"exported/web_icon_sizes_parser.cc",
"exported/web_image_generator.cc",
- "exported/web_input_event.cc",
- "exported/web_media_constraints.cc",
+ "exported/web_isolate.cc",
"exported/web_media_player_client.cc",
"exported/web_media_player_encrypted_media_client.cc",
"exported/web_media_player_source.cc",
@@ -524,15 +530,7 @@ jumbo_component("platform") {
"exported/web_media_stream_track.cc",
"exported/web_memory_pressure_listener.cc",
"exported/web_mixed_content.cc",
- "exported/web_mouse_event.cc",
- "exported/web_mouse_wheel_event.cc",
"exported/web_network_state_notifier.cc",
- "exported/web_pointer_event.cc",
- "exported/web_prerender.cc",
- "exported/web_prerendering_support.cc",
- "exported/web_resource_timing_info.cc",
- "exported/web_rtc_peer_connection_handler_client.cc",
- "exported/web_rtc_stats.cc",
"exported/web_runtime_features.cc",
"exported/web_security_origin.cc",
"exported/web_string.cc",
@@ -541,10 +539,8 @@ jumbo_component("platform") {
"exported/web_text_run.cc",
"exported/web_thread_safe_data.cc",
"exported/web_time_range.cc",
- "exported/web_touch_event.cc",
"exported/web_url.cc",
"exported/web_url_error.cc",
- "exported/web_url_load_timing.cc",
"exported/web_url_loader_client.cc",
"exported/web_url_loader_test_delegate.cc",
"exported/web_url_request.cc",
@@ -643,6 +639,9 @@ jumbo_component("platform") {
"fonts/opentype/open_type_caps_support.cc",
"fonts/opentype/open_type_caps_support.h",
"fonts/opentype/open_type_caps_support_mpl.cc",
+ "fonts/opentype/open_type_math_stretch_data.h",
+ "fonts/opentype/open_type_math_support.cc",
+ "fonts/opentype/open_type_math_support.h",
"fonts/opentype/open_type_types.h",
"fonts/opentype/open_type_vertical_data.cc",
"fonts/opentype/open_type_vertical_data.h",
@@ -684,6 +683,8 @@ jumbo_component("platform") {
"fonts/shaping/shape_result_view.h",
"fonts/shaping/shaping_line_breaker.cc",
"fonts/shaping/shaping_line_breaker.h",
+ "fonts/shaping/stretchy_operator_shaper.cc",
+ "fonts/shaping/stretchy_operator_shaper.h",
"fonts/simple_font_data.cc",
"fonts/simple_font_data.h",
"fonts/skia/font_cache_skia.cc",
@@ -719,8 +720,6 @@ jumbo_component("platform") {
"fonts/win/dwrite_font_format_support.h",
"fonts/win/fallback_family_style_cache_win.cc",
"fonts/win/fallback_family_style_cache_win.h",
- "fonts/win/fallback_lru_cache_win.cc",
- "fonts/win/fallback_lru_cache_win.h",
"fonts/win/font_cache_skia_win.cc",
"fonts/win/font_fallback_win.cc",
"fonts/win/font_fallback_win.h",
@@ -951,6 +950,8 @@ jumbo_component("platform") {
"graphics/gpu/shared_gpu_context.h",
"graphics/gpu/webgl_image_conversion.cc",
"graphics/gpu/webgl_image_conversion.h",
+ "graphics/gpu/webgpu_image_bitmap_handler.cc",
+ "graphics/gpu/webgpu_image_bitmap_handler.h",
"graphics/gpu/webgpu_swap_buffer_provider.cc",
"graphics/gpu/webgpu_swap_buffer_provider.h",
"graphics/gpu/xr_frame_transport.cc",
@@ -974,8 +975,6 @@ jumbo_component("platform") {
"graphics/graphics_types.cc",
"graphics/graphics_types.h",
"graphics/graphics_types_3d.h",
- "graphics/hit_test_rect.cc",
- "graphics/hit_test_rect.h",
"graphics/image.cc",
"graphics/image.h",
"graphics/image_animation_policy.h",
@@ -1000,10 +999,12 @@ jumbo_component("platform") {
"graphics/lab_color_space.h",
"graphics/logging_canvas.cc",
"graphics/logging_canvas.h",
- "graphics/mailbox_texture_holder.cc",
- "graphics/mailbox_texture_holder.h",
"graphics/main_thread_mutator_client.cc",
"graphics/main_thread_mutator_client.h",
+ "graphics/memory_managed_paint_canvas.cc",
+ "graphics/memory_managed_paint_canvas.h",
+ "graphics/memory_managed_paint_recorder.cc",
+ "graphics/memory_managed_paint_recorder.h",
"graphics/mutator_client.h",
"graphics/offscreen_canvas_placeholder.cc",
"graphics/offscreen_canvas_placeholder.h",
@@ -1035,10 +1036,10 @@ jumbo_component("platform") {
"graphics/paint/geometry_mapper_clip_cache.h",
"graphics/paint/geometry_mapper_transform_cache.cc",
"graphics/paint/geometry_mapper_transform_cache.h",
+ "graphics/paint/graphics_layer_display_item.cc",
+ "graphics/paint/graphics_layer_display_item.h",
"graphics/paint/hit_test_data.cc",
"graphics/paint/hit_test_data.h",
- "graphics/paint/hit_test_display_item.cc",
- "graphics/paint/hit_test_display_item.h",
"graphics/paint/paint_artifact.cc",
"graphics/paint/paint_artifact.h",
"graphics/paint/paint_canvas.h",
@@ -1067,9 +1068,8 @@ jumbo_component("platform") {
"graphics/paint/raster_invalidator.h",
"graphics/paint/ref_counted_property_tree_state.h",
"graphics/paint/scoped_display_item_fragment.h",
+ "graphics/paint/scoped_paint_chunk_hint.h",
"graphics/paint/scoped_paint_chunk_properties.h",
- "graphics/paint/scroll_hit_test_display_item.cc",
- "graphics/paint/scroll_hit_test_display_item.h",
"graphics/paint/scroll_paint_property_node.cc",
"graphics/paint/scroll_paint_property_node.h",
"graphics/paint/scrollbar_display_item.cc",
@@ -1111,8 +1111,6 @@ jumbo_component("platform") {
"graphics/skia/sk_size_hash.h",
"graphics/skia/skia_utils.cc",
"graphics/skia/skia_utils.h",
- "graphics/skia_texture_holder.cc",
- "graphics/skia_texture_holder.h",
"graphics/squashing_disallowed_reasons.cc",
"graphics/squashing_disallowed_reasons.h",
"graphics/static_bitmap_image.cc",
@@ -1123,8 +1121,9 @@ jumbo_component("platform") {
"graphics/subtree_paint_property_update_reason.h",
"graphics/surface_layer_bridge.cc",
"graphics/surface_layer_bridge.h",
- "graphics/texture_holder.h",
"graphics/touch_action.h",
+ "graphics/touch_action_rect.cc",
+ "graphics/touch_action_rect.h",
"graphics/unaccelerated_static_bitmap_image.cc",
"graphics/unaccelerated_static_bitmap_image.h",
"graphics/video_frame_resource_provider.cc",
@@ -1133,6 +1132,7 @@ jumbo_component("platform") {
"graphics/video_frame_submitter.h",
"graphics/web_graphics_context_3d_provider_wrapper.cc",
"graphics/web_graphics_context_3d_provider_wrapper.h",
+ "heap_observer_list.h",
"image-decoders/bmp/bmp_image_decoder.cc",
"image-decoders/bmp/bmp_image_decoder.h",
"image-decoders/bmp/bmp_image_reader.cc",
@@ -1171,8 +1171,6 @@ jumbo_component("platform") {
"keyboard_codes.h",
"language.cc",
"language.h",
- "lifecycle_notifier.h",
- "lifecycle_observer.h",
"link_hash.cc",
"link_hash.h",
"mac/block_exceptions.h",
@@ -1185,6 +1183,7 @@ jumbo_component("platform") {
"mac/local_current_graphics_context.mm",
"mac/web_core_ns_cell_extras.h",
"mac/web_core_ns_cell_extras.mm",
+ "media/web_audio_source_provider_client.h",
"media/webaudiosourceprovider_impl.cc",
"media_capabilities/web_audio_configuration.h",
"media_capabilities/web_media_capabilities_info.h",
@@ -1194,12 +1193,17 @@ jumbo_component("platform") {
"mediastream/aec_dump_agent_impl.h",
"mediastream/audio_service_audio_processor_proxy.cc",
"mediastream/audio_service_audio_processor_proxy.h",
+ "mediastream/media_constraints.cc",
+ "mediastream/media_constraints.h",
+ "mediastream/media_stream_audio_deliverer.h",
"mediastream/media_stream_audio_level_calculator.cc",
"mediastream/media_stream_audio_level_calculator.h",
"mediastream/media_stream_audio_processor_options.cc",
"mediastream/media_stream_audio_processor_options.h",
"mediastream/media_stream_audio_source.cc",
"mediastream/media_stream_audio_source.h",
+ "mediastream/media_stream_audio_track.cc",
+ "mediastream/media_stream_audio_track.h",
"mediastream/media_stream_component.cc",
"mediastream/media_stream_component.h",
"mediastream/media_stream_descriptor.cc",
@@ -1208,6 +1212,7 @@ jumbo_component("platform") {
"mediastream/media_stream_source.h",
"mediastream/media_stream_web_audio_source.cc",
"mediastream/media_stream_web_audio_source.h",
+ "mediastream/webaudio_destination_consumer.h",
"mediastream/webaudio_media_stream_source.cc",
"mediastream/webaudio_media_stream_source.h",
"mediastream/webrtc_uma_histograms.cc",
@@ -1225,6 +1230,11 @@ jumbo_component("platform") {
"mojo/bluetooth_mojom_traits.cc",
"mojo/bluetooth_mojom_traits.h",
"mojo/fetch_api_request_headers_mojom_traits.h",
+ "mojo/heap_mojo_receiver.h",
+ "mojo/heap_mojo_receiver_set.h",
+ "mojo/heap_mojo_remote.h",
+ "mojo/heap_mojo_unique_receiver_set.h",
+ "mojo/heap_mojo_wrapper_mode.h",
"mojo/kurl_mojom_traits.h",
"mojo/mojo_helper.h",
"mojo/security_origin_mojom_traits.h",
@@ -1260,6 +1270,10 @@ jumbo_component("platform") {
"peerconnection/rtc_api_name.h",
"peerconnection/rtc_dtmf_sender_handler.cc",
"peerconnection/rtc_dtmf_sender_handler.h",
+ "peerconnection/rtc_encoded_audio_stream_transformer.cc",
+ "peerconnection/rtc_encoded_audio_stream_transformer.h",
+ "peerconnection/rtc_encoded_video_stream_transformer.cc",
+ "peerconnection/rtc_encoded_video_stream_transformer.h",
"peerconnection/rtc_event_log_output_sink.h",
"peerconnection/rtc_event_log_output_sink_proxy.cc",
"peerconnection/rtc_event_log_output_sink_proxy.h",
@@ -1267,6 +1281,9 @@ jumbo_component("platform") {
"peerconnection/rtc_ice_candidate_platform.h",
"peerconnection/rtc_legacy_stats.h",
"peerconnection/rtc_offer_options_platform.h",
+ "peerconnection/rtc_peer_connection_handler_client.cc",
+ "peerconnection/rtc_peer_connection_handler_client.h",
+ "peerconnection/rtc_peer_connection_handler_platform.h",
"peerconnection/rtc_rtp_receiver_platform.cc",
"peerconnection/rtc_rtp_receiver_platform.h",
"peerconnection/rtc_rtp_sender_platform.cc",
@@ -1275,6 +1292,7 @@ jumbo_component("platform") {
"peerconnection/rtc_rtp_source.h",
"peerconnection/rtc_rtp_transceiver_platform.cc",
"peerconnection/rtc_rtp_transceiver_platform.h",
+ "peerconnection/rtc_scoped_refptr_cross_thread_copier.h",
"peerconnection/rtc_session_description_platform.cc",
"peerconnection/rtc_session_description_platform.h",
"peerconnection/rtc_session_description_request.h",
@@ -1303,9 +1321,6 @@ jumbo_component("platform") {
"peerconnection/webrtc_util.h",
"peerconnection/webrtc_video_track_source.cc",
"peerconnection/webrtc_video_track_source.h",
- "prerender.cc",
- "prerender.h",
- "prerender_client.h",
"resolution_units.h",
"supplementable.cc",
"supplementable.h",
@@ -1416,6 +1431,7 @@ jumbo_component("platform") {
"weborigin/origin_access_entry.cc",
"weborigin/origin_access_entry.h",
"weborigin/referrer.h",
+ "weborigin/reporting_disposition.h",
"weborigin/scheme_registry.cc",
"weborigin/scheme_registry.h",
"weborigin/security_origin.cc",
@@ -1423,7 +1439,6 @@ jumbo_component("platform") {
"weborigin/security_origin_hash.h",
"weborigin/security_policy.cc",
"weborigin/security_policy.h",
- "weborigin/security_violation_reporting_policy.h",
"webrtc/peer_connection_remote_audio_source.cc",
"webrtc/peer_connection_remote_audio_source.h",
"webrtc/track_observer.cc",
@@ -1434,6 +1449,11 @@ jumbo_component("platform") {
"webrtc/webrtc_video_frame_adapter.h",
"webrtc/webrtc_video_utils.cc",
"webrtc/webrtc_video_utils.h",
+ "widget/frame_widget.cc",
+ "widget/frame_widget.h",
+ "widget/widget_base.cc",
+ "widget/widget_base.h",
+ "widget/widget_base_client.h",
"windows_keyboard_codes.h",
]
@@ -1482,6 +1502,7 @@ jumbo_component("platform") {
public_deps = [
":blink_platform_public_deps",
+ ":platform_export",
"//third_party/blink/renderer/platform/blob",
"//third_party/blink/renderer/platform/heap",
"//third_party/blink/renderer/platform/instrumentation",
@@ -1491,7 +1512,6 @@ jumbo_component("platform") {
"//ui/gfx",
]
deps = [
- ":platform_export",
"//base/allocator:buildflags",
"//cc/ipc",
"//components/paint_preview/common",
@@ -1502,12 +1522,14 @@ jumbo_component("platform") {
"//gin",
"//jingle:webrtc_glue",
"//media",
+ "//media/capture:capture_switches",
"//media/capture/mojom:video_capture",
"//mojo/public/cpp/base",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/bindings:wtf_support",
"//services/service_manager/public/cpp",
"//services/viz/public/cpp/gpu",
+ "//skia",
"//skia:skcms",
"//third_party:freetype_harfbuzz",
"//third_party/abseil-cpp/absl/types:optional",
@@ -1515,13 +1537,17 @@ jumbo_component("platform") {
"//third_party/blink/public/common",
"//third_party/blink/public/mojom:embedded_frame_sink_mojo_bindings_blink",
"//third_party/blink/public/strings",
+ "//third_party/blink/renderer/platform/wtf",
"//third_party/ced",
"//third_party/emoji-segmenter",
+ "//third_party/harfbuzz-ng:hb_scoped_util",
"//third_party/icu",
"//third_party/libyuv",
"//third_party/webrtc_overrides:webrtc_component",
"//third_party/zlib/google:compression_utils",
- "//ui/base:base",
+ "//ui/base/cursor",
+ "//ui/base/mojom:cursor_type_blink",
+ "//ui/events/ipc",
"//ui/gfx/geometry",
"//ui/gfx/mojom",
]
@@ -1597,24 +1623,15 @@ jumbo_component("platform") {
deps += [ "//third_party/pffft" ]
}
+ if (!is_debug && !optimize_for_size) {
+ configs -= [ "//build/config/compiler:default_optimization" ]
+ configs += [ "//build/config/compiler:optimize_max" ]
+ }
+
configs -= [ "//build/config/compiler:default_symbols" ]
configs += blink_symbols_config
}
-source_set("geometry_mojom_traits") {
- visibility += [ "//ui/gfx/geometry/mojom:mojom_blink" ]
-
- sources = [
- "mojo/geometry_mojom_traits.cc",
- "mojo/geometry_mojom_traits.h",
- ]
-
- public_deps = [
- "//third_party/blink/public:blink_headers",
- "//ui/gfx/geometry/mojom:mojom_blink_headers",
- ]
-}
-
jumbo_static_library("test_support") {
visibility += [ "//third_party/blink/*" ]
testonly = true
@@ -1706,6 +1723,7 @@ jumbo_static_library("test_support") {
"//mojo/public/cpp/bindings",
"//services/service_manager/public/cpp",
"//skia",
+ "//third_party/blink/public/common:common",
"//third_party/blink/renderer/platform/blob:test_support",
"//third_party/blink/renderer/platform/heap:test_support",
"//third_party/blink/renderer/platform/loader:test_support",
@@ -1719,9 +1737,7 @@ jumbo_static_library("test_support") {
}
test("blink_platform_unittests") {
- deps = [
- ":blink_platform_unittests_sources",
- ]
+ deps = [ ":blink_platform_unittests_sources" ]
}
jumbo_source_set("blink_platform_unittests_sources") {
@@ -1744,6 +1760,8 @@ jumbo_source_set("blink_platform_unittests_sources") {
"bindings/parkable_string_test.cc",
"bindings/runtime_call_stats_test.cc",
"cookie/canonical_cookie_test.cc",
+ "disk_data_allocator_test.cc",
+ "disk_data_allocator_test_utils.h",
"exported/file_path_conversion_test.cc",
"exported/mediastream/media_stream_audio_test.cc",
"exported/page_zoom_test.cc",
@@ -1765,6 +1783,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"fonts/generic_font_family_settings_test.cc",
"fonts/mac/font_matcher_mac_test.mm",
"fonts/opentype/font_settings_test.cc",
+ "fonts/opentype/open_type_math_support_test.cc",
"fonts/opentype/open_type_vertical_data_test.cc",
"fonts/orientation_iterator_test.cc",
"fonts/script_run_iterator_test.cc",
@@ -1776,6 +1795,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"fonts/shaping/shape_result_test.cc",
"fonts/shaping/shape_result_view_test.cc",
"fonts/shaping/shaping_line_breaker_test.cc",
+ "fonts/shaping/stretchy_operator_shaper_test.cc",
"fonts/small_caps_iterator_test.cc",
"fonts/symbols_iterator_test.cc",
"fonts/typesetting_features_test.cc",
@@ -1817,6 +1837,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"graphics/gpu/drawing_buffer_test.cc",
"graphics/gpu/shared_gpu_context_test.cc",
"graphics/gpu/webgl_image_conversion_test.cc",
+ "graphics/gpu/webgpu_image_bitmap_handler_test.cc",
"graphics/gpu/webgpu_swap_buffer_provider_test.cc",
"graphics/graphics_context_test.cc",
"graphics/lab_color_space_test.cc",
@@ -1836,11 +1857,13 @@ jumbo_source_set("blink_platform_unittests_sources") {
"graphics/paint/paint_property_node_test.cc",
"graphics/paint/paint_record_builder_test.cc",
"graphics/paint/raster_invalidator_test.cc",
+ "graphics/paint/scrollbar_display_item_test.cc",
"graphics/paint_invalidation_reason_test.cc",
"graphics/path_test.cc",
"graphics/placeholder_image_test.cc",
"graphics/static_bitmap_image_test.cc",
"graphics/video_frame_submitter_test.cc",
+ "heap_observer_list_test.cc",
"image-decoders/bmp/bmp_image_decoder_test.cc",
"image-decoders/fast_shared_buffer_reader_test.cc",
"image-decoders/gif/gif_image_decoder_test.cc",
@@ -1857,7 +1880,6 @@ jumbo_source_set("blink_platform_unittests_sources") {
"image-decoders/webp/webp_image_decoder_test.cc",
"json/json_parser_test.cc",
"json/json_values_test.cc",
- "lifecycle_context_test.cc",
"loader/allowed_by_nosniff_test.cc",
"loader/cors/cors_test.cc",
"mac/graphics_context_canvas_test.mm",
@@ -1866,11 +1888,16 @@ jumbo_source_set("blink_platform_unittests_sources") {
"mediastream/webrtc_uma_histograms_test.cc",
"mhtml/mhtml_parser_test.cc",
"mojo/big_string_mojom_traits_test.cc",
- "mojo/geometry_mojom_traits_test.cc",
+ "mojo/heap_mojo_receiver_set_test.cc",
+ "mojo/heap_mojo_receiver_test.cc",
+ "mojo/heap_mojo_remote_test.cc",
+ "mojo/heap_mojo_unique_receiver_set_test.cc",
"mojo/kurl_security_origin_test.cc",
"mojo/string16_mojom_traits_test.cc",
"p2p/filtering_network_manager_test.cc",
"p2p/ipc_network_manager_test.cc",
+ "peerconnection/rtc_encoded_audio_stream_transformer_test.cc",
+ "peerconnection/rtc_encoded_video_stream_transformer_test.cc",
"peerconnection/rtc_stats_test.cc",
"peerconnection/rtc_video_decoder_adapter_test.cc",
"peerconnection/rtc_video_encoder_test.cc",
@@ -1878,7 +1905,9 @@ jumbo_source_set("blink_platform_unittests_sources") {
"peerconnection/task_queue_factory_test.cc",
"peerconnection/transmission_encoding_info_handler_test.cc",
"peerconnection/two_keys_adapter_map_unittest.cc",
+ "peerconnection/webrtc_audio_sink_test.cc",
"peerconnection/webrtc_video_track_source_test.cc",
+ "runtime_enabled_features_test.cc",
"text/bidi_resolver_test.cc",
"text/bidi_test_harness.h",
"text/capitalize_test.cc",
@@ -1913,8 +1942,10 @@ jumbo_source_set("blink_platform_unittests_sources") {
]
if (is_win) {
- sources += [ "text/locale_win_test.cc" ]
- sources += [ "fonts/win/fallback_lru_cache_win_test.cc" ]
+ sources += [
+ "fonts/win/fallback_lru_cache_win_test.cc",
+ "text/locale_win_test.cc",
+ ]
} else if (is_mac) {
sources += [
"fonts/opentype/open_type_caps_support_test.mm",
@@ -1946,7 +1977,6 @@ jumbo_source_set("blink_platform_unittests_sources") {
"//mojo/public/cpp/test_support:test_utils",
"//mojo/public/interfaces/bindings/tests:test_interfaces_blink",
"//services/viz/public/mojom",
- "//services/viz/public/mojom:mojom_blink",
"//skia",
"//skia:skcms",
"//skia:test_fonts",
@@ -1965,13 +1995,12 @@ jumbo_source_set("blink_platform_unittests_sources") {
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gfx/geometry/mojom:test_interfaces_blink",
+ "//ui/gfx/mojom:test_interfaces_blink",
"//url",
"//url/mojom:test_url_mojom_gurl_blink",
]
- data_deps = [
- ":blink_platform_unittests_data",
- ]
+ data_deps = [ ":blink_platform_unittests_data" ]
defines = [ "INSIDE_BLINK" ]
}
@@ -1980,9 +2009,7 @@ executable("image_decode_bench") {
visibility = [] # Allow re-assignment of list.
visibility = [ "*" ]
- sources = [
- "testing/image_decode_bench.cc",
- ]
+ sources = [ "testing/image_decode_bench.cc" ]
deps = [
":platform",
@@ -2038,6 +2065,9 @@ group("blink_platform_unittests_data") {
# Required by some image decoder tests.
"image-decoders/testing/",
"//third_party/blink/web_tests/images/resources/",
+
+ # Required by some font tests.
+ "//third_party/blink/web_tests/external/wpt/fonts/",
]
}
@@ -2049,9 +2079,7 @@ if (current_cpu == "x86" || current_cpu == "x64") {
":blink_platform_implementation",
"//third_party/blink/renderer:non_test_config",
]
- public_deps = [
- ":blink_platform_public_deps",
- ]
+ public_deps = [ ":blink_platform_public_deps" ]
if (is_win) {
cflags = [ "/arch:AVX" ]
} else {
@@ -2067,9 +2095,7 @@ test("blink_fuzzer_unittests") {
"//third_party/blink/public:test_support",
]
- sources = [
- "testing/run_all_tests.cc",
- ]
+ sources = [ "testing/run_all_tests.cc" ]
if (is_linux) {
deps += [
@@ -2097,9 +2123,7 @@ jumbo_source_set("blink_fuzzer_test_support") {
# Fuzzer for blink::MHTMLParser.
fuzzer_test("mhtml_parser_fuzzer") {
- sources = [
- "mhtml/mhtml_fuzzer.cc",
- ]
+ sources = [ "mhtml/mhtml_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2114,9 +2138,7 @@ fuzzer_test("mhtml_parser_fuzzer") {
# Fuzzer for blink::WebIconSizesParser.
fuzzer_test("web_icon_sizes_fuzzer") {
- sources = [
- "exported/web_icon_sizes_fuzzer.cc",
- ]
+ sources = [ "exported/web_icon_sizes_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2125,9 +2147,7 @@ fuzzer_test("web_icon_sizes_fuzzer") {
}
fuzzer_test("blink_png_decoder_fuzzer") {
- sources = [
- "png_fuzzer.cc",
- ]
+ sources = [ "png_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2143,9 +2163,7 @@ fuzzer_test("blink_png_decoder_fuzzer") {
# Fuzzer for blink::DateTimeFormat.
fuzzer_test("blink_date_time_format_fuzzer") {
- sources = [
- "text/date_time_format_fuzzer.cc",
- ]
+ sources = [ "text/date_time_format_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2156,9 +2174,7 @@ fuzzer_test("blink_date_time_format_fuzzer") {
# Fuzzer for blink::JSONParser.
fuzzer_test("blink_json_parser_fuzzer") {
- sources = [
- "json/json_parser_fuzzer.cc",
- ]
+ sources = [ "json/json_parser_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2167,9 +2183,7 @@ fuzzer_test("blink_json_parser_fuzzer") {
}
fuzzer_test("blink_harfbuzz_shaper_fuzzer") {
- sources = [
- "fonts/shaping/harfbuzz_shaper_fuzzer.cc",
- ]
+ sources = [ "fonts/shaping/harfbuzz_shaper_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2179,9 +2193,7 @@ fuzzer_test("blink_harfbuzz_shaper_fuzzer") {
}
fuzzer_test("blink_http_parsers_fuzzer") {
- sources = [
- "network/http_parsers_fuzzer.cc",
- ]
+ sources = [ "network/http_parsers_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2197,9 +2209,7 @@ template("blink_text_codec_fuzzer") {
}
name = target_name
fuzzer_test("blink_text_codec_" + name + "_fuzzer") {
- sources = [
- "text_codec_fuzzer.cc",
- ]
+ sources = [ "text_codec_fuzzer.cc" ]
deps = [
":blink_fuzzer_test_support",
":platform",
@@ -2249,7 +2259,6 @@ jumbo_source_set("unit_tests") {
"graphics/test/stub_image.h",
# Tests migrated from the web/tests directory.
- "exported/web_resource_timing_info_test.cc",
"exported/web_url_request_test.cc",
"exported/web_url_response_test.cc",
"timer_perf_test.cc",
@@ -2263,7 +2272,6 @@ jumbo_source_set("unit_tests") {
deps = [
":test_support",
- "//services/viz/public/mojom:mojom_blink",
"//testing/gmock",
"//testing/gtest",
]
diff --git a/chromium/third_party/blink/renderer/platform/DEPS b/chromium/third_party/blink/renderer/platform/DEPS
index 4d639942df5..99201dec859 100644
--- a/chromium/third_party/blink/renderer/platform/DEPS
+++ b/chromium/third_party/blink/renderer/platform/DEPS
@@ -62,6 +62,8 @@ include_rules = [
"+services/metrics/public/cpp/ukm_entry_builder.h",
"+services/metrics/public/cpp/ukm_recorder.h",
"+services/metrics/public/cpp/ukm_source_id.h",
+ "+services/network/public/cpp",
+ "+services/network/public/mojom",
"+services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h",
"+skia/ext",
#TODO(nverne): remove this
@@ -69,6 +71,7 @@ include_rules = [
"+third_party/ced/src/compact_enc_det/compact_enc_det.h",
"+third_party/khronos",
"+third_party/skia",
+ "+ui/base/cursor/cursor.h",
"+ui/base/resource/scale_factor.h",
"+ui/gfx",
"+url",
diff --git a/chromium/third_party/blink/renderer/platform/PRESUBMIT.py b/chromium/third_party/blink/renderer/platform/PRESUBMIT.py
index e053782b759..fe39215b5b2 100644
--- a/chromium/third_party/blink/renderer/platform/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/platform/PRESUBMIT.py
@@ -1,7 +1,6 @@
# 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.
-
"""Presubmit script for changes affecting Source/platform.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
@@ -42,9 +41,12 @@ def _CheckRuntimeEnabledFeaturesSorted(input_api, output_api):
# Diff the sorted/unsorted versions.
differ = difflib.Differ()
diff = differ.compare(features, features_sorted)
- return [output_api.PresubmitError(
- 'runtime_enabled_features.json5 features must be sorted alphabetically. '
- 'Diff of feature order follows:', long_text='\n'.join(diff))]
+ return [
+ output_api.PresubmitError(
+ 'runtime_enabled_features.json5 features must be sorted alphabetically. '
+ 'Diff of feature order follows:',
+ long_text='\n'.join(diff))
+ ]
def _CommonChecks(input_api, output_api):
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc
index 4ea0dacd875..f02f038486a 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc
@@ -14,8 +14,7 @@ namespace blink {
std::unique_ptr<CompositorAnimation> CompositorAnimation::Create() {
return std::make_unique<CompositorAnimation>(
- cc::SingleKeyframeEffectAnimation::Create(
- cc::AnimationIdProvider::NextAnimationId()));
+ cc::Animation::Create(cc::AnimationIdProvider::NextAnimationId()));
}
std::unique_ptr<CompositorAnimation>
@@ -23,17 +22,14 @@ CompositorAnimation::CreateWorkletAnimation(
cc::WorkletAnimationId worklet_animation_id,
const String& name,
double playback_rate,
- std::unique_ptr<CompositorScrollTimeline> scroll_timeline,
std::unique_ptr<cc::AnimationOptions> options,
std::unique_ptr<cc::AnimationEffectTimings> effect_timings) {
return std::make_unique<CompositorAnimation>(cc::WorkletAnimation::Create(
- worklet_animation_id, name.Utf8(), playback_rate,
- std::move(scroll_timeline), std::move(options),
+ worklet_animation_id, name.Utf8(), playback_rate, std::move(options),
std::move(effect_timings)));
}
-CompositorAnimation::CompositorAnimation(
- scoped_refptr<cc::SingleKeyframeEffectAnimation> animation)
+CompositorAnimation::CompositorAnimation(scoped_refptr<cc::Animation> animation)
: animation_(animation), delegate_() {}
CompositorAnimation::~CompositorAnimation() {
@@ -44,7 +40,7 @@ CompositorAnimation::~CompositorAnimation() {
animation_->animation_timeline()->DetachAnimation(animation_);
}
-cc::SingleKeyframeEffectAnimation* CompositorAnimation::CcAnimation() const {
+cc::Animation* CompositorAnimation::CcAnimation() const {
return animation_.get();
}
@@ -76,7 +72,7 @@ void CompositorAnimation::RemoveKeyframeModel(int keyframe_model_id) {
}
void CompositorAnimation::PauseKeyframeModel(int keyframe_model_id,
- double time_offset) {
+ base::TimeDelta time_offset) {
animation_->PauseKeyframeModel(keyframe_model_id, time_offset);
}
@@ -88,9 +84,8 @@ void CompositorAnimation::UpdateScrollTimeline(
base::Optional<cc::ElementId> element_id,
base::Optional<double> start_scroll_offset,
base::Optional<double> end_scroll_offset) {
- cc::ToWorkletAnimation(animation_.get())
- ->UpdateScrollTimeline(element_id, start_scroll_offset,
- end_scroll_offset);
+ animation_->UpdateScrollTimeline(element_id, start_scroll_offset,
+ end_scroll_offset);
}
void CompositorAnimation::UpdatePlaybackRate(double playback_rate) {
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
index e900e473315..348a4480437 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
@@ -10,9 +10,8 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
+#include "cc/animation/animation.h"
#include "cc/animation/animation_delegate.h"
-#include "cc/animation/scroll_timeline.h"
-#include "cc/animation/single_keyframe_effect_animation.h"
#include "cc/animation/worklet_animation.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -24,8 +23,6 @@ class AnimationCurve;
namespace blink {
-using CompositorScrollTimeline = cc::ScrollTimeline;
-
class CompositorAnimationDelegate;
class CompositorKeyframeModel;
@@ -37,15 +34,13 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
cc::WorkletAnimationId,
const String& name,
double playback_rate,
- std::unique_ptr<CompositorScrollTimeline>,
std::unique_ptr<cc::AnimationOptions>,
std::unique_ptr<cc::AnimationEffectTimings> effect_timings);
- explicit CompositorAnimation(
- scoped_refptr<cc::SingleKeyframeEffectAnimation>);
+ explicit CompositorAnimation(scoped_refptr<cc::Animation>);
~CompositorAnimation() override;
- cc::SingleKeyframeEffectAnimation* CcAnimation() const;
+ cc::Animation* CcAnimation() const;
// An animation delegate is notified when animations are started and stopped.
// The CompositorAnimation does not take ownership of the delegate, and
@@ -59,7 +54,7 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
void AddKeyframeModel(std::unique_ptr<CompositorKeyframeModel>);
void RemoveKeyframeModel(int keyframe_model_id);
- void PauseKeyframeModel(int keyframe_model_id, double time_offset);
+ void PauseKeyframeModel(int keyframe_model_id, base::TimeDelta time_offset);
void AbortKeyframeModel(int keyframe_model_id);
void UpdateScrollTimeline(base::Optional<cc::ElementId>,
@@ -85,7 +80,7 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
void NotifyLocalTimeUpdated(
base::Optional<base::TimeDelta> local_time) override;
- scoped_refptr<cc::SingleKeyframeEffectAnimation> animation_;
+ scoped_refptr<cc::Animation> animation_;
CompositorAnimationDelegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(CompositorAnimation);
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc
index c40fb3822d0..25a9e0b34ae 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_test.cc
@@ -60,7 +60,7 @@ TEST_F(CompositorAnimationTest, NullDelegate) {
std::unique_ptr<CompositorAnimationTestClient> client(
new CompositorAnimationTestClient);
CompositorAnimation* animation = client->GetCompositorAnimation();
- cc::SingleKeyframeEffectAnimation* cc_animation = animation->CcAnimation();
+ cc::Animation* cc_animation = animation->CcAnimation();
timeline->AnimationAttached(*client);
int timeline_id = cc_animation->animation_timeline()->id();
@@ -93,8 +93,7 @@ TEST_F(CompositorAnimationTest, NotifyFromCCAfterCompositorAnimationDeletion) {
std::unique_ptr<CompositorAnimationTestClient> client(
new CompositorAnimationTestClient);
CompositorAnimation* animation = client->GetCompositorAnimation();
- scoped_refptr<cc::SingleKeyframeEffectAnimation> cc_animation =
- animation->CcAnimation();
+ scoped_refptr<cc::Animation> cc_animation = animation->CcAnimation();
timeline->AnimationAttached(*client);
int timeline_id = cc_animation->animation_timeline()->id();
@@ -129,8 +128,7 @@ TEST_F(CompositorAnimationTest,
scoped_refptr<cc::AnimationTimeline> cc_timeline =
timeline->GetAnimationTimeline();
- scoped_refptr<cc::SingleKeyframeEffectAnimation> cc_animation =
- client->animation_->CcAnimation();
+ scoped_refptr<cc::Animation> cc_animation = client->animation_->CcAnimation();
EXPECT_FALSE(cc_animation->animation_timeline());
timeline->AnimationAttached(*client);
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.cc
index eca78aece63..3da0644ab74 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.cc
@@ -15,6 +15,10 @@ CompositorAnimationTimeline::CompositorAnimationTimeline()
: animation_timeline_(cc::AnimationTimeline::Create(
cc::AnimationIdProvider::NextTimelineId())) {}
+CompositorAnimationTimeline::CompositorAnimationTimeline(
+ scoped_refptr<cc::AnimationTimeline> timeline)
+ : animation_timeline_(timeline) {}
+
CompositorAnimationTimeline::~CompositorAnimationTimeline() {
// Detach timeline from host, otherwise it stays there (leaks) until
// compositor shutdown.
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h
index b4e6b8427d4..8307cd8f257 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline.h
@@ -24,6 +24,7 @@ class PLATFORM_EXPORT CompositorAnimationTimeline {
public:
CompositorAnimationTimeline();
+ explicit CompositorAnimationTimeline(scoped_refptr<cc::AnimationTimeline>);
~CompositorAnimationTimeline();
cc::AnimationTimeline* GetAnimationTimeline() const;
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
index 656f2f22d6d..8aeb308e331 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
@@ -90,9 +90,8 @@ double CompositorKeyframeModel::TimeOffset() const {
return keyframe_model_->time_offset().InSecondsF();
}
-void CompositorKeyframeModel::SetTimeOffset(double monotonic_time) {
- keyframe_model_->set_time_offset(
- base::TimeDelta::FromSecondsD(monotonic_time));
+void CompositorKeyframeModel::SetTimeOffset(base::TimeDelta monotonic_time) {
+ keyframe_model_->set_time_offset(monotonic_time);
}
blink::CompositorKeyframeModel::Direction
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
index 3002115a428..7144083160b 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
@@ -63,7 +63,7 @@ class PLATFORM_EXPORT CompositorKeyframeModel {
void SetStartTime(base::TimeTicks);
double TimeOffset() const;
- void SetTimeOffset(double monotonic_time);
+ void SetTimeOffset(base::TimeDelta monotonic_time);
Direction GetDirection() const;
void SetDirection(Direction);
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc
index d6e98d70c29..98c3567a652 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_keyframe_model_test.cc
@@ -28,7 +28,7 @@ TEST(WebCompositorAnimationTest, ModifiedSettings) {
*curve, compositor_target_property::OPACITY, 0, 1);
keyframe_model->SetIterations(2);
keyframe_model->SetStartTime(2);
- keyframe_model->SetTimeOffset(2);
+ keyframe_model->SetTimeOffset(base::TimeDelta::FromSeconds(2));
keyframe_model->SetDirection(CompositorKeyframeModel::Direction::REVERSE);
EXPECT_EQ(2, keyframe_model->Iterations());
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc
index 001388046da..9ee7cf65d70 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_transform_operations.cc
@@ -28,29 +28,29 @@ void CompositorTransformOperations::AppendTranslate(double x,
double y,
double z) {
transform_operations_.AppendTranslate(
- SkDoubleToMScalar(x), SkDoubleToMScalar(y), SkDoubleToMScalar(z));
+ SkDoubleToScalar(x), SkDoubleToScalar(y), SkDoubleToScalar(z));
}
void CompositorTransformOperations::AppendRotate(double x,
double y,
double z,
double degrees) {
- transform_operations_.AppendRotate(SkDoubleToMScalar(x), SkDoubleToMScalar(y),
- SkDoubleToMScalar(z),
- SkDoubleToMScalar(degrees));
+ transform_operations_.AppendRotate(SkDoubleToScalar(x), SkDoubleToScalar(y),
+ SkDoubleToScalar(z),
+ SkDoubleToScalar(degrees));
}
void CompositorTransformOperations::AppendScale(double x, double y, double z) {
- transform_operations_.AppendScale(SkDoubleToMScalar(x), SkDoubleToMScalar(y),
- SkDoubleToMScalar(z));
+ transform_operations_.AppendScale(SkDoubleToScalar(x), SkDoubleToScalar(y),
+ SkDoubleToScalar(z));
}
void CompositorTransformOperations::AppendSkew(double x, double y) {
- transform_operations_.AppendSkew(SkDoubleToMScalar(x), SkDoubleToMScalar(y));
+ transform_operations_.AppendSkew(SkDoubleToScalar(x), SkDoubleToScalar(y));
}
void CompositorTransformOperations::AppendPerspective(double depth) {
- transform_operations_.AppendPerspective(SkDoubleToMScalar(depth));
+ transform_operations_.AppendPerspective(SkDoubleToScalar(depth));
}
void CompositorTransformOperations::AppendMatrix(const SkMatrix44& matrix) {
diff --git a/chromium/third_party/blink/renderer/platform/animation/timing_function.cc b/chromium/third_party/blink/renderer/platform/animation/timing_function.cc
index 2ea4d36719a..5d8e9c8806a 100644
--- a/chromium/third_party/blink/renderer/platform/animation/timing_function.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/timing_function.cc
@@ -200,7 +200,7 @@ bool operator==(const CubicBezierTimingFunction& lhs,
if (rhs.GetType() != TimingFunction::Type::CUBIC_BEZIER)
return false;
- const CubicBezierTimingFunction& ctf = ToCubicBezierTimingFunction(rhs);
+ const auto& ctf = To<CubicBezierTimingFunction>(rhs);
if ((lhs.GetEaseType() == CubicBezierTimingFunction::EaseType::CUSTOM) &&
(ctf.GetEaseType() == CubicBezierTimingFunction::EaseType::CUSTOM))
return (lhs.X1() == ctf.X1()) && (lhs.Y1() == ctf.Y1()) &&
@@ -213,7 +213,7 @@ bool operator==(const StepsTimingFunction& lhs, const TimingFunction& rhs) {
if (rhs.GetType() != TimingFunction::Type::STEPS)
return false;
- const StepsTimingFunction& stf = ToStepsTimingFunction(rhs);
+ const auto& stf = To<StepsTimingFunction>(rhs);
return (lhs.NumberOfSteps() == stf.NumberOfSteps()) &&
(lhs.GetStepPosition() == stf.GetStepPosition());
}
@@ -223,15 +223,15 @@ bool operator==(const StepsTimingFunction& lhs, const TimingFunction& rhs) {
bool operator==(const TimingFunction& lhs, const TimingFunction& rhs) {
switch (lhs.GetType()) {
case TimingFunction::Type::LINEAR: {
- const LinearTimingFunction& linear = ToLinearTimingFunction(lhs);
+ const auto& linear = To<LinearTimingFunction>(lhs);
return (linear == rhs);
}
case TimingFunction::Type::CUBIC_BEZIER: {
- const CubicBezierTimingFunction& cubic = ToCubicBezierTimingFunction(lhs);
+ const auto& cubic = To<CubicBezierTimingFunction>(lhs);
return (cubic == rhs);
}
case TimingFunction::Type::STEPS: {
- const StepsTimingFunction& step = ToStepsTimingFunction(lhs);
+ const auto& step = To<StepsTimingFunction>(lhs);
return (step == rhs);
}
default:
diff --git a/chromium/third_party/blink/renderer/platform/animation/timing_function.h b/chromium/third_party/blink/renderer/platform/animation/timing_function.h
index f7a9eaef5b1..8cf6ef43f37 100644
--- a/chromium/third_party/blink/renderer/platform/animation/timing_function.h
+++ b/chromium/third_party/blink/renderer/platform/animation/timing_function.h
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
@@ -217,14 +218,24 @@ PLATFORM_EXPORT bool operator==(const StepsTimingFunction&,
PLATFORM_EXPORT bool operator==(const TimingFunction&, const TimingFunction&);
PLATFORM_EXPORT bool operator!=(const TimingFunction&, const TimingFunction&);
-#define DEFINE_TIMING_FUNCTION_TYPE_CASTS(typeName, enumName) \
- DEFINE_TYPE_CASTS(typeName##TimingFunction, TimingFunction, value, \
- value->GetType() == TimingFunction::Type::enumName, \
- value.GetType() == TimingFunction::Type::enumName)
-
-DEFINE_TIMING_FUNCTION_TYPE_CASTS(Linear, LINEAR);
-DEFINE_TIMING_FUNCTION_TYPE_CASTS(CubicBezier, CUBIC_BEZIER);
-DEFINE_TIMING_FUNCTION_TYPE_CASTS(Steps, STEPS);
+template <>
+struct DowncastTraits<LinearTimingFunction> {
+ static bool AllowFrom(const TimingFunction& value) {
+ return value.GetType() == TimingFunction::Type::LINEAR;
+ }
+};
+template <>
+struct DowncastTraits<CubicBezierTimingFunction> {
+ static bool AllowFrom(const TimingFunction& value) {
+ return value.GetType() == TimingFunction::Type::CUBIC_BEZIER;
+ }
+};
+template <>
+struct DowncastTraits<StepsTimingFunction> {
+ static bool AllowFrom(const TimingFunction& value) {
+ return value.GetType() == TimingFunction::Type::STEPS;
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/DEPS b/chromium/third_party/blink/renderer/platform/audio/DEPS
index 5a7148091dd..970052c08fd 100644
--- a/chromium/third_party/blink/renderer/platform/audio/DEPS
+++ b/chromium/third_party/blink/renderer/platform/audio/DEPS
@@ -12,7 +12,6 @@ include_rules = [
"+third_party/blink/renderer/platform/wtf/cross_thread_functional.h",
"+third_party/blink/renderer/platform/geometry/float_point_3d.h",
"+third_party/blink/renderer/platform/heap",
- "+third_party/blink/renderer/platform/instrumentation/histogram.h",
"+third_party/blink/renderer/platform/instrumentation",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/scheduler/public",
diff --git a/chromium/third_party/blink/renderer/platform/audio/OWNERS b/chromium/third_party/blink/renderer/platform/audio/OWNERS
index caaf05cf1d8..bcc0e71a548 100644
--- a/chromium/third_party/blink/renderer/platform/audio/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/audio/OWNERS
@@ -1,5 +1,4 @@
hongchan@chromium.org
-kbr@chromium.org
rtoy@chromium.org
# COMPONENT: Blink>WebAudio
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
index 3e2f1a5a3fa..819ca91d754 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
@@ -61,7 +61,8 @@ size_t AudioDelayDSPKernel::BufferLengthForDelay(double max_delay_time,
// Compute the length of the buffer needed to handle a max delay of
// |maxDelayTime|. One is added to handle the case where the actual delay
// equals the maximum delay.
- return 1 + audio_utilities::TimeToSampleFrame(max_delay_time, sample_rate);
+ return 1 + audio_utilities::TimeToSampleFrame(max_delay_time, sample_rate,
+ audio_utilities::kRoundUp);
}
bool AudioDelayDSPKernel::HasSampleAccurateValues() {
@@ -79,14 +80,14 @@ double AudioDelayDSPKernel::DelayTime(float sample_rate) {
void AudioDelayDSPKernel::Process(const float* source,
float* destination,
uint32_t frames_to_process) {
- size_t buffer_length = buffer_.size();
+ int buffer_length = buffer_.size();
float* buffer = buffer_.Data();
DCHECK(buffer_length);
DCHECK(source);
DCHECK(destination);
DCHECK_GE(write_index_, 0);
- DCHECK_LT(static_cast<size_t>(write_index_), buffer_length);
+ DCHECK_LT(write_index_, buffer_length);
float sample_rate = this->SampleRate();
double max_time = MaxDelayTime();
@@ -112,28 +113,25 @@ void AudioDelayDSPKernel::Process(const float* source,
// Linearly interpolate in-between delay times.
int read_index1 = static_cast<int>(read_position);
DCHECK_GE(read_index1, 0);
- DCHECK_LT(static_cast<size_t>(read_index1), buffer_length);
+ DCHECK_LT(read_index1, buffer_length);
int read_index2 = read_index1 + 1;
- if (read_index2 >= static_cast<int>(buffer_length))
+ if (read_index2 >= buffer_length)
read_index2 -= buffer_length;
DCHECK_GE(read_index2, 0);
- DCHECK_LT(static_cast<size_t>(read_index2), buffer_length);
-
- double interpolation_factor = read_position - read_index1;
+ DCHECK_LT(read_index2, buffer_length);
buffer[w_index] = *source++;
- ++w_index;
- if (w_index >= static_cast<int>(buffer_length))
- w_index -= buffer_length;
+ float interpolation_factor = read_position - read_index1;
float sample1 = buffer[read_index1];
float sample2 = buffer[read_index2];
- double output =
- (1 - interpolation_factor) * sample1 + interpolation_factor * sample2;
+ ++w_index;
+ if (w_index >= buffer_length)
+ w_index -= buffer_length;
- *destination++ = static_cast<float>(output);
+ *destination++ = sample1 + interpolation_factor * (sample2 - sample1);
}
write_index_ = w_index;
@@ -152,7 +150,8 @@ void AudioDelayDSPKernel::Process(const float* source,
// Make sure the delay time is in a valid range.
delay_time = clampTo(delay_time, 0.0, max_time);
double desired_delay_frames = delay_time * sample_rate;
- double read_position = write_index_ + buffer_length - desired_delay_frames;
+ int w_index = write_index_;
+ double read_position = w_index + buffer_length - desired_delay_frames;
if (read_position >= buffer_length)
read_position -= buffer_length;
@@ -161,34 +160,34 @@ void AudioDelayDSPKernel::Process(const float* source,
// interpolation.
int read_index1 = static_cast<int>(read_position);
int read_index2 = (read_index1 + 1) % buffer_length;
- double interp_factor = read_position - read_index1;
+ float interp_factor = read_position - read_index1;
- int w_index = write_index_;
+ float* w = &buffer[w_index];
+ float* r1 = &buffer[read_index1];
+ float* r2 = &buffer[read_index2];
+ float* buffer_end = &buffer[buffer_length];
for (unsigned i = 0; i < frames_to_process; ++i) {
// Copy the latest sample into the buffer. Needed because
// w_index could be the same as read_index1 or read_index2.
- buffer[w_index] = *source++;
- float sample1 = buffer[read_index1];
- float sample2 = buffer[read_index2];
+ *w++ = *source++;
+ float sample1 = *r1++;
+ float sample2 = *r2++;
// Update the indices and wrap them to the beginning of the buffer if
// needed.
- ++w_index;
- ++read_index1;
- ++read_index2;
- if (w_index >= static_cast<int>(buffer_length))
- w_index -= buffer_length;
- if (read_index1 >= static_cast<int>(buffer_length))
- read_index1 -= buffer_length;
- if (read_index2 >= static_cast<int>(buffer_length))
- read_index2 -= buffer_length;
+ if (w >= buffer_end)
+ w = buffer;
+ if (r1 >= buffer_end)
+ r1 = buffer;
+ if (r2 >= buffer_end)
+ r2 = buffer;
// Linearly interpolate between samples.
- *destination++ = (1 - interp_factor) * sample1 + interp_factor * sample2;
+ *destination++ = sample1 + interp_factor * (sample2 - sample1);
}
- write_index_ = w_index;
+ write_index_ = w - buffer;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
index ad2ac3c5a15..c66a178d20a 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
@@ -32,13 +32,13 @@
#include <memory>
#include <utility>
+#include "base/metrics/histogram_functions.h"
#include "media/base/audio_bus.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/audio/push_pull_fifo.h"
#include "third_party/blink/renderer/platform/audio/vector_math.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -67,7 +67,6 @@ AudioDestination::AudioDestination(AudioIOCallback& callback,
const WebAudioLatencyHint& latency_hint,
base::Optional<float> context_sample_rate)
: number_of_output_channels_(number_of_output_channels),
- play_state_(PlayState::kStopped),
fifo_(
std::make_unique<PushPullFIFO>(number_of_output_channels, kFIFOSize)),
output_bus_(AudioBus::Create(number_of_output_channels,
@@ -76,7 +75,8 @@ AudioDestination::AudioDestination(AudioIOCallback& callback,
render_bus_(AudioBus::Create(number_of_output_channels,
audio_utilities::kRenderQuantumFrames)),
callback_(callback),
- frames_elapsed_(0) {
+ frames_elapsed_(0),
+ device_state_(DeviceState::kStopped) {
// Create WebAudioDevice. blink::WebAudioDevice is designed to support the
// local input (e.g. loopback from OS audio system), but Chromium's media
// renderer does not support it currently. Thus, we use zero for the number
@@ -126,29 +126,23 @@ AudioDestination::AudioDestination(AudioIOCallback& callback,
context_sample_rate_ = web_audio_device_->SampleRate();
}
- DEFINE_STATIC_LOCAL(SparseHistogram, sample_rate_histogram,
- ("WebAudio.AudioContext.HardwareSampleRate"));
-
- sample_rate_histogram.Sample(web_audio_device_->SampleRate());
-
- // The actual supplied |sampleRate| is probably a small set including 44100,
- // 48000, 22050, and 2400 Hz. Other valid values range from 3000 to 384000
- // Hz, but are not expected to be used much.
- DEFINE_STATIC_LOCAL(SparseHistogram, selected_sample_rate_histogram,
- ("WebAudio.AudioContextOptions.sampleRate"));
-
- // From the expected values above and the common HW sample rates, we expect
- // the most common ratios to be the set 0.5, 44100/48000, and 48000/44100.
- // Other values are possible but seem unlikely.
- DEFINE_STATIC_LOCAL(SparseHistogram, sample_rate_ratio_histogram,
- ("WebAudio.AudioContextOptions.sampleRateRatio"));
+ base::UmaHistogramSparse("WebAudio.AudioContext.HardwareSampleRate",
+ web_audio_device_->SampleRate());
// Record the selected sample rate and ratio if the sampleRate was given. The
// ratio is recorded as a percentage, rounded to the nearest percent.
if (context_sample_rate.has_value()) {
- selected_sample_rate_histogram.Sample(context_sample_rate.value());
- sample_rate_ratio_histogram.Sample(
- static_cast<int32_t>(100 * scale_factor + 0.5));
+ // The actual supplied |sampleRate| is probably a small set including 44100,
+ // 48000, 22050, and 2400 Hz. Other valid values range from 3000 to 384000
+ // Hz, but are not expected to be used much.
+ base::UmaHistogramSparse("WebAudio.AudioContextOptions.sampleRate",
+ context_sample_rate.value());
+ // From the expected values above and the common HW sample rates, we expect
+ // the most common ratios to be the set 0.5, 44100/48000, and 48000/44100.
+ // Other values are possible but seem unlikely.
+ base::UmaHistogramSparse("WebAudio.AudioContextOptions.sampleRateRatio",
+
+ static_cast<int32_t>(100 * scale_factor + 0.5));
}
}
@@ -214,6 +208,16 @@ void AudioDestination::RequestRender(size_t frames_requested,
"frames_to_render", frames_to_render, "timestamp (s)",
delay_timestamp);
+ MutexTryLocker locker(state_change_lock_);
+
+ // The state might be changing by ::Stop() call. If the state is locked, do
+ // not touch the below.
+ if (!locker.Locked())
+ return;
+
+ if (device_state_ != DeviceState::kRunning)
+ return;
+
metric_reporter_.BeginTrace();
frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
@@ -240,8 +244,8 @@ void AudioDestination::RequestRender(size_t frames_requested,
output_position_.position = 0.0;
if (resampler_) {
- resampler_->Resample(audio_utilities::kRenderQuantumFrames,
- resampler_bus_.get());
+ resampler_->ResampleInternal(audio_utilities::kRenderQuantumFrames,
+ resampler_bus_.get());
} else {
// Process WebAudio graph and push the rendered output to FIFO.
callback_.Render(render_bus_.get(), audio_utilities::kRenderQuantumFrames,
@@ -258,64 +262,72 @@ void AudioDestination::RequestRender(size_t frames_requested,
void AudioDestination::Start() {
DCHECK(IsMainThread());
+ TRACE_EVENT0("webaudio", "AudioDestination::Start");
- // Start the "audio device" after the rendering thread is ready.
- if (web_audio_device_ && play_state_ == PlayState::kStopped) {
- TRACE_EVENT0("webaudio", "AudioDestination::Start");
- web_audio_device_->Start();
- play_state_ = PlayState::kPlaying;
- }
+ if (device_state_ != DeviceState::kStopped)
+ return;
+ web_audio_device_->Start();
+ SetDeviceState(DeviceState::kRunning);
}
void AudioDestination::StartWithWorkletTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner) {
DCHECK(IsMainThread());
+ DCHECK_EQ(worklet_task_runner_, nullptr);
+ TRACE_EVENT0("webaudio", "AudioDestination::StartWithWorkletTaskRunner");
- if (web_audio_device_ && play_state_ == PlayState::kStopped) {
- TRACE_EVENT0("webaudio", "AudioDestination::Start");
- worklet_task_runner_ = std::move(worklet_task_runner);
- web_audio_device_->Start();
- play_state_ = PlayState::kPlaying;
- }
+ if (device_state_ != DeviceState::kStopped)
+ return;
+ worklet_task_runner_ = std::move(worklet_task_runner);
+ web_audio_device_->Start();
+ SetDeviceState(DeviceState::kRunning);
}
void AudioDestination::Stop() {
DCHECK(IsMainThread());
+ TRACE_EVENT0("webaudio", "AudioDestination::Stop");
- // This assumes stopping the "audio device" is synchronous and dumping the
- // rendering thread is safe after that.
- if (web_audio_device_ && play_state_ != PlayState::kStopped) {
- TRACE_EVENT0("webaudio", "AudioDestination::Stop");
- web_audio_device_->Stop();
- worklet_task_runner_ = nullptr;
- play_state_ = PlayState::kStopped;
- }
+ if (device_state_ == DeviceState::kStopped)
+ return;
+ web_audio_device_->Stop();
+
+ // Resetting |worklet_task_runner_| here is safe because
+ // AudioDestination::Render() won't be called after WebAudioDevice::Stop()
+ // call above.
+ worklet_task_runner_ = nullptr;
+
+ SetDeviceState(DeviceState::kStopped);
}
void AudioDestination::Pause() {
DCHECK(IsMainThread());
- if (web_audio_device_ && play_state_ == PlayState::kPlaying) {
- web_audio_device_->Pause();
- play_state_ = PlayState::kPaused;
- }
+ TRACE_EVENT0("webaudio", "AudioDestination::Pause");
+
+ if (device_state_ != DeviceState::kRunning)
+ return;
+ web_audio_device_->Pause();
+ SetDeviceState(DeviceState::kPaused);
}
void AudioDestination::Resume() {
DCHECK(IsMainThread());
- if (web_audio_device_ && play_state_ == PlayState::kPaused) {
- web_audio_device_->Resume();
- play_state_ = PlayState::kPlaying;
- }
+ TRACE_EVENT0("webaudio", "AudioDestination::Resume");
+
+ if (device_state_ != DeviceState::kPaused)
+ return;
+ web_audio_device_->Resume();
+ SetDeviceState(DeviceState::kRunning);
}
-uint32_t AudioDestination::CallbackBufferSize() const {
+bool AudioDestination::IsPlaying() {
DCHECK(IsMainThread());
- return callback_buffer_size_;
+ MutexLocker locker(state_change_lock_);
+ return device_state_ == DeviceState::kRunning;
}
-bool AudioDestination::IsPlaying() {
+uint32_t AudioDestination::CallbackBufferSize() const {
DCHECK(IsMainThread());
- return play_state_ == PlayState::kPlaying;
+ return callback_buffer_size_;
}
int AudioDestination::FramesPerBuffer() const {
@@ -336,19 +348,16 @@ uint32_t AudioDestination::MaxChannelCount() {
}
bool AudioDestination::CheckBufferSize() {
+ // Record the sizes if we successfully created an output device.
// Histogram for audioHardwareBufferSize
- DEFINE_STATIC_LOCAL(SparseHistogram, hardware_buffer_size_histogram,
- ("WebAudio.AudioDestination.HardwareBufferSize"));
+ base::UmaHistogramSparse("WebAudio.AudioDestination.HardwareBufferSize",
+ HardwareBufferSize());
// Histogram for the actual callback size used. Typically, this is the same
// as audioHardwareBufferSize, but can be adjusted depending on some
// heuristics below.
- DEFINE_STATIC_LOCAL(SparseHistogram, callback_buffer_size_histogram,
- ("WebAudio.AudioDestination.CallbackBufferSize"));
-
- // Record the sizes if we successfully created an output device.
- hardware_buffer_size_histogram.Sample(HardwareBufferSize());
- callback_buffer_size_histogram.Sample(callback_buffer_size_);
+ base::UmaHistogramSparse("WebAudio.AudioDestination.CallbackBufferSize",
+ callback_buffer_size_);
// Check if the requested buffer size is too large.
bool is_buffer_size_valid =
@@ -364,4 +373,11 @@ void AudioDestination::ProvideResamplerInput(int resampler_frame_delay,
callback_.Render(dest, audio_utilities::kRenderQuantumFrames,
output_position_, metric_reporter_.GetMetric());
}
+
+void AudioDestination::SetDeviceState(DeviceState state) {
+ DCHECK(IsMainThread());
+ MutexLocker locker(state_change_lock_);
+ device_state_ = state;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
index f3045cceaa2..dafb1d9da4c 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/platform/audio/audio_io_callback.h"
#include "third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
@@ -117,11 +118,19 @@ class PLATFORM_EXPORT AudioDestination
static uint32_t MaxChannelCount();
private:
+ // Represents the current state of the underlying |WebAudioDevice| object
+ // (RendererWebAudioDeviceImpl).
+ enum DeviceState {
+ kRunning,
+ kPaused,
+ kStopped,
+ };
+
+ void SetDeviceState(DeviceState);
+
// Provide input to the resampler (if used).
void ProvideResamplerInput(int resampler_frame_delay, AudioBus* dest);
- enum class PlayState { kStopped, kPlaying, kPaused };
-
// Check if the buffer size chosen by the WebAudioDevice is too large.
bool CheckBufferSize();
@@ -131,7 +140,6 @@ class PLATFORM_EXPORT AudioDestination
std::unique_ptr<WebAudioDevice> web_audio_device_;
const unsigned number_of_output_channels_;
uint32_t callback_buffer_size_;
- PlayState play_state_;
// The task runner for AudioWorklet operation. This is only valid when
// the AudioWorklet is activated.
@@ -168,6 +176,13 @@ class PLATFORM_EXPORT AudioDestination
AudioCallbackMetricReporter metric_reporter_;
+ // This protects |device_state_| below.
+ mutable Mutex state_change_lock_;
+
+ // Modified only on the main thread, so it can be read without holding a lock
+ // there.
+ DeviceState device_state_;
+
DISALLOW_COPY_AND_ASSIGN(AudioDestination);
};
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination_test.cc b/chromium/third_party/blink/renderer/platform/audio/audio_destination_test.cc
index 072ca234d0a..62ea2d72525 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination_test.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination_test.cc
@@ -73,6 +73,7 @@ void CountWASamplesProcessedForRate(base::Optional<float> sample_rate) {
scoped_refptr<AudioDestination> destination = AudioDestination::Create(
callback, channel_count, latency_hint, sample_rate);
+ destination->Start();
Vector<float> channels[channel_count];
WebVector<float*> dest_data(static_cast<size_t>(channel_count));
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_source_provider_client.h b/chromium/third_party/blink/renderer/platform/audio/audio_source_provider_client.h
index 2d77c44a5cd..4372a94a853 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_source_provider_client.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_source_provider_client.h
@@ -42,7 +42,7 @@ class AudioSourceProviderClient : public GarbageCollectedMixin {
// changed.
virtual void OnCurrentSrcChanged(const KURL& current_src) {}
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
protected:
virtual ~AudioSourceProviderClient() = default;
diff --git a/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc b/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc
index dbf97962bef..22fb5b2af72 100644
--- a/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc
@@ -34,7 +34,7 @@
namespace blink {
EqualPowerPanner::EqualPowerPanner(float sample_rate)
- : Panner(kPanningModelEqualPower) {}
+ : Panner(PanningModel::kEqualPower) {}
void EqualPowerPanner::Pan(double azimuth,
double /*elevation*/,
diff --git a/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc b/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc
index c2b692bc562..69b31dffe9d 100644
--- a/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/ffmpeg/fft_frame_ffmpeg.cc
@@ -84,8 +84,8 @@ FFTFrame::FFTFrame(const FFTFrame& frame)
// Copy/setup frame data.
unsigned nbytes = sizeof(float) * (fft_size_ / 2);
- memcpy(RealData(), frame.RealData(), nbytes);
- memcpy(ImagData(), frame.ImagData(), nbytes);
+ memcpy(RealData().Data(), frame.RealData().Data(), nbytes);
+ memcpy(ImagData().Data(), frame.ImagData().Data(), nbytes);
}
int FFTFrame::MinFFTSize() {
diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
index b5b02afabb7..b10f84b06c2 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
@@ -82,13 +82,13 @@ void FFTFrame::InterpolateFrequencyComponents(const FFTFrame& frame1,
double interp) {
// FIXME : with some work, this method could be optimized
- float* real_p = RealData();
- float* imag_p = ImagData();
+ AudioFloatArray& real = RealData();
+ AudioFloatArray& imag = ImagData();
- const float* real_p1 = frame1.RealData();
- const float* imag_p1 = frame1.ImagData();
- const float* real_p2 = frame2.RealData();
- const float* imag_p2 = frame2.ImagData();
+ const AudioFloatArray& real1 = frame1.RealData();
+ const AudioFloatArray& imag1 = frame1.ImagData();
+ const AudioFloatArray& real2 = frame2.RealData();
+ const AudioFloatArray& imag2 = frame2.ImagData();
fft_size_ = frame1.FftSize();
log2fft_size_ = frame1.Log2FFTSize();
@@ -100,14 +100,26 @@ void FFTFrame::InterpolateFrequencyComponents(const FFTFrame& frame1,
double last_phase1 = 0.0;
double last_phase2 = 0.0;
- real_p[0] = static_cast<float>(s1base * real_p1[0] + s2base * real_p2[0]);
- imag_p[0] = static_cast<float>(s1base * imag_p1[0] + s2base * imag_p2[0]);
+ const float* real_p1_data = real1.Data();
+ const float* real_p2_data = real2.Data();
+ const float* imag_p1_data = imag1.Data();
+ const float* imag_p2_data = imag2.Data();
+
+ real[0] = static_cast<float>(s1base * real_p1_data[0] +
+ s2base * real_p2_data[0]);
+ imag[0] = static_cast<float>(s1base * imag_p1_data[0] +
+ s2base * imag_p2_data[0]);
int n = fft_size_ / 2;
+ DCHECK_GE(real1.size(), static_cast<uint32_t>(n));
+ DCHECK_GE(imag1.size(), static_cast<uint32_t>(n));
+ DCHECK_GE(real2.size(), static_cast<uint32_t>(n));
+ DCHECK_GE(imag2.size(), static_cast<uint32_t>(n));
+
for (int i = 1; i < n; ++i) {
- std::complex<double> c1(real_p1[i], imag_p1[i]);
- std::complex<double> c2(real_p2[i], imag_p2[i]);
+ std::complex<double> c1(real_p1_data[i], imag_p1_data[i]);
+ std::complex<double> c2(real_p2_data[i], imag_p2_data[i]);
double mag1 = abs(c1);
double mag2 = abs(c2);
@@ -178,14 +190,14 @@ void FFTFrame::InterpolateFrequencyComponents(const FFTFrame& frame1,
std::complex<double> c = std::polar(mag, phase_accum);
- real_p[i] = static_cast<float>(c.real());
- imag_p[i] = static_cast<float>(c.imag());
+ real[i] = static_cast<float>(c.real());
+ imag[i] = static_cast<float>(c.imag());
}
}
double FFTFrame::ExtractAverageGroupDelay() {
- float* real_p = RealData();
- float* imag_p = ImagData();
+ AudioFloatArray& real = RealData();
+ AudioFloatArray& imag = ImagData();
double ave_sum = 0.0;
double weight_sum = 0.0;
@@ -198,7 +210,7 @@ double FFTFrame::ExtractAverageGroupDelay() {
// Calculate weighted average group delay
for (int i = 0; i < half_size; i++) {
- std::complex<double> c(real_p[i], imag_p[i]);
+ std::complex<double> c(real[i], imag[i]);
double mag = abs(c);
double phase = arg(c);
@@ -228,7 +240,7 @@ double FFTFrame::ExtractAverageGroupDelay() {
AddConstantGroupDelay(-ave_sample_delay);
// Remove DC offset
- real_p[0] = 0.0f;
+ real[0] = 0.0f;
return ave_sample_delay;
}
@@ -236,8 +248,8 @@ double FFTFrame::ExtractAverageGroupDelay() {
void FFTFrame::AddConstantGroupDelay(double sample_frame_delay) {
int half_size = FftSize() / 2;
- float* real_p = RealData();
- float* imag_p = ImagData();
+ AudioFloatArray& real = RealData();
+ AudioFloatArray& imag = ImagData();
const double sample_phase_delay =
kTwoPiDouble / static_cast<double>(FftSize());
@@ -246,7 +258,7 @@ void FFTFrame::AddConstantGroupDelay(double sample_frame_delay) {
// Add constant group delay
for (int i = 1; i < half_size; i++) {
- std::complex<double> c(real_p[i], imag_p[i]);
+ std::complex<double> c(real[i], imag[i]);
double mag = abs(c);
double phase = arg(c);
@@ -254,8 +266,8 @@ void FFTFrame::AddConstantGroupDelay(double sample_frame_delay) {
std::complex<double> c2 = std::polar(mag, phase);
- real_p[i] = static_cast<float>(c2.real());
- imag_p[i] = static_cast<float>(c2.imag());
+ real[i] = static_cast<float>(c2.real());
+ imag[i] = static_cast<float>(c2.imag());
}
}
@@ -263,21 +275,27 @@ void FFTFrame::Multiply(const FFTFrame& frame) {
FFTFrame& frame1 = *this;
const FFTFrame& frame2 = frame;
- float* real_p1 = frame1.RealData();
- float* imag_p1 = frame1.ImagData();
- const float* real_p2 = frame2.RealData();
- const float* imag_p2 = frame2.ImagData();
+ AudioFloatArray& real1 = frame1.RealData();
+ AudioFloatArray& imag1 = frame1.ImagData();
+ const AudioFloatArray& real2 = frame2.RealData();
+ const AudioFloatArray& imag2 = frame2.ImagData();
unsigned half_size = FftSize() / 2;
- float real0 = real_p1[0];
- float imag0 = imag_p1[0];
+ float real0 = real1[0];
+ float imag0 = imag1[0];
+
+ DCHECK_GE(real1.size(), half_size);
+ DCHECK_GE(imag1.size(), half_size);
+ DCHECK_GE(real2.size(), half_size);
+ DCHECK_GE(imag2.size(), half_size);
- vector_math::Zvmul(real_p1, imag_p1, real_p2, imag_p2, real_p1, imag_p1,
+ vector_math::Zvmul(real1.Data(), imag1.Data(), real2.Data(),
+ imag2.Data(), real1.Data(), imag1.Data(),
half_size);
// Multiply the packed DC/nyquist component
- real_p1[0] = real0 * real_p2[0];
- imag_p1[0] = imag0 * imag_p2[0];
+ real1[0] = real0 * real2.Data()[0];
+ imag1[0] = imag0 * imag2.Data()[0];
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_frame.h b/chromium/third_party/blink/renderer/platform/audio/fft_frame.h
index a6022b9d852..bfd2abd1548 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_frame.h
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_frame.h
@@ -38,13 +38,13 @@
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
-#if defined(OS_MACOSX)
-#include <Accelerate/Accelerate.h>
-#elif defined(WTF_USE_WEBAUDIO_FFMPEG)
+#if defined(WTF_USE_WEBAUDIO_FFMPEG)
struct RDFTContext;
#elif defined(WTF_USE_WEBAUDIO_PFFFT)
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/pffft/src/pffft.h"
+#elif defined(OS_MACOSX)
+#include <Accelerate/Accelerate.h>
#endif
namespace blink {
@@ -83,10 +83,10 @@ class PLATFORM_EXPORT FFTFrame {
// least |fft_size_| elements.
void DoInverseFFT(float* data);
- float* RealData() { return real_data_.Data(); }
- const float* RealData() const { return real_data_.Data(); }
- float* ImagData() { return imag_data_.Data(); }
- const float* ImagData() const { return imag_data_.Data(); }
+ AudioFloatArray& RealData() { return real_data_; }
+ const AudioFloatArray& RealData() const { return real_data_; }
+ AudioFloatArray& ImagData() { return imag_data_; }
+ const AudioFloatArray& ImagData() const { return imag_data_; }
unsigned FftSize() const { return fft_size_; }
unsigned Log2FFTSize() const { return log2fft_size_; }
@@ -144,7 +144,7 @@ class PLATFORM_EXPORT FFTFrame {
AudioFloatArray real_data_;
AudioFloatArray imag_data_;
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(WTF_USE_WEBAUDIO_PFFFT)
// Thin wrapper around FFTSetup so we can call the appropriate routines to
// construct or release the FFTSetup objects.
class FFTSetupDatum {
diff --git a/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc b/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc
index a4c440b1b87..cc12303b7f6 100644
--- a/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/hrtf_panner.cc
@@ -42,7 +42,7 @@ const double kMaxDelayTimeSeconds = 0.002;
const int kUninitializedAzimuth = -1;
HRTFPanner::HRTFPanner(float sample_rate, HRTFDatabaseLoader* database_loader)
- : Panner(kPanningModelHRTF),
+ : Panner(PanningModel::kHRTF),
database_loader_(database_loader),
sample_rate_(sample_rate),
crossfade_selection_(kCrossfadeSelection1),
diff --git a/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc b/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc
index 8b77f6dae3d..3315687447f 100644
--- a/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/mac/fft_frame_mac.cc
@@ -30,7 +30,7 @@
#include "build/build_config.h"
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(WTF_USE_WEBAUDIO_PFFFT)
#include "third_party/blink/renderer/platform/audio/fft_frame.h"
#include "third_party/blink/renderer/platform/audio/hrtf_panner.h"
@@ -131,8 +131,8 @@ FFTFrame::FFTFrame(const FFTFrame& frame)
// Copy/setup frame data
unsigned nbytes = sizeof(float) * fft_size_;
- memcpy(RealData(), frame.frame_.realp, nbytes);
- memcpy(ImagData(), frame.frame_.imagp, nbytes);
+ memcpy(RealData().Data(), frame.frame_.realp, nbytes);
+ memcpy(ImagData().Data(), frame.frame_.imagp, nbytes);
}
FFTFrame::~FFTFrame() {}
@@ -201,4 +201,4 @@ void FFTFrame::Cleanup() {
} // namespace blink
-#endif // #if defined(OS_MACOSX)
+#endif // #if defined(OS_MACOSX) && !defined(WTF_USE_WEBAUDIO_PFFFT)
diff --git a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc
index 97778014ac3..9f01d98e939 100644
--- a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.cc
@@ -24,8 +24,21 @@ MediaMultiChannelResampler::MediaMultiChannelResampler(
}
void MediaMultiChannelResampler::Resample(int frames,
- media::AudioBus* audio_bus) {
- resampler_->Resample(audio_bus->frames(), audio_bus);
+ blink::AudioBus* audio_bus) {
+ // Create a media::AudioBus wrapper around the memory provided by the
+ // blink::AudioBus.
+ std::unique_ptr<media::AudioBus> resampler_bus_ =
+ media::AudioBus::CreateWrapper(audio_bus->NumberOfChannels());
+ for (unsigned int i = 0; i < audio_bus->NumberOfChannels(); ++i) {
+ resampler_bus_->SetChannelData(i, audio_bus->Channel(i)->MutableData());
+ }
+ resampler_bus_->set_frames(audio_bus->length());
+ ResampleInternal(frames, resampler_bus_.get());
+}
+
+void MediaMultiChannelResampler::ResampleInternal(int frames,
+ media::AudioBus* audio_bus) {
+ resampler_->Resample(frames, audio_bus);
}
void MediaMultiChannelResampler::ProvideResamplerInput(
diff --git a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h
index 73b8b34af94..18992a98c2c 100644
--- a/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/media_multi_channel_resampler.h
@@ -31,7 +31,7 @@ class PLATFORM_EXPORT MediaMultiChannelResampler {
// frames are available to satisfy the request. |frame_delay| is the number
// of output frames already processed and can be used to estimate delay.
typedef WTF::CrossThreadRepeatingFunction<void(int frame_delay,
- AudioBus* audio_bus)>
+ blink::AudioBus* audio_bus)>
ReadCB;
public:
@@ -44,8 +44,16 @@ class PLATFORM_EXPORT MediaMultiChannelResampler {
size_t request_frames,
ReadCB read_cb);
- // Resamples |frames| of data from |read_cb_| into AudioBus.
- void Resample(int frames, media::AudioBus* audio_bus);
+ // Resamples |frames| of data from |read_cb_| into a blink::AudioBus, this
+ // requires creating a wrapper for the media::AudioBus on each call and so
+ // resampling directly into a media::AudioBus using ResampleInternal() is
+ // preferred if possible.
+ void Resample(int frames, blink::AudioBus* audio_bus);
+
+ // Resamples |frames| of data from |read_cb_| into a media::AudioBus by
+ // directly calling Resample() on the underlying
+ // media::MultiChannelResampler.
+ void ResampleInternal(int frames, media::AudioBus* audio_bus);
private:
// Wrapper method used to provide input to the media::MultiChannelResampler
diff --git a/chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.cc b/chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.cc
deleted file mode 100644
index ee5c7dac00d..00000000000
--- a/chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/audio/multi_channel_resampler.h"
-
-#include <memory>
-#include "third_party/blink/renderer/platform/audio/audio_bus.h"
-
-namespace blink {
-
-namespace {
-
-// ChannelProvider provides a single channel of audio data (one channel at a
-// time) for each channel of data provided to us in a multi-channel provider.
-
-class ChannelProvider final : public AudioSourceProvider {
- public:
- ChannelProvider(AudioSourceProvider* multi_channel_provider,
- unsigned number_of_channels)
- : multi_channel_provider_(multi_channel_provider),
- number_of_channels_(number_of_channels),
- current_channel_(0),
- frames_to_process_(0) {}
-
- // provideInput() will be called once for each channel, starting with the
- // first channel. Each time it's called, it will provide the next channel of
- // data.
- void ProvideInput(AudioBus* bus, uint32_t frames_to_process) override {
- DCHECK(bus);
- DCHECK_EQ(bus->NumberOfChannels(), 1u);
-
- // Get the data from the multi-channel provider when the first channel asks
- // for it. For subsequent channels, we can just dish out the channel data
- // from that (stored in m_multiChannelBus).
- if (!current_channel_) {
- frames_to_process_ = frames_to_process;
- multi_channel_bus_ =
- AudioBus::Create(number_of_channels_, frames_to_process);
- multi_channel_provider_->ProvideInput(multi_channel_bus_.get(),
- frames_to_process);
- }
-
- DCHECK(multi_channel_bus_.get());
- DCHECK_EQ(frames_to_process, frames_to_process_);
-
- // Copy the channel data from what we received from m_multiChannelProvider.
- DCHECK_LT(current_channel_, number_of_channels_);
- memcpy(bus->Channel(0)->MutableData(),
- multi_channel_bus_->Channel(current_channel_)->Data(),
- sizeof(float) * frames_to_process);
- ++current_channel_;
- }
-
- private:
- AudioSourceProvider* multi_channel_provider_;
- scoped_refptr<AudioBus> multi_channel_bus_;
- unsigned number_of_channels_;
- unsigned current_channel_;
- // Used to verify that all channels ask for the same amount.
- uint32_t frames_to_process_;
-};
-
-} // namespace
-
-MultiChannelResampler::MultiChannelResampler(double scale_factor,
- unsigned number_of_channels)
- : number_of_channels_(number_of_channels) {
- // Create each channel's resampler.
- for (unsigned channel_index = 0; channel_index < number_of_channels;
- ++channel_index)
- kernels_.push_back(std::make_unique<SincResampler>(scale_factor));
-}
-
-void MultiChannelResampler::Process(AudioSourceProvider* provider,
- AudioBus* destination,
- uint32_t frames_to_process) {
- // The provider can provide us with multi-channel audio data. But each of our
- // single-channel resamplers (kernels) below requires a provider which
- // provides a single unique channel of data. channelProvider wraps the
- // original multi-channel provider and dishes out one channel at a time.
- ChannelProvider channel_provider(provider, number_of_channels_);
-
- for (unsigned channel_index = 0; channel_index < number_of_channels_;
- ++channel_index) {
- // Depending on the sample-rate scale factor, and the internal buffering
- // used in a SincResampler kernel, this call to process() will only
- // sometimes call provideInput() on the channelProvider. However, if it
- // calls provideInput() for the first channel, then it will call it for the
- // remaining channels, since they all buffer in the same way and are
- // processing the same number of frames.
- kernels_[channel_index]->Process(
- &channel_provider, destination->Channel(channel_index)->MutableData(),
- frames_to_process);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.h b/chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.h
deleted file mode 100644
index 84eaa98e616..00000000000
--- a/chromium/third_party/blink/renderer/platform/audio/multi_channel_resampler.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_MULTI_CHANNEL_RESAMPLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_MULTI_CHANNEL_RESAMPLER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/audio/sinc_resampler.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class AudioBus;
-
-class PLATFORM_EXPORT MultiChannelResampler {
- USING_FAST_MALLOC(MultiChannelResampler);
-
- public:
- MultiChannelResampler(double scale_factor, unsigned number_of_channels);
-
- // Process given AudioSourceProvider for streaming applications.
- void Process(AudioSourceProvider*,
- AudioBus* destination,
- uint32_t frames_to_process);
-
- private:
- // FIXME: the mac port can have a more highly optimized implementation based
- // on CoreAudio instead of SincResampler. For now the default implementation
- // will be used on all ports.
- // https://bugs.webkit.org/show_bug.cgi?id=75118
-
- // Each channel will be resampled using a high-quality SincResampler.
- Vector<std::unique_ptr<SincResampler>> kernels_;
-
- unsigned number_of_channels_;
-
- DISALLOW_COPY_AND_ASSIGN(MultiChannelResampler);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_MULTI_CHANNEL_RESAMPLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/audio/panner.cc b/chromium/third_party/blink/renderer/platform/audio/panner.cc
index dfb9d7cf7c4..5721c6b7ccc 100644
--- a/chromium/third_party/blink/renderer/platform/audio/panner.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/panner.cc
@@ -38,16 +38,14 @@ std::unique_ptr<Panner> Panner::Create(PanningModel model,
float sample_rate,
HRTFDatabaseLoader* database_loader) {
switch (model) {
- case kPanningModelEqualPower:
+ case PanningModel::kEqualPower:
return std::make_unique<EqualPowerPanner>(sample_rate);
- case kPanningModelHRTF:
+ case PanningModel::kHRTF:
return std::make_unique<HRTFPanner>(sample_rate, database_loader);
-
- default:
- NOTREACHED();
- return nullptr;
}
+ NOTREACHED();
+ return nullptr;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/panner.h b/chromium/third_party/blink/renderer/platform/audio/panner.h
index 1b5e3357fba..b2bed74ccb7 100644
--- a/chromium/third_party/blink/renderer/platform/audio/panner.h
+++ b/chromium/third_party/blink/renderer/platform/audio/panner.h
@@ -46,10 +46,13 @@ class PLATFORM_EXPORT Panner {
USING_FAST_MALLOC(Panner);
public:
- // This values are used in histograms and should not be renumbered or deleted.
- enum { kPanningModelEqualPower = 0, kPanningModelHRTF = 1 };
-
- typedef unsigned PanningModel;
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class PanningModel {
+ kEqualPower = 0,
+ kHRTF = 1,
+ kMaxValue = kHRTF,
+ };
static std::unique_ptr<Panner> Create(PanningModel,
float sample_rate,
@@ -77,7 +80,7 @@ class PLATFORM_EXPORT Panner {
virtual bool RequiresTailProcessing() const = 0;
protected:
- Panner(PanningModel model) : panning_model_(model) {}
+ explicit Panner(PanningModel model) : panning_model_(model) {}
PanningModel panning_model_;
diff --git a/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc b/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc
index 7432ad58e2e..620188fff08 100644
--- a/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/pffft/fft_frame_pffft.cc
@@ -111,8 +111,8 @@ FFTFrame::FFTFrame(const FFTFrame& frame)
// Copy/setup frame data.
unsigned nbytes = sizeof(float) * (fft_size_ / 2);
- memcpy(RealData(), frame.RealData(), nbytes);
- memcpy(ImagData(), frame.ImagData(), nbytes);
+ memcpy(RealData().Data(), frame.RealData().Data(), nbytes);
+ memcpy(ImagData().Data(), frame.ImagData().Data(), nbytes);
}
int FFTFrame::MinFFTSize() {
diff --git a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc
index 81e8266794c..cc56b77e982 100644
--- a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc
@@ -7,9 +7,9 @@
#include <algorithm>
#include <memory>
+#include "base/metrics/histogram_functions.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -40,20 +40,16 @@ PushPullFIFO::~PushPullFIFO() {
// Capture the percentage of underflow happened based on the total pull count.
// (100 buckets of size 1) This is equivalent of
// "Media.AudioRendererMissedDeadline" metric for WebAudio.
- DEFINE_STATIC_LOCAL(
- LinearHistogram,
- fifo_underflow_percentage_histogram,
- ("WebAudio.PushPullFIFO.UnderflowPercentage", 1, 100, 101));
- fifo_underflow_percentage_histogram.Count(
+ base::UmaHistogramPercentage(
+ "WebAudio.PushPullFIFO.UnderflowPercentage",
static_cast<int32_t>(100.0 * underflow_count_ / pull_count_));
// We only collect the underflow count because no overflow can happen in the
// current implementation. This is similar to
// "Media.AudioRendererAudioGlitches" metric for WebAudio, which is a simple
// flag indicates any instance of glitches during FIFO's lifetime.
- DEFINE_STATIC_LOCAL(BooleanHistogram, fifo_underflow_glitches_histogram,
- ("WebAudio.PushPullFIFO.UnderflowGlitches"));
- fifo_underflow_glitches_histogram.Count(underflow_count_ > 0);
+ base::UmaHistogramBoolean("WebAudio.PushPullFIFO.UnderflowGlitches",
+ underflow_count_ > 0);
}
// Push the data from |input_bus| to FIFO. The size of push is determined by
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
index e56d98347f9..6a451b02b7f 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
@@ -45,7 +45,8 @@ void ActiveScriptWrappableBase::TraceActiveScriptWrappables(
if (!active_wrappable->DispatchHasPendingActivity())
continue;
- ScriptWrappable* script_wrappable = active_wrappable->ToScriptWrappable();
+ const ScriptWrappable* script_wrappable =
+ active_wrappable->ToScriptWrappable();
visitor->Trace(script_wrappable);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
index f3e3f040e61..cf158f453c5 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
@@ -31,7 +31,7 @@ class PLATFORM_EXPORT ActiveScriptWrappableBase : public GarbageCollectedMixin {
virtual bool IsContextDestroyed() const = 0;
virtual bool DispatchHasPendingActivity() const = 0;
- virtual ScriptWrappable* ToScriptWrappable() = 0;
+ virtual const ScriptWrappable* ToScriptWrappable() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ActiveScriptWrappableBase);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.cc b/chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.cc
new file mode 100644
index 00000000000..68332fece42
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.cc
@@ -0,0 +1,22 @@
+// 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 "third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h"
+
+namespace blink {
+
+// TODO(crbug.com/1051395) Actually instantiate multiple blink isolates.
+static BlinkIsolate* g_single_isolate = nullptr;
+
+BlinkIsolate* BlinkIsolate::GetCurrent() {
+ return g_single_isolate;
+}
+
+BlinkIsolate::BlinkIsolate() {
+ g_single_isolate = this;
+}
+
+BlinkIsolate::~BlinkIsolate() = default;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h b/chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h
new file mode 100644
index 00000000000..e48db29c9ac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h
@@ -0,0 +1,39 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_BLINK_ISOLATE_BLINK_ISOLATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_BLINK_ISOLATE_BLINK_ISOLATE_H_
+
+#include "third_party/blink/public/platform/web_isolate.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+// An BlinkIsolate is a memory and scheduling isolation boundary in Blink,
+// which is currently being introduced as a part of Multiple Blink Isolates
+// project.
+// TODO(crbug.com/1051790): is the tracking bug for the project.
+//
+// An Isolate will hold a distinct memory region (V8 and Oilpan heaps),
+// and a dedicated scheduler.
+class PLATFORM_EXPORT BlinkIsolate : public WebIsolate {
+ public:
+ // Get the currently active BlinkIsolate. GetCurrent() may return nullptr if
+ // there is no active BlinkIsolate.
+ // TODO(crbug.com/1051395): GetCurrent() returns the singleton BlinkIsolate
+ // instance for now, but will change once we start instantiating multiple
+ // BlinkIsolates.
+ static BlinkIsolate* GetCurrent();
+
+ BlinkIsolate();
+ ~BlinkIsolate() override;
+
+ private:
+ BlinkIsolate(const BlinkIsolate&) = delete;
+ BlinkIsolate& operator=(const BlinkIsolate&) = delete;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_BLINK_ISOLATE_BLINK_ISOLATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
index 65fe7e63b89..942043b0907 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
@@ -28,7 +28,7 @@ class PLATFORM_EXPORT CallbackFunctionBase
public:
virtual ~CallbackFunctionBase() = default;
- virtual void Trace(blink::Visitor* visitor);
+ virtual void Trace(Visitor* visitor);
v8::Local<v8::Object> CallbackObject() {
return callback_function_.NewLocal(GetIsolate());
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
index 6176390dcec..6c303236d50 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
@@ -34,7 +34,7 @@ class PLATFORM_EXPORT CallbackInterfaceBase
virtual ~CallbackInterfaceBase() = default;
- virtual void Trace(blink::Visitor*);
+ virtual void Trace(Visitor*);
// Check the identity of |callback_object_|. There can be multiple
// CallbackInterfaceBase objects that have the same |callback_object_| but
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
index 5187367c974..652ff138557 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
@@ -75,7 +75,7 @@ class PLATFORM_EXPORT CallbackMethodRetriever {
const StringView& property,
ExceptionState&);
- Member<CallbackFunctionBase> constructor_;
+ CallbackFunctionBase* constructor_;
v8::Isolate* isolate_;
v8::Local<v8::Context> current_context_;
v8::Local<v8::Object> prototype_object_;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h b/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h
index 6ee38d858ba..0d81ab9e815 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dictionary_base.h
@@ -10,6 +10,9 @@
#include "v8/include/v8.h"
namespace blink {
+
+class Visitor;
+
namespace bindings {
// This class is the base class for all IDL dictionary implementations. This is
@@ -33,6 +36,8 @@ class PLATFORM_EXPORT DictionaryBase : public GarbageCollected<DictionaryBase> {
return v8_object;
}
+ virtual void Trace(Visitor*) {}
+
protected:
DictionaryBase() = default;
@@ -41,7 +46,7 @@ class PLATFORM_EXPORT DictionaryBase : public GarbageCollected<DictionaryBase> {
DictionaryBase& operator=(const DictionaryBase&) = delete;
DictionaryBase& operator=(const DictionaryBase&&) = delete;
- virtual void FillWithMembers(v8::Isolate* isolate,
+ virtual bool FillWithMembers(v8::Isolate* isolate,
v8::Local<v8::Object> creation_context,
v8::Local<v8::Object> v8_object) const = 0;
};
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc
index 5e10e7024b2..e0b991138b5 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc
@@ -10,20 +10,16 @@ DOMDataStore::DOMDataStore(v8::Isolate* isolate, bool is_main_world)
: is_main_world_(is_main_world) {}
void DOMDataStore::Dispose() {
- for (const auto& it : wrapper_map_) {
+ for (auto& it : wrapper_map_) {
// Explicitly reset references so that a following V8 GC will not find them
// and treat them as roots. There's optimizations (see
// EmbedderHeapTracer::IsRootForNonTracingGC) that would not treat them as
// roots and then Blink would not be able to find and remove them from a DOM
// world. Explicitly resetting on disposal avoids that problem
- it.value->ref.Clear();
+ it.value.Clear();
}
}
-void DOMDataStore::WrappedReference::Trace(Visitor* visitor) {
- visitor->Trace(ref);
-}
-
void DOMDataStore::Trace(Visitor* visitor) {
visitor->Trace(wrapper_map_);
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h
index 975c6b567c9..0d8cfbc5ce7 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h
@@ -35,6 +35,7 @@
#include "base/optional.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
#include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -118,7 +119,7 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
return object->MainWorldWrapper(isolate);
auto it = wrapper_map_.find(object);
if (it != wrapper_map_.end())
- return it->value->ref.NewLocal(isolate);
+ return it->value.NewLocal(isolate);
return v8::Local<v8::Object>();
}
@@ -132,13 +133,12 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
return object->SetWrapper(isolate, wrapper_type_info, wrapper);
auto result = wrapper_map_.insert(
- object, MakeGarbageCollected<WrappedReference>(isolate, wrapper));
+ object, TraceWrapperV8Reference<v8::Object>(isolate, wrapper));
if (LIKELY(result.is_new_entry)) {
- wrapper_type_info->ConfigureWrapper(
- &result.stored_value->value->ref.Get());
+ wrapper_type_info->ConfigureWrapper(&result.stored_value->value.Get());
} else {
- DCHECK(!result.stored_value->value->ref.IsEmpty());
- wrapper = result.stored_value->value->ref.NewLocal(isolate);
+ DCHECK(!result.stored_value->value.IsEmpty());
+ wrapper = result.stored_value->value.NewLocal(isolate);
}
return result.is_new_entry;
}
@@ -149,8 +149,8 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
DCHECK(!is_main_world_);
const auto& it = wrapper_map_.find(object);
if (it != wrapper_map_.end()) {
- if (it->value->ref.Get() == handle) {
- it->value->ref.Clear();
+ if (it->value.Get() == handle) {
+ it->value.Clear();
wrapper_map_.erase(it);
return true;
}
@@ -164,7 +164,7 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
return object->SetReturnValue(return_value);
auto it = wrapper_map_.find(object);
if (it != wrapper_map_.end()) {
- return_value.Set(it->value->ref.Get());
+ return_value.Set(it->value.Get());
return true;
}
return false;
@@ -198,24 +198,10 @@ class DOMDataStore final : public GarbageCollected<DOMDataStore> {
return wrappable->IsEqualTo(holder);
}
- // Wrapper around TraceWrapperV8Reference to allow use in ephemeron hash map
- // below.
- class PLATFORM_EXPORT WrappedReference final
- : public GarbageCollected<WrappedReference> {
- public:
- WrappedReference() = default;
- WrappedReference(v8::Isolate* isolate, v8::Local<v8::Object> handle)
- : ref(isolate, handle) {}
-
- virtual void Trace(Visitor*);
-
- TraceWrapperV8Reference<v8::Object> ref;
- };
-
bool is_main_world_;
- // Ephemeron map: WrappedReference will be kept alive as long as
- // ScriptWrappable is alive.
- HeapHashMap<WeakMember<const ScriptWrappable>, Member<WrappedReference>>
+ // Ephemeron map: V8 wrapper will be kept alive as long as ScriptWrappable is.
+ HeapHashMap<WeakMember<const ScriptWrappable>,
+ TraceWrapperV8Reference<v8::Object>>
wrapper_map_;
DISALLOW_COPY_AND_ASSIGN(DOMDataStore);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h b/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h
new file mode 100644
index 00000000000..f5e0fcf185a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/enumeration_base.h
@@ -0,0 +1,92 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ENUMERATION_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ENUMERATION_BASE_H_
+
+#include <type_traits>
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+namespace bindings {
+
+class PLATFORM_EXPORT EnumerationBase {
+ DISALLOW_NEW();
+
+ public:
+ ~EnumerationBase() = default;
+
+ const char* AsCStr() const { return string_literal_; }
+ String AsString() const { return string_literal_; }
+
+ // Migration adapter
+ operator AtomicString() const { return string_literal_; }
+ operator String() const { return string_literal_; }
+
+ // Returns true if the value is invalid. The instance in this state must be
+ // created only when an exception is thrown.
+ bool IsEmpty() const { return !string_literal_; }
+
+ protected:
+ // Integer type that is convertible from/to enum values defined in subclasses.
+ using enum_int_t = size_t;
+
+ constexpr EnumerationBase() = default;
+ explicit constexpr EnumerationBase(enum_int_t enum_value,
+ const char* string_literal)
+ : enum_value_(enum_value), string_literal_(string_literal) {}
+ constexpr EnumerationBase(const EnumerationBase&) = default;
+ constexpr EnumerationBase(EnumerationBase&&) = default;
+
+ EnumerationBase& operator=(const EnumerationBase&) = default;
+ EnumerationBase& operator=(EnumerationBase&&) = default;
+
+ enum_int_t GetEnumValue() const { return enum_value_; }
+
+ private:
+ // Subclasses are supposed to define a C++ enum class and a table of strings
+ // that represent IDL enumeration values. |enum_value_| is an enum value of
+ // the C++ enum class (must be convertible from/to enum_int_t) and
+ // |string_literal_| is a pointer to a string in the table.
+ enum_int_t enum_value_ = 0;
+ const char* string_literal_ = nullptr;
+
+ template <typename T>
+ friend typename std::
+ enable_if_t<std::is_base_of<bindings::EnumerationBase, T>::value, bool>
+ operator==(const T& lhs, const T& rhs);
+
+ template <typename T>
+ friend typename std::
+ enable_if_t<std::is_base_of<bindings::EnumerationBase, T>::value, bool>
+ operator!=(const T& lhs, const T& rhs);
+};
+
+} // namespace bindings
+
+template <typename T>
+typename std::enable_if_t<std::is_base_of<bindings::EnumerationBase, T>::value,
+ bool>
+operator==(const T& lhs, const T& rhs) {
+ DCHECK(!lhs.IsEmpty() && !rhs.IsEmpty());
+ return lhs.string_literal_ == rhs.string_literal_;
+}
+
+template <typename T>
+typename std::enable_if_t<std::is_base_of<bindings::EnumerationBase, T>::value,
+ bool>
+operator!=(const T& lhs, const T& rhs) {
+ DCHECK(!lhs.IsEmpty() && !rhs.IsEmpty());
+ return lhs.string_literal_ != rhs.string_literal_;
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ENUMERATION_BASE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
index c9f4ac49bd9..e2f8e5672d6 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
@@ -186,6 +186,18 @@ enum class ParkableStringImpl::Status : uint8_t {
kLocked
};
+ParkableStringImpl::ParkableMetadata::ParkableMetadata(
+ String string,
+ std::unique_ptr<SecureDigest> digest)
+ : mutex_(),
+ lock_depth_(0),
+ state_(State::kUnparked),
+ compressed_(nullptr),
+ digest_(*digest),
+ is_young_(true),
+ is_8bit_(string.Is8Bit()),
+ length_(string.length()) {}
+
// static
std::unique_ptr<ParkableStringImpl::SecureDigest>
ParkableStringImpl::HashString(StringImpl* string) {
@@ -224,15 +236,10 @@ scoped_refptr<ParkableStringImpl> ParkableStringImpl::MakeParkable(
ParkableStringImpl::ParkableStringImpl(scoped_refptr<StringImpl>&& impl,
std::unique_ptr<SecureDigest> digest)
- : mutex_(),
- lock_depth_(0),
- state_(State::kUnparked),
- string_(std::move(impl)),
- compressed_(nullptr),
- digest_(std::move(digest)),
- is_young_(true),
- is_8bit_(string_.Is8Bit()),
- length_(string_.length())
+ : string_(std::move(impl)),
+ metadata_(digest ? std::make_unique<ParkableMetadata>(string_,
+ std::move(digest))
+ : nullptr)
#if DCHECK_IS_ON()
,
owning_thread_(CurrentThread())
@@ -248,7 +255,8 @@ ParkableStringImpl::~ParkableStringImpl() {
DCHECK_EQ(0, lock_depth_for_testing());
AsanUnpoisonString(string_);
- DCHECK(state_ == State::kParked || state_ == State::kUnparked);
+ DCHECK(metadata_->state_ == State::kParked ||
+ metadata_->state_ == State::kUnparked);
ParkableStringManager::Instance().Remove(this);
}
@@ -257,8 +265,8 @@ void ParkableStringImpl::Lock() {
if (!may_be_parked())
return;
- MutexLocker locker(mutex_);
- lock_depth_ += 1;
+ MutexLocker locker(metadata_->mutex_);
+ metadata_->lock_depth_ += 1;
// Make young as this is a strong (but not certain) indication that the string
// will be accessed soon.
MakeYoung();
@@ -268,8 +276,8 @@ void ParkableStringImpl::Lock() {
void ParkableStringImpl::LockWithoutMakingYoung() {
DCHECK(may_be_parked());
- MutexLocker locker(mutex_);
- lock_depth_ += 1;
+ MutexLocker locker(metadata_->mutex_);
+ metadata_->lock_depth_ += 1;
}
#endif // defined(ADDRESS_SANITIZER)
@@ -278,9 +286,9 @@ void ParkableStringImpl::Unlock() {
if (!may_be_parked())
return;
- MutexLocker locker(mutex_);
- DCHECK_GT(lock_depth_, 0);
- lock_depth_ -= 1;
+ MutexLocker locker(metadata_->mutex_);
+ DCHECK_GT(metadata_->lock_depth_, 0);
+ metadata_->lock_depth_ -= 1;
#if defined(ADDRESS_SANITIZER) && DCHECK_IS_ON()
// There are no external references to the data, nobody should touch the data.
@@ -302,13 +310,8 @@ void ParkableStringImpl::Unlock() {
void ParkableStringImpl::PurgeMemory() {
AssertOnValidThread();
- if (state_ == State::kUnparked)
- compressed_ = nullptr;
-}
-
-void ParkableStringImpl::MakeYoung() {
- mutex_.AssertAcquired();
- is_young_ = true;
+ if (metadata_->state_ == State::kUnparked)
+ metadata_->compressed_ = nullptr;
}
const String& ParkableStringImpl::ToString() {
@@ -316,7 +319,7 @@ const String& ParkableStringImpl::ToString() {
if (!may_be_parked())
return string_;
- MutexLocker locker(mutex_);
+ MutexLocker locker(metadata_->mutex_);
MakeYoung();
AsanUnpoisonString(string_);
Unpark();
@@ -325,21 +328,42 @@ const String& ParkableStringImpl::ToString() {
unsigned ParkableStringImpl::CharactersSizeInBytes() const {
AssertOnValidThread();
- return length_ * (is_8bit() ? sizeof(LChar) : sizeof(UChar));
+ if (!may_be_parked())
+ return string_.CharactersSizeInBytes();
+
+ return metadata_->length_ * (is_8bit() ? sizeof(LChar) : sizeof(UChar));
+}
+
+size_t ParkableStringImpl::MemoryFootprintForDump() const {
+ AssertOnValidThread();
+ size_t size = sizeof(ParkableStringImpl);
+
+ if (!may_be_parked())
+ return size + string_.CharactersSizeInBytes();
+
+ size += sizeof(ParkableMetadata);
+
+ if (!is_parked())
+ size += string_.CharactersSizeInBytes();
+
+ if (metadata_->compressed_)
+ size += metadata_->compressed_->size();
+
+ return size;
}
ParkableStringImpl::AgeOrParkResult ParkableStringImpl::MaybeAgeOrParkString() {
- MutexLocker locker(mutex_);
+ MutexLocker locker(metadata_->mutex_);
AssertOnValidThread();
DCHECK(may_be_parked());
DCHECK(!is_parked());
Status status = CurrentStatus();
- if (is_young_) {
+ if (metadata_->is_young_) {
if (status == Status::kUnreferencedExternally)
- is_young_ = false;
+ metadata_->is_young_ = false;
} else {
- if (state_ == State::kParkingInProgress)
+ if (metadata_->state_ == State::kParkingInProgress)
return AgeOrParkResult::kSuccessOrTransientFailure;
if (CanParkNow()) {
@@ -356,16 +380,17 @@ ParkableStringImpl::AgeOrParkResult ParkableStringImpl::MaybeAgeOrParkString() {
}
bool ParkableStringImpl::Park(ParkingMode mode) {
- MutexLocker locker(mutex_);
+ MutexLocker locker(metadata_->mutex_);
AssertOnValidThread();
DCHECK(may_be_parked());
- if (state_ == State::kParkingInProgress || state_ == State::kParked)
+ if (metadata_->state_ == State::kParkingInProgress ||
+ metadata_->state_ == State::kParked)
return true;
// Making the string old to cancel parking if it is accessed/locked before
// parking is complete.
- is_young_ = false;
+ metadata_->is_young_ = false;
if (!CanParkNow())
return false;
@@ -373,15 +398,42 @@ bool ParkableStringImpl::Park(ParkingMode mode) {
return true;
}
+bool ParkableStringImpl::is_parked() const {
+ DCHECK(may_be_parked());
+ return metadata_->state_ == State::kParked;
+}
+
+void ParkableStringImpl::MakeYoung() {
+ metadata_->is_young_ = true;
+}
+
+ParkableStringImpl::Status ParkableStringImpl::CurrentStatus() const {
+ AssertOnValidThread();
+ DCHECK(may_be_parked());
+ // Can park iff:
+ // - |this| is not locked.
+ // - There are no external reference to |string_|. Since |this| holds a
+ // reference to |string_|, it must the only one.
+ if (metadata_->lock_depth_ != 0)
+ return Status::kLocked;
+ if (!string_.Impl()->HasOneRef())
+ return Status::kTooManyReferences;
+ return Status::kUnreferencedExternally;
+}
+
+bool ParkableStringImpl::CanParkNow() const {
+ return CurrentStatus() == Status::kUnreferencedExternally &&
+ !metadata_->is_young_;
+}
+
void ParkableStringImpl::ParkInternal(ParkingMode mode) {
- mutex_.AssertAcquired();
- DCHECK_EQ(State::kUnparked, state_);
- DCHECK(!is_young_);
+ DCHECK_EQ(State::kUnparked, metadata_->state_);
+ DCHECK(!metadata_->is_young_);
DCHECK(CanParkNow());
// Parking can proceed synchronously.
if (has_compressed_data()) {
- state_ = State::kParked;
+ metadata_->state_ = State::kParked;
ParkableStringManager::Instance().OnParked(this);
// Must unpoison the memory before releasing it.
@@ -398,45 +450,21 @@ void ParkableStringImpl::ParkInternal(ParkingMode mode) {
FROM_HERE,
CrossThreadBindOnce(&ParkableStringImpl::CompressInBackground,
WTF::Passed(std::move(params))));
- state_ = State::kParkingInProgress;
+ metadata_->state_ = State::kParkingInProgress;
}
}
-bool ParkableStringImpl::is_parked() const {
- return state_ == State::kParked;
-}
-
-ParkableStringImpl::Status ParkableStringImpl::CurrentStatus() const {
- AssertOnValidThread();
- mutex_.AssertAcquired();
- DCHECK(may_be_parked());
- // Can park iff:
- // - |this| is not locked.
- // - There are no external reference to |string_|. Since |this| holds a
- // reference to |string_|, it must the only one.
- if (lock_depth_ != 0)
- return Status::kLocked;
- if (!string_.Impl()->HasOneRef())
- return Status::kTooManyReferences;
- return Status::kUnreferencedExternally;
-}
-
-bool ParkableStringImpl::CanParkNow() const {
- return CurrentStatus() == Status::kUnreferencedExternally && !is_young_;
-}
-
void ParkableStringImpl::Unpark() {
AssertOnValidThread();
DCHECK(may_be_parked());
- mutex_.AssertAcquired();
- if (state_ != State::kParked)
+ if (metadata_->state_ != State::kParked)
return;
TRACE_EVENT1("blink", "ParkableStringImpl::Unpark", "size",
CharactersSizeInBytes());
- DCHECK(compressed_);
+ DCHECK(metadata_->compressed_);
string_ = UnparkInternal();
- state_ = State::kUnparked;
+ metadata_->state_ = State::kUnparked;
ParkableStringManager::Instance().OnUnparked(this);
}
@@ -448,8 +476,8 @@ String ParkableStringImpl::UnparkInternal() const {
base::ElapsedTimer timer;
base::StringPiece compressed_string_piece(
- reinterpret_cast<const char*>(compressed_->data()),
- compressed_->size() * sizeof(uint8_t));
+ reinterpret_cast<const char*>(metadata_->compressed_->data()),
+ metadata_->compressed_->size() * sizeof(uint8_t));
String uncompressed;
base::StringPiece uncompressed_string_piece;
size_t size = CharactersSizeInBytes();
@@ -491,15 +519,15 @@ void ParkableStringImpl::OnParkingCompleteOnMainThread(
std::unique_ptr<CompressionTaskParams> params,
std::unique_ptr<Vector<uint8_t>> compressed,
base::TimeDelta parking_thread_time) {
- MutexLocker locker(mutex_);
- DCHECK_EQ(State::kParkingInProgress, state_);
+ MutexLocker locker(metadata_->mutex_);
+ DCHECK_EQ(State::kParkingInProgress, metadata_->state_);
// Always keep the compressed data. Compression is expensive, so even if the
// uncompressed representation cannot be discarded now, avoid compressing
// multiple times. This will allow synchronous parking next time.
- DCHECK(!compressed_);
+ DCHECK(!metadata_->compressed_);
if (compressed)
- compressed_ = std::move(compressed);
+ metadata_->compressed_ = std::move(compressed);
// Between |Park()| and now, things may have happened:
// 1. |ToString()| or
@@ -507,15 +535,15 @@ void ParkableStringImpl::OnParkingCompleteOnMainThread(
//
// Both of these will make the string young again, and if so we don't
// discard the compressed representation yet.
- if (CanParkNow() && compressed_) {
- state_ = State::kParked;
+ if (CanParkNow() && metadata_->compressed_) {
+ metadata_->state_ = State::kParked;
ParkableStringManager::Instance().OnParked(this);
// Must unpoison the memory before releasing it.
AsanUnpoisonString(string_);
string_ = String();
} else {
- state_ = State::kUnparked;
+ metadata_->state_ = State::kUnparked;
}
// Record the time no matter whether the string was parked or not, as the
// parking cost was paid.
@@ -606,6 +634,7 @@ void ParkableStringImpl::CompressInBackground(
RecordStatistics(size, timer.Elapsed(), ParkingAction::kParked);
}
+
ParkableString::ParkableString(scoped_refptr<StringImpl>&& impl) {
if (!impl) {
impl_ = nullptr;
@@ -634,14 +663,16 @@ void ParkableString::Unlock() const {
void ParkableString::OnMemoryDump(WebProcessMemoryDump* pmd,
const String& name) const {
- // Parkable strings are reported by ParkableStringManager.
- if (!impl_ || may_be_parked())
+ if (!impl_)
return;
auto* dump = pmd->CreateMemoryAllocatorDump(name);
- dump->AddScalar("size", "bytes", CharactersSizeInBytes());
- pmd->AddSuballocation(dump->Guid(),
- String(WTF::Partitions::kAllocatedObjectPoolName));
+ dump->AddScalar("size", "bytes", impl_->MemoryFootprintForDump());
+
+ const char* parent_allocation =
+ may_be_parked() ? ParkableStringManager::kAllocatorDumpName
+ : WTF::Partitions::kAllocatedObjectPoolName;
+ pmd->AddSuballocation(dump->Guid(), parent_allocation);
}
bool ParkableString::Is8Bit() const {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
index cd1b5ee2be8..b9d2bd8ef62 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
@@ -72,9 +72,29 @@ class PLATFORM_EXPORT ParkableStringImpl final
const String& ToString();
// See the matching String methods.
- bool is_8bit() const { return is_8bit_; }
- unsigned length() const { return length_; }
+ bool is_8bit() const {
+ if (!may_be_parked())
+ return string_.Is8Bit();
+
+ return metadata_->is_8bit_;
+ }
+ unsigned length() const {
+ if (!may_be_parked())
+ return string_.length();
+
+ return metadata_->length_;
+ }
unsigned CharactersSizeInBytes() const;
+ size_t MemoryFootprintForDump() const;
+
+ // Returns true iff the string can be parked. This does not mean that the
+ // string can be parked now, merely that it is eligible to be parked at some
+ // point.
+ bool may_be_parked() const { return !!metadata_; }
+
+ // Note: Public member functions below must only be called on strings for
+ // which |may_be_parked()| returns true. Otherwise, these will either trigger
+ // a DCHECK() or crash.
// Tries to either age or park a string:
//
@@ -98,32 +118,30 @@ class PLATFORM_EXPORT ParkableStringImpl final
//
// Returns true if the string is being parked or has been parked.
bool Park(ParkingMode mode);
- // Returns true iff the string can be parked. This does not mean that the
- // string can be parked now, merely that it is eligible to be parked at some
- // point.
- bool may_be_parked() const { return !!digest_; }
+
// Returns true if the string is parked.
bool is_parked() const;
+
// Returns whether synchronous parking is possible, that is the string was
// parked in the past.
- bool has_compressed_data() const { return !!compressed_; }
+ bool has_compressed_data() const { return !!metadata_->compressed_; }
+
// Returns the compressed size, must not be called unless the string has a
// compressed representation.
size_t compressed_size() const {
DCHECK(has_compressed_data());
- return compressed_->size();
+ return metadata_->compressed_->size();
}
bool is_young_for_testing() {
- MutexLocker locker(mutex_);
- return is_young_;
+ MutexLocker locker(metadata_->mutex_);
+ return metadata_->is_young_;
}
- // Must only be called on parkable ParkableStringImpls.
- SecureDigest* digest() const {
+ const SecureDigest* digest() const {
AssertOnValidThread();
- DCHECK(digest_);
- return digest_.get();
+ DCHECK(metadata_);
+ return &metadata_->digest_;
}
private:
@@ -136,20 +154,25 @@ class PLATFORM_EXPORT ParkableStringImpl final
ParkableStringImpl(scoped_refptr<StringImpl>&& impl,
std::unique_ptr<SecureDigest> digest);
+ // Note: Private member functions below must only be called on strings for
+ // which |may_be_parked()| returns true. Otherwise, these will either trigger
+ // a DCHECK() or crash.
+
#if defined(ADDRESS_SANITIZER)
// See |CompressInBackground()|. Doesn't make the string young.
// May be called from any thread.
void LockWithoutMakingYoung();
#endif // defined(ADDRESS_SANITIZER)
// May be called from any thread.
- void MakeYoung() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ void MakeYoung() EXCLUSIVE_LOCKS_REQUIRED(metadata_->mutex_);
// Whether the string is referenced or locked. The return value is valid as
// long as |mutex_| is held.
- Status CurrentStatus() const EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- bool CanParkNow() const EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- void ParkInternal(ParkingMode mode);
- void Unpark();
- String UnparkInternal() const;
+ Status CurrentStatus() const EXCLUSIVE_LOCKS_REQUIRED(metadata_->mutex_);
+ bool CanParkNow() const EXCLUSIVE_LOCKS_REQUIRED(metadata_->mutex_);
+ void ParkInternal(ParkingMode mode)
+ EXCLUSIVE_LOCKS_REQUIRED(metadata_->mutex_);
+ void Unpark() EXCLUSIVE_LOCKS_REQUIRED(metadata_->mutex_);
+ String UnparkInternal() const EXCLUSIVE_LOCKS_REQUIRED(metadata_->mutex_);
// Called on the main thread after compression is done.
// |params| is the same as the one passed to |CompressInBackground()|,
// |compressed| is the compressed data, nullptr if compression failed.
@@ -164,31 +187,40 @@ class PLATFORM_EXPORT ParkableStringImpl final
static void CompressInBackground(std::unique_ptr<CompressionTaskParams>);
int lock_depth_for_testing() {
- MutexLocker locker_(mutex_);
- return lock_depth_;
+ MutexLocker locker_(metadata_->mutex_);
+ return metadata_->lock_depth_;
}
- Mutex mutex_;
- int lock_depth_ GUARDED_BY(mutex_);
+ // Metadata only used for parkable ParkableStrings.
+ struct ParkableMetadata {
+ ParkableMetadata(String string, std::unique_ptr<SecureDigest> digest);
+
+ Mutex mutex_;
+ int lock_depth_ GUARDED_BY(mutex_);
+
+ // Main thread only.
+ State state_;
+ std::unique_ptr<Vector<uint8_t>> compressed_;
+ const SecureDigest digest_;
+
+ // A string can either be "young" or "old". It starts young, and transitions
+ // are:
+ // Young -> Old: By calling |MaybeAgeOrParkString()|.
+ // Old -> Young: When the string is accessed, either by |Lock()|-ing it or
+ // calling |ToString()|.
+ //
+ // Thread safety: it is typically not safe to guard only one part of a
+ // bitfield with a mutex, but this is correct here, as the other members are
+ // const (and never change).
+ bool is_young_ : 1 GUARDED_BY(mutex_);
+ const bool is_8bit_ : 1;
+ const unsigned length_;
+
+ DISALLOW_COPY_AND_ASSIGN(ParkableMetadata);
+ };
- // Main thread only.
- State state_;
String string_;
- std::unique_ptr<Vector<uint8_t>> compressed_;
- const std::unique_ptr<SecureDigest> digest_;
-
- // A string can either be "young" or "old". It starts young, and transitions
- // are:
- // Young -> Old: By calling |MaybeAgeOrParkString()|.
- // Old -> Young: When the string is accessed, either by |Lock()|-ing it or
- // calling |ToString()|.
- //
- // Thread safety: it is typically not safe to guard only one part of a
- // bitfield with a mutex, but this is correct here, as the other members are
- // const (and never change).
- bool is_young_ : 1 GUARDED_BY(mutex_);
- const bool is_8bit_ : 1;
- const unsigned length_;
+ const std::unique_ptr<ParkableMetadata> metadata_;
#if DCHECK_IS_ON()
const base::PlatformThreadId owning_thread_;
@@ -200,13 +232,26 @@ class PLATFORM_EXPORT ParkableStringImpl final
#endif
}
- FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockUnlock);
- FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockParkedString);
+ public:
FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, Equality);
FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, EqualityNoUnparking);
+ FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockUnlock);
+ FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockParkedString);
+ FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, ReportMemoryDump);
+ FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, MemoryFootprintForDump);
+
DISALLOW_COPY_AND_ASSIGN(ParkableStringImpl);
};
+#if !DCHECK_IS_ON()
+// 3 pointers:
+// - vtable (from RefCounted)
+// - string_.Impl()
+// - metadata_
+static_assert(sizeof(ParkableStringImpl) == 3 * sizeof(void*),
+ "ParkableStringImpl should not be too large");
+#endif
+
class PLATFORM_EXPORT ParkableString final {
DISALLOW_NEW();
@@ -249,6 +294,9 @@ class PLATFORM_EXPORT ParkableString final {
scoped_refptr<ParkableStringImpl> impl_;
};
+static_assert(sizeof(ParkableString) == sizeof(void*),
+ "ParkableString should be small");
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_PARKABLE_STRING_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
index 45da38a8126..dd987fac607 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
@@ -62,17 +62,20 @@ class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>,
} // namespace
+const char* ParkableStringManager::kAllocatorDumpName = "parkable_strings";
+
// Compares not the pointers, but the arrays. Uses pointers to save space.
struct ParkableStringManager::SecureDigestHash {
STATIC_ONLY(SecureDigestHash);
- static unsigned GetHash(ParkableStringImpl::SecureDigest* const digest) {
+ static unsigned GetHash(
+ const ParkableStringImpl::SecureDigest* const digest) {
// The first bytes of the hash are as good as anything else.
return *reinterpret_cast<const unsigned*>(digest->data());
}
- static inline bool Equal(ParkableStringImpl::SecureDigest* const a,
- ParkableStringImpl::SecureDigest* const b) {
+ static inline bool Equal(const ParkableStringImpl::SecureDigest* const a,
+ const ParkableStringImpl::SecureDigest* const b) {
return a == b ||
std::equal(a->data(), a->data() + ParkableStringImpl::kDigestSize,
b->data());
@@ -121,7 +124,7 @@ bool ParkableStringManager::OnMemoryDump(
base::trace_event::ProcessMemoryDump* pmd) {
DCHECK(IsMainThread());
base::trace_event::MemoryAllocatorDump* dump =
- pmd->CreateAllocatorDump("parkable_strings");
+ pmd->CreateAllocatorDump(kAllocatorDumpName);
Statistics stats = ComputeStatistics();
@@ -375,7 +378,7 @@ ParkableStringManager::Statistics ParkableStringManager::ComputeStatistics()
// The digest has an inline capacity set to the digest size, hence sizeof() is
// accurate.
constexpr size_t kParkableStringImplActualSize =
- sizeof(ParkableStringImpl) + sizeof(ParkableStringImpl::SecureDigest);
+ sizeof(ParkableStringImpl) + sizeof(ParkableStringImpl::ParkableMetadata);
for (const auto& kv : unparked_strings_) {
ParkableStringImpl* str = kv.value;
@@ -386,6 +389,15 @@ ParkableStringManager::Statistics ParkableStringManager::ComputeStatistics()
if (str->has_compressed_data())
stats.overhead_size += str->compressed_size();
+
+ // Since ParkableStringManager wants to have a finer breakdown of memory
+ // footprint, this doesn't directly use
+ // |ParkableStringImpl::MemoryFootprintForDump()|. However we want the two
+ // computations to be consistent, hence the DCHECK().
+ size_t memory_footprint =
+ (str->has_compressed_data() ? str->compressed_size() : 0) + size +
+ kParkableStringImplActualSize;
+ DCHECK_EQ(memory_footprint, str->MemoryFootprintForDump());
}
for (const auto& kv : parked_strings_) {
@@ -395,6 +407,11 @@ ParkableStringManager::Statistics ParkableStringManager::ComputeStatistics()
stats.original_size += size;
stats.compressed_size += str->compressed_size();
stats.metadata_size += kParkableStringImplActualSize;
+
+ // See comment above.
+ size_t memory_footprint =
+ str->compressed_size() + kParkableStringImplActualSize;
+ DCHECK_EQ(memory_footprint, str->MemoryFootprintForDump());
}
stats.total_size = stats.uncompressed_size + stats.compressed_size +
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
index ecc958b620f..e7fd7298c4d 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
@@ -67,6 +67,8 @@ class PLATFORM_EXPORT ParkableStringManager {
// Public for testing.
constexpr static int kAgingIntervalInSeconds = 2;
+ static const char* kAllocatorDumpName;
+
private:
friend class ParkableString;
friend class ParkableStringImpl;
@@ -102,11 +104,11 @@ class PLATFORM_EXPORT ParkableStringManager {
// Relies on secure hash equality for deduplication. If one day SHA256 becomes
// insecure, then this would need to be updated to a more robust hash.
- WTF::HashMap<ParkableStringImpl::SecureDigest*,
+ WTF::HashMap<const ParkableStringImpl::SecureDigest*,
ParkableStringImpl*,
SecureDigestHash>
unparked_strings_;
- WTF::HashMap<ParkableStringImpl::SecureDigest*,
+ WTF::HashMap<const ParkableStringImpl::SecureDigest*,
ParkableStringImpl*,
SecureDigestHash>
parked_strings_;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
index a6b796743d6..a1e7a6a9e6c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
@@ -611,6 +611,9 @@ TEST_F(ParkableStringTest, ReportMemoryDump) {
using testing::Contains;
using testing::Eq;
+ constexpr size_t kActualSize =
+ sizeof(ParkableStringImpl) + sizeof(ParkableStringImpl::ParkableMetadata);
+
auto& manager = ParkableStringManager::Instance();
ParkableString parkable1(MakeLargeString('a').ReleaseImpl());
ParkableString parkable2(MakeLargeString('b').ReleaseImpl());
@@ -647,29 +650,53 @@ TEST_F(ParkableStringTest, ReportMemoryDump) {
kCompressedSize);
EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(overhead))));
- constexpr size_t kParkableStringImplActualSize =
- sizeof(ParkableStringImpl) + sizeof(ParkableStringImpl::SecureDigest);
MemoryAllocatorDump::Entry metadata("metadata_size", "bytes",
- 2 * kParkableStringImplActualSize);
+ 2 * kActualSize);
EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(metadata))));
MemoryAllocatorDump::Entry savings(
"savings_size", "bytes",
- 2 * kStringSize - (kStringSize + 2 * kCompressedSize +
- 2 * kParkableStringImplActualSize));
+ 2 * kStringSize - (kStringSize + 2 * kCompressedSize + 2 * kActualSize));
EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(savings))));
}
+TEST_F(ParkableStringTest, MemoryFootprintForDump) {
+ constexpr size_t kActualSize =
+ sizeof(ParkableStringImpl) + sizeof(ParkableStringImpl::ParkableMetadata);
+
+ size_t memory_footprint;
+ ParkableString parkable1(MakeLargeString('a').ReleaseImpl());
+ ParkableString parkable2(MakeLargeString('b').ReleaseImpl());
+ ParkableString parkable3(String("short string, not parkable").ReleaseImpl());
+
+ WaitForDelayedParking();
+ parkable1.ToString();
+
+ // Compressed and uncompressed data.
+ memory_footprint = kActualSize + parkable1.Impl()->compressed_size() +
+ parkable1.Impl()->CharactersSizeInBytes();
+ EXPECT_EQ(memory_footprint, parkable1.Impl()->MemoryFootprintForDump());
+
+ // Compressed uncompressed data only.
+ memory_footprint = kActualSize + parkable2.Impl()->compressed_size();
+ EXPECT_EQ(memory_footprint, parkable2.Impl()->MemoryFootprintForDump());
+
+ // Short string, no metadata.
+ memory_footprint =
+ sizeof(ParkableStringImpl) + parkable3.Impl()->CharactersSizeInBytes();
+ EXPECT_EQ(memory_footprint, parkable3.Impl()->MemoryFootprintForDump());
+}
+
TEST_F(ParkableStringTest, CompressionDisabled) {
base::test::ScopedFeatureList features;
features.InitAndDisableFeature(kCompressParkableStrings);
ParkableString parkable(MakeLargeString().ReleaseImpl());
WaitForDelayedParking();
- EXPECT_FALSE(parkable.Impl()->is_parked());
+ EXPECT_FALSE(parkable.Impl()->may_be_parked());
MemoryPressureListenerRegistry::Instance().OnPurgeMemory();
- EXPECT_FALSE(parkable.Impl()->is_parked());
+ EXPECT_FALSE(parkable.Impl()->may_be_parked());
}
TEST_F(ParkableStringTest, Aging) {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
index d898c3c5280..99a79bb2eb2 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
@@ -23,6 +23,10 @@
#include "third_party/blink/renderer/platform/wtf/vector.h"
#endif
+#if BUILDFLAG(BLINK_BINDINGS_TRACE_ENABLED)
+#include "base/trace_event/trace_event.h"
+#endif
+
namespace base {
class TickClock;
}
@@ -167,6 +171,15 @@ class PLATFORM_EXPORT RuntimeCallTimer {
} while (false)
#endif
+#if BUILDFLAG(BLINK_BINDINGS_TRACE_ENABLED)
+#define BLINK_BINDINGS_TRACE_EVENT(trace_event_name) \
+ TRACE_EVENT0("blink.bindings", trace_event_name)
+#else
+#define BLINK_BINDINGS_TRACE_EVENT(trace_event_name) \
+ do { \
+ } while (false)
+#endif
+
// Maintains a stack of timers and provides functions to manage recording scopes
// by pausing and resuming timers in the chain when entering and leaving a
// scope.
@@ -236,6 +249,7 @@ class PLATFORM_EXPORT RuntimeCallStats {
#define CALLBACK_COUNTERS(V) \
BINDINGS_METHOD(V, ElementGetBoundingClientRect) \
+ BINDINGS_METHOD(V, ElementGetInnerHTML) \
BINDINGS_METHOD(V, EventTargetDispatchEvent) \
BINDINGS_METHOD(V, HTMLElementClick) \
BINDINGS_METHOD(V, NodeAppendChild) \
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h b/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h
deleted file mode 100644
index e6224751292..00000000000
--- a/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_PROMISE_PROPERTIES_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_PROMISE_PROPERTIES_H_
-
-// See ScriptPromiseProperty.h
-#define SCRIPT_PROMISE_PROPERTIES(P, ...) \
- P(ScriptPromise, kReady##__VA_ARGS__) \
- P(ScriptPromise, kClosed##__VA_ARGS__) \
- P(ScriptPromise, kFinished##__VA_ARGS__) \
- P(ScriptPromise, kLoaded##__VA_ARGS__) \
- P(ScriptPromise, kLost##__VA_ARGS__) \
- P(ScriptPromise, kReleased##__VA_ARGS__) \
- P(ScriptPromise, kResponseReady##__VA_ARGS__) \
- P(ScriptPromise, kUserChoice##__VA_ARGS__) \
- P(ScriptPromise, kPreloadResponse##__VA_ARGS__)
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_PROMISE_PROPERTIES_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_state.h b/chromium/third_party/blink/renderer/platform/bindings/script_state.h
index f4ba8ef7edc..22baa5189bb 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_state.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_state.h
@@ -75,7 +75,7 @@ class V8PerContextData;
// all V8 proxy objects that have references to the ScriptState are destructed.
class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
public:
- class Scope {
+ class Scope final {
STACK_ALLOCATED();
public:
@@ -95,10 +95,36 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
v8::Local<v8::Context> context_;
};
+ // Use EscapableScope if you have to return a v8::Local to an outer scope.
+ // See v8::EscapableHandleScope.
+ class EscapableScope final {
+ STACK_ALLOCATED();
+
+ public:
+ // You need to make sure that scriptState->context() is not empty before
+ // creating a Scope.
+ explicit EscapableScope(ScriptState* script_state)
+ : handle_scope_(script_state->GetIsolate()),
+ context_(script_state->GetContext()) {
+ DCHECK(script_state->ContextIsValid());
+ context_->Enter();
+ }
+
+ ~EscapableScope() { context_->Exit(); }
+
+ v8::Local<v8::Value> Escape(v8::Local<v8::Value> value) {
+ return handle_scope_.Escape(value);
+ }
+
+ private:
+ v8::EscapableHandleScope handle_scope_;
+ v8::Local<v8::Context> context_;
+ };
+
ScriptState(v8::Local<v8::Context>, scoped_refptr<DOMWrapperWorld>);
~ScriptState();
- void Trace(blink::Visitor*) {}
+ void Trace(Visitor*) {}
static ScriptState* Current(v8::Isolate* isolate) { // DEPRECATED
return From(isolate->GetCurrentContext());
@@ -193,9 +219,9 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
// exactly.
SelfKeepAlive<ScriptState> reference_from_v8_context_;
- static constexpr int kV8ContextPerContextDataIndex = static_cast<int>(
- gin::kPerContextDataStartIndex + // NOLINT(readability/enum_casing)
- gin::kEmbedderBlink); // NOLINT(readability/enum_casing)
+ static constexpr int kV8ContextPerContextDataIndex =
+ static_cast<int>(gin::kPerContextDataStartIndex) +
+ static_cast<int>(gin::kEmbedderBlink);
DISALLOW_COPY_AND_ASSIGN(ScriptState);
};
@@ -215,7 +241,7 @@ class ScriptStateProtectingContext final
}
}
- void Trace(blink::Visitor* visitor) { visitor->Trace(script_state_); }
+ void Trace(Visitor* visitor) { visitor->Trace(script_state_); }
ScriptState* Get() const { return script_state_; }
void Reset() {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
index 3f344d0ccf0..aaea2cdebb7 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
@@ -17,7 +17,7 @@ struct SameSizeAsScriptWrappable {
static_assert(sizeof(ScriptWrappable) <= sizeof(SameSizeAsScriptWrappable),
"ScriptWrappable should stay small");
-v8::Local<v8::Object> ScriptWrappable::Wrap(
+v8::Local<v8::Value> ScriptWrappable::Wrap(
v8::Isolate* isolate,
v8::Local<v8::Object> creation_context) {
const WrapperTypeInfo* wrapper_type_info = this->GetWrapperTypeInfo();
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
index 25475561588..2a0f41e3f32 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
@@ -48,7 +48,7 @@ namespace blink {
// a v8::Object and toScriptWrappable() converts a v8::Object back to
// a ScriptWrappable. v8::Object as platform object is called "wrapper object".
// The wrapper object for the main world is stored in ScriptWrappable. Wrapper
-// objects for other worlds are stored in DOMWrapperMap.
+// objects for other worlds are stored in DOMDataStore.
class PLATFORM_EXPORT ScriptWrappable
: public GarbageCollected<ScriptWrappable>,
public NameClient {
@@ -68,7 +68,7 @@ class PLATFORM_EXPORT ScriptWrappable
const char* NameInHeapSnapshot() const override;
- virtual void Trace(blink::Visitor*);
+ virtual void Trace(Visitor*);
template <typename T>
T* ToImpl() {
@@ -78,16 +78,14 @@ class PLATFORM_EXPORT ScriptWrappable
sizeof(T) && WTF::IsGarbageCollectedType<T>::value,
"Classes implementing ScriptWrappable must be garbage collected.");
-// Check if T* is castable to ScriptWrappable*, which means T doesn't
-// have two or more ScriptWrappable as superclasses. If T has two
-// ScriptWrappable as superclasses, conversions from T* to
-// ScriptWrappable* are ambiguous.
-#if !defined(COMPILER_MSVC)
- // MSVC 2013 doesn't support static_assert + constexpr well.
+ // Check if T* is castable to ScriptWrappable*, which means T doesn't
+ // have two or more ScriptWrappable as superclasses. If T has two
+ // ScriptWrappable as superclasses, conversions from T* to
+ // ScriptWrappable* are ambiguous.
static_assert(!static_cast<ScriptWrappable*>(static_cast<T*>(nullptr)),
"Class T must not have two or more ScriptWrappable as its "
"superclasses.");
-#endif
+
return static_cast<T*>(this);
}
@@ -97,8 +95,8 @@ class PLATFORM_EXPORT ScriptWrappable
virtual const WrapperTypeInfo* GetWrapperTypeInfo() const = 0;
// Creates and returns a new wrapper object.
- virtual v8::Local<v8::Object> Wrap(v8::Isolate*,
- v8::Local<v8::Object> creation_context);
+ virtual v8::Local<v8::Value> Wrap(v8::Isolate*,
+ v8::Local<v8::Object> creation_context);
// Associates the instance with the given |wrapper| if this instance is not
// yet associated with any wrapper. Returns the wrapper already associated
@@ -190,6 +188,9 @@ inline bool ScriptWrappable::UnsetMainWorldWrapperIfSet(
const WrapperTypeInfo* GetWrapperTypeInfo() const override { \
return &wrapper_type_info_; \
} \
+ static const WrapperTypeInfo* GetStaticWrapperTypeInfo() { \
+ return &wrapper_type_info_; \
+ } \
\
private: \
static const WrapperTypeInfo& wrapper_type_info_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h b/chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h
deleted file mode 100644
index 03a87e9e10c..00000000000
--- a/chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SHARED_PERSISTENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SHARED_PERSISTENT_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
-#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-// A ref counted version of ScopedPersistent. This class is intended for use by
-// ScriptValue and not for normal use. Consider using ScopedPersistent directly
-// instead.
-// TODO(crbug.com/1029738): Remove once bug is fixed.
-template <typename T>
-class SharedPersistent : public RefCounted<SharedPersistent<T>> {
- USING_FAST_MALLOC(SharedPersistent);
-
- public:
- static scoped_refptr<SharedPersistent<T>> Create(v8::Isolate* isolate,
- v8::Local<T> value) {
- return base::AdoptRef(new SharedPersistent<T>(isolate, value));
- }
-
- // Returns the V8 reference. Crashes if |world_| is set and it is
- // different from |target_script_state|'s world.
- v8::Local<T> Get(ScriptState* target_script_state) const {
- DCHECK(!value_.IsEmpty());
- if (world_) {
- CHECK_EQ(world_.get(), &target_script_state->World());
- }
- return value_.NewLocal(target_script_state->GetIsolate());
- }
-
- // Returns a V8 reference that is safe to access in |target_script_state|.
- // The return value may be a cloned object.
- v8::Local<T> GetAcrossWorld(ScriptState* target_script_state) const {
- CHECK(world_);
- DCHECK(!value_.IsEmpty());
-
- v8::Isolate* isolate = target_script_state->GetIsolate();
-
- if (world_ == &target_script_state->World())
- return value_.NewLocal(isolate);
-
- // If |v8_reference| is a v8::Object, clones |v8_reference| in the context
- // of |target_script_state| and returns it. Otherwise returns
- // |v8_reference| itself that is already safe to access in
- // |target_script_state|.
-
- v8::Local<v8::Value> value = value_.NewLocal(isolate);
- DCHECK(value->IsObject());
- return value.template As<T>();
- }
-
- bool IsEmpty() { return value_.IsEmpty(); }
-
- bool operator==(const SharedPersistent<T>& other) {
- return value_ == other.value_;
- }
-
- private:
- explicit SharedPersistent(v8::Isolate* isolate, v8::Local<T> value)
- : value_(isolate, value) {
- DCHECK(!value.IsEmpty());
- // Basically, |world_| is a world when this V8 reference is created.
- // However, when this V8 reference isn't created in context and value is
- // object, we set |world_| to a value's creation cotext's world.
- if (isolate->InContext()) {
- world_ = &DOMWrapperWorld::Current(isolate);
- if (value->IsObject()) {
- v8::Local<v8::Context> context =
- value.template As<v8::Object>()->CreationContext();
- // Creation context is null if the value is a remote object.
- if (!context.IsEmpty()) {
- ScriptState* script_state = ScriptState::From(context);
- CHECK_EQ(world_.get(), &script_state->World());
- }
- }
- } else if (value->IsObject()) {
- ScriptState* script_state =
- ScriptState::From(value.template As<v8::Object>()->CreationContext());
- world_ = &script_state->World();
- }
- }
-
- ScopedPersistent<T> value_;
- // The world of the current context at the time when |value_| was set.
- // It's guaranteed that, if |value_| is a v8::Object, the world of the
- // creation context of |value_| is the same as |world_|.
- scoped_refptr<const DOMWrapperWorld> world_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedPersistent);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SHARED_PERSISTENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
index 246140e5dcd..50ae965e76e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/union_base.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -85,6 +86,17 @@ inline v8::Local<v8::Value> ToV8(CallbackInterfaceBase* callback,
: v8::Null(isolate).As<v8::Value>();
}
+// Union type
+
+inline v8::Local<v8::Value> ToV8(const bindings::UnionBase& value,
+ v8::Local<v8::Object> creation_context,
+ v8::Isolate* isolate) {
+ v8::Local<v8::Value> v8_value =
+ value.CreateV8Object(isolate, creation_context);
+ DCHECK(!v8_value.IsEmpty());
+ return v8_value;
+}
+
// Primitives
inline v8::Local<v8::Value> ToV8(const String& value,
@@ -208,27 +220,27 @@ inline v8::Local<v8::Value> ToV8(const base::Optional<InnerType>& value,
// Declare the function here but define it later so it can call the ToV8()
// overloads below.
template <typename Sequence>
-inline v8::Local<v8::Value> ToV8SequenceInternal(
+inline v8::Local<v8::Array> ToV8SequenceInternal(
const Sequence&,
v8::Local<v8::Object> creation_context,
v8::Isolate*);
template <typename T, size_t Extent>
-inline v8::Local<v8::Value> ToV8(base::span<T, Extent> value,
+inline v8::Local<v8::Array> ToV8(base::span<T, Extent> value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate);
}
template <typename T, wtf_size_t inlineCapacity>
-inline v8::Local<v8::Value> ToV8(const Vector<T, inlineCapacity>& value,
+inline v8::Local<v8::Array> ToV8(const Vector<T, inlineCapacity>& value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate);
}
template <typename T, wtf_size_t inlineCapacity>
-inline v8::Local<v8::Value> ToV8(const HeapVector<T, inlineCapacity>& value,
+inline v8::Local<v8::Array> ToV8(const HeapVector<T, inlineCapacity>& value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate);
@@ -289,7 +301,7 @@ inline v8::Local<v8::Value> ToV8(const HeapVector<std::pair<String, T>>& value,
}
template <typename Sequence>
-inline v8::Local<v8::Value> ToV8SequenceInternal(
+inline v8::Local<v8::Array> ToV8SequenceInternal(
const Sequence& sequence,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
@@ -312,7 +324,7 @@ inline v8::Local<v8::Value> ToV8SequenceInternal(
if (!array->CreateDataProperty(context, index++, value)
.To(&created_property) ||
!created_property) {
- return v8::Local<v8::Value>();
+ return v8::Local<v8::Array>();
}
}
return array;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/union_base.h b/chromium/third_party/blink/renderer/platform/bindings/union_base.h
new file mode 100644
index 00000000000..35ce7f8151b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/union_base.h
@@ -0,0 +1,45 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_UNION_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_UNION_BASE_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class Visitor;
+
+namespace bindings {
+
+// This class is the base class for all IDL dictionary implementations. This
+// is designed to collaborate with NativeValueTraits and ToV8 with supporting
+// type dispatching (SFINAE, etc.).
+class PLATFORM_EXPORT UnionBase {
+ DISALLOW_NEW();
+
+ public:
+ virtual ~UnionBase() = default;
+
+ virtual v8::Local<v8::Value> CreateV8Object(
+ v8::Isolate* isolate,
+ v8::Local<v8::Object> creation_context) const = 0;
+
+ void Trace(Visitor*) {}
+
+ protected:
+ UnionBase() = default;
+ UnionBase(const UnionBase&) = default;
+ UnionBase(UnionBase&&) = default;
+ UnionBase& operator=(const UnionBase&) = default;
+ UnionBase& operator=(UnionBase&&) = default;
+};
+
+} // namespace bindings
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_UNION_BASE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h b/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
index ba7445d3342..ed84d117363 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
@@ -46,6 +46,10 @@
namespace blink {
+namespace bindings {
+class DictionaryBase;
+}
+
// This file contains bindings helper functions that do not have dependencies
// to core/ or bindings/core. For core-specific helper functions, see
// bindings/core/v8/V8BindingForCore.h.
@@ -99,6 +103,11 @@ inline void V8SetReturnValue(const CallbackInfo& info, uint32_t value) {
}
template <typename CallbackInfo>
+inline void V8SetReturnValue(const CallbackInfo& info, uint64_t value) {
+ info.GetReturnValue().Set(static_cast<double>(value));
+}
+
+template <typename CallbackInfo>
inline void V8SetReturnValueBool(const CallbackInfo& info, bool v) {
info.GetReturnValue().Set(v);
}
@@ -162,7 +171,7 @@ inline void V8SetReturnValue(const CallbackInfo& callback_info,
}
if (DOMDataStore::SetReturnValue(callback_info.GetReturnValue(), impl))
return;
- v8::Local<v8::Object> wrapper =
+ v8::Local<v8::Value> wrapper =
impl->Wrap(callback_info.GetIsolate(), creation_context);
V8SetReturnValue(callback_info, wrapper);
}
@@ -184,7 +193,7 @@ inline void V8SetReturnValueForMainWorld(const CallbackInfo& callback_info,
if (DOMDataStore::SetReturnValueForMainWorld(callback_info.GetReturnValue(),
impl))
return;
- v8::Local<v8::Object> wrapper =
+ v8::Local<v8::Value> wrapper =
impl->Wrap(callback_info.GetIsolate(), callback_info.Holder());
V8SetReturnValue(callback_info, wrapper);
}
@@ -200,7 +209,7 @@ inline void V8SetReturnValueFast(const CallbackInfo& callback_info,
if (DOMDataStore::SetReturnValueFast(callback_info.GetReturnValue(), impl,
callback_info.Holder(), wrappable))
return;
- v8::Local<v8::Object> wrapper =
+ v8::Local<v8::Value> wrapper =
impl->Wrap(callback_info.GetIsolate(), callback_info.Holder());
V8SetReturnValue(callback_info, wrapper);
}
@@ -212,6 +221,20 @@ inline void V8SetReturnValueFast(const CallbackInfo& callback_info,
V8SetReturnValue(callback_info, handle);
}
+// Dictionary
+template <class CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ bindings::DictionaryBase* value,
+ v8::Local<v8::Object> creation_context) {
+ V8SetReturnValue(info, ToV8(value, creation_context, info.GetIsolate()));
+}
+
+template <class CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ bindings::DictionaryBase* value) {
+ V8SetReturnValue(info, ToV8(value, info.Holder(), info.GetIsolate()));
+}
+
// Convert v8::String to a WTF::String. If the V8 string is not already
// an external string then it is transformed into an external string at this
// point to avoid repeated conversions.
@@ -359,6 +382,24 @@ static void IndexedPropertyEnumerator(
PLATFORM_EXPORT v8::Local<v8::Value> FreezeV8Object(v8::Local<v8::Value>,
v8::Isolate*);
+// Return values of indexed properties and named properties
+
+enum class IndexedPropertySetterResult {
+ kDidNotIntercept, // Fallback to the default set operation.
+ kIntercepted, // Intercepted regardless of whether it succeeded or not.
+};
+
+enum class NamedPropertySetterResult {
+ kDidNotIntercept, // Fallback to the default set operation.
+ kIntercepted, // Intercepted regardless of whether it succeeded or not.
+};
+
+enum class NamedPropertyDeleterResult {
+ kDidNotIntercept, // Fallback to the default delete operation.
+ kDeleted, // Successfully deleted.
+ kDidNotDelete, // Intercepted but failed to delete.
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_BINDING_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_binding_macros.h b/chromium/third_party/blink/renderer/platform/bindings/v8_binding_macros.h
index 2ec174ff7aa..1c5a0f9dacf 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_binding_macros.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_binding_macros.h
@@ -59,16 +59,6 @@ namespace blink {
if (UNLIKELY(!var.Prepare())) \
return retVal;
-// Checks for a given v8::Value (value) whether it is an ArrayBufferView and
-// below a certain size limit. If below the limit, memory is allocated on the
-// stack to hold the actual payload. Keep the limit in sync with V8's
-// typed_array_max_size.
-#define allocateFlexibleArrayBufferViewStorage(value) \
- (value->IsArrayBufferView() && \
- (value.As<v8::ArrayBufferView>()->ByteLength() <= 64) \
- ? alloca(value.As<v8::ArrayBufferView>()->ByteLength()) \
- : nullptr)
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_BINDING_MACROS_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc
new file mode 100644
index 00000000000..a434695b8e2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc
@@ -0,0 +1,96 @@
+// 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 "third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h"
+
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+
+namespace blink {
+
+namespace bindings {
+
+v8::MaybeLocal<v8::Function> GetCrossOriginFunction(
+ v8::Isolate* isolate,
+ v8::FunctionCallback callback,
+ int func_length,
+ const WrapperTypeInfo* wrapper_type_info) {
+ v8::Local<v8::Context> current_context = isolate->GetCurrentContext();
+ ScriptState* script_state = ScriptState::From(current_context);
+ V8PerIsolateData* per_isolate_data = V8PerIsolateData::From(isolate);
+ const void* callback_key = reinterpret_cast<const void*>(callback);
+
+ // ES functions accessible across origins are not interface objects, but we
+ // reuse the cache of interface objects, which just works because both are
+ // V8 function template.
+ v8::Local<v8::FunctionTemplate> function_template =
+ per_isolate_data->FindInterfaceTemplate(script_state->World(),
+ callback_key);
+ if (function_template.IsEmpty()) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ per_isolate_data->FindInterfaceTemplate(script_state->World(),
+ wrapper_type_info);
+ v8::Local<v8::Signature> signature =
+ v8::Signature::New(isolate, interface_template);
+ function_template = v8::FunctionTemplate::New(
+ isolate, callback, v8::Local<v8::Value>(), signature, func_length,
+ v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect);
+ per_isolate_data->SetInterfaceTemplate(script_state->World(), callback_key,
+ function_template);
+ }
+ return function_template->GetFunction(current_context);
+}
+
+v8::MaybeLocal<v8::Value> GetCrossOriginFunctionOrUndefined(
+ v8::Isolate* isolate,
+ v8::FunctionCallback callback,
+ int func_length,
+ const WrapperTypeInfo* wrapper_type_info) {
+ if (!callback) {
+ return v8::Undefined(isolate);
+ }
+ v8::Local<v8::Function> function;
+ if (GetCrossOriginFunction(isolate, callback, func_length, wrapper_type_info)
+ .ToLocal(&function)) {
+ return function;
+ }
+ return v8::MaybeLocal<v8::Value>();
+}
+
+bool IsSupportedInCrossOriginPropertyFallback(
+ v8::Isolate* isolate,
+ v8::Local<v8::Name> property_name) {
+ return (property_name == V8AtomicString(isolate, "then") ||
+ property_name == v8::Symbol::GetToStringTag(isolate) ||
+ property_name == v8::Symbol::GetHasInstance(isolate) ||
+ property_name == v8::Symbol::GetIsConcatSpreadable(isolate));
+}
+
+v8::Local<v8::Array> EnumerateCrossOriginProperties(
+ v8::Isolate* isolate,
+ base::span<const CrossOriginAttributeTableEntry> attributes,
+ base::span<const CrossOriginOperationTableEntry> operations) {
+ v8::Local<v8::Value> default_supported[] = {
+ V8AtomicString(isolate, "then"),
+ v8::Symbol::GetToStringTag(isolate),
+ v8::Symbol::GetHasInstance(isolate),
+ v8::Symbol::GetIsConcatSpreadable(isolate),
+ };
+ const uint32_t length =
+ attributes.size() + operations.size() + base::size(default_supported);
+ Vector<v8::Local<v8::Value>> elements;
+ elements.ReserveCapacity(length);
+ for (const auto& attribute : attributes)
+ elements.UncheckedAppend(V8AtomicString(isolate, attribute.name));
+ for (const auto& operation : operations)
+ elements.UncheckedAppend(V8AtomicString(isolate, operation.name));
+ for (const auto& name : default_supported)
+ elements.UncheckedAppend(name);
+ return v8::Array::New(isolate, elements.data(), elements.size());
+}
+
+} // namespace bindings
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h
new file mode 100644
index 00000000000..d441696a42a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h
@@ -0,0 +1,65 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_PROPERTY_SUPPORT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_PROPERTY_SUPPORT_H_
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "v8/include/v8.h"
+
+// This file provides utilities to support implementation of cross origin
+// properties in generated bindings code. Should be used only in generated
+// bindings code.
+
+namespace blink {
+
+struct WrapperTypeInfo;
+
+namespace bindings {
+
+struct CrossOriginAttributeTableEntry final {
+ const char* name;
+ v8::FunctionCallback get_callback;
+ v8::FunctionCallback set_callback;
+ v8::GenericNamedPropertyGetterCallback get_value;
+ v8::GenericNamedPropertySetterCallback set_value;
+};
+
+struct CrossOriginOperationTableEntry final {
+ const char* name;
+ v8::FunctionCallback callback;
+ int func_length;
+};
+
+PLATFORM_EXPORT v8::MaybeLocal<v8::Function> GetCrossOriginFunction(
+ v8::Isolate* isolate,
+ v8::FunctionCallback callback,
+ int func_length,
+ const WrapperTypeInfo* wrapper_type_info);
+
+PLATFORM_EXPORT v8::MaybeLocal<v8::Value> GetCrossOriginFunctionOrUndefined(
+ v8::Isolate* isolate,
+ v8::FunctionCallback callback,
+ int func_length,
+ const WrapperTypeInfo* wrapper_type_info);
+
+// HTML 7.2.3.2 CrossOriginPropertyFallback ( P )
+// https://html.spec.whatwg.org/C/#crossoriginpropertyfallback-(-p-)
+PLATFORM_EXPORT bool IsSupportedInCrossOriginPropertyFallback(
+ v8::Isolate* isolate,
+ v8::Local<v8::Name> property_name);
+
+// HTML 7.2.3.7 CrossOriginOwnPropertyKeys ( O )
+// https://html.spec.whatwg.org/C/#crossoriginownpropertykeys-(-o-)
+PLATFORM_EXPORT v8::Local<v8::Array> EnumerateCrossOriginProperties(
+ v8::Isolate* isolate,
+ base::span<const CrossOriginAttributeTableEntry> attributes,
+ base::span<const CrossOriginOperationTableEntry> operations);
+
+} // namespace bindings
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_PROPERTY_SUPPORT_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h b/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h
new file mode 100644
index 00000000000..402b97cc68a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h
@@ -0,0 +1,99 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class DOMWrapperWorld;
+
+namespace bindings {
+
+// The common base class of code-generated V8-Blink bridge class of IDL
+// interfaces and namespaces.
+class PLATFORM_EXPORT V8InterfaceBridgeBase {
+ STATIC_ONLY(V8InterfaceBridgeBase);
+
+ protected:
+ using InstallInterfaceTemplateFuncType =
+ void (*)(v8::Isolate* isolate,
+ const DOMWrapperWorld& world,
+ v8::Local<v8::FunctionTemplate> interface_template);
+ using InstallUnconditionalPropertiesFuncType =
+ void (*)(v8::Isolate* isolate,
+ const DOMWrapperWorld& world,
+ v8::Local<v8::ObjectTemplate> instance_template,
+ v8::Local<v8::ObjectTemplate> prototype_template,
+ v8::Local<v8::FunctionTemplate> interface_template);
+ using InstallContextIndependentPropertiesFuncType =
+ void (*)(v8::Isolate* isolate,
+ const DOMWrapperWorld& world,
+ v8::Local<v8::ObjectTemplate> instance_template,
+ v8::Local<v8::ObjectTemplate> prototype_template,
+ v8::Local<v8::FunctionTemplate> interface_template);
+ using InstallContextDependentPropertiesFuncType =
+ void (*)(v8::Local<v8::Context> context,
+ const DOMWrapperWorld& world,
+ v8::Local<v8::Object> instance_object,
+ v8::Local<v8::Object> prototype_object,
+ v8::Local<v8::Function> interface_object);
+};
+
+template <class V8T, class T>
+class V8InterfaceBridge : public V8InterfaceBridgeBase {
+ public:
+ static T* ToWrappable(v8::Isolate* isolate, v8::Local<v8::Value> value) {
+ return HasInstance(isolate, value)
+ ? ToWrappableUnsafe(value.As<v8::Object>())
+ : nullptr;
+ }
+
+ static T* ToWrappableUnsafe(v8::Local<v8::Object> value) {
+ return ToScriptWrappable(value)->ToImpl<T>();
+ }
+
+ static bool HasInstance(v8::Isolate* isolate, v8::Local<v8::Value> value) {
+ return V8PerIsolateData::From(isolate)->HasInstance(
+ V8T::GetWrapperTypeInfo(), value);
+ }
+
+ // Migration adapter
+ static bool HasInstance(v8::Local<v8::Value> value, v8::Isolate* isolate) {
+ return HasInstance(isolate, value);
+ }
+
+ static T* ToImpl(v8::Local<v8::Object> value) {
+ return ToWrappableUnsafe(value);
+ }
+
+ static T* ToImplWithTypeCheck(v8::Isolate* isolate,
+ v8::Local<v8::Value> value) {
+ return ToWrappable(isolate, value);
+ }
+
+ static void InstallContextDependentAdapter(
+ v8::Local<v8::Context> context,
+ const DOMWrapperWorld& world,
+ v8::Local<v8::Object> instance_object,
+ v8::Local<v8::Object> prototype_object,
+ v8::Local<v8::Function> interface_object,
+ v8::Local<v8::FunctionTemplate> interface_template) {
+ V8T::InstallContextDependentProperties(context, world, instance_object,
+ prototype_object, interface_object);
+ }
+};
+
+} // namespace bindings
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
index 6c25c30dcb3..032aca70e3f 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -172,8 +172,9 @@ void V8PerIsolateData::WillBeDestroyed(v8::Isolate* isolate) {
// callbacks are missing and state gets out of sync.
ThreadState* const thread_state = ThreadState::Current();
thread_state->FinishIncrementalMarkingIfRunning(
- BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::GCReason::kThreadTerminationGC);
+ BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
+ BlinkGC::GCReason::kThreadTerminationGC);
thread_state->DetachFromIsolate();
}
@@ -267,26 +268,28 @@ void V8PerIsolateData::ClearPersistentsForV8ContextSnapshot() {
private_property_.reset();
}
-const v8::Eternal<v8::Name>* V8PerIsolateData::FindOrCreateEternalNameCache(
+const base::span<const v8::Eternal<v8::Name>>
+V8PerIsolateData::FindOrCreateEternalNameCache(
const void* lookup_key,
- const char* const names[],
- size_t count) {
+ const base::span<const char* const>& names) {
auto it = eternal_name_cache_.find(lookup_key);
const Vector<v8::Eternal<v8::Name>>* vector = nullptr;
if (UNLIKELY(it == eternal_name_cache_.end())) {
v8::Isolate* isolate = this->GetIsolate();
- Vector<v8::Eternal<v8::Name>> new_vector(count);
- std::transform(
- names, names + count, new_vector.begin(), [isolate](const char* name) {
- return v8::Eternal<v8::Name>(isolate, V8AtomicString(isolate, name));
- });
+ Vector<v8::Eternal<v8::Name>> new_vector(names.size());
+ std::transform(names.begin(), names.end(), new_vector.begin(),
+ [isolate](const char* name) {
+ return v8::Eternal<v8::Name>(
+ isolate, V8AtomicString(isolate, name));
+ });
vector = &eternal_name_cache_.Set(lookup_key, std::move(new_vector))
.stored_value->value;
} else {
vector = &it->value;
}
- DCHECK_EQ(vector->size(), count);
- return vector->data();
+ DCHECK_EQ(vector->size(), names.size());
+ return base::span<const v8::Eternal<v8::Name>>(vector->data(),
+ vector->size());
}
v8::Local<v8::Context> V8PerIsolateData::EnsureScriptRegexpContext() {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
index 6b5c64a59f3..f64cd5c5029 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
@@ -28,6 +28,7 @@
#include <memory>
+#include "base/containers/span.h"
#include "base/macros.h"
#include "gin/public/gin_embedders.h"
#include "gin/public/isolate_holder.h"
@@ -106,7 +107,7 @@ class PLATFORM_EXPORT V8PerIsolateData {
public:
virtual ~GarbageCollectedData() = default;
virtual void WillBeDestroyed() {}
- virtual void Trace(blink::Visitor*) {}
+ virtual void Trace(Visitor*) {}
};
static v8::Isolate* Initialize(scoped_refptr<base::SingleThreadTaskRunner>,
@@ -182,10 +183,9 @@ class PLATFORM_EXPORT V8PerIsolateData {
// yet exist, it is created from the given array of strings. Once created,
// these live for as long as the isolate, so this is appropriate only for a
// compile-time list of related names, such as IDL dictionary keys.
- const v8::Eternal<v8::Name>* FindOrCreateEternalNameCache(
+ const base::span<const v8::Eternal<v8::Name>> FindOrCreateEternalNameCache(
const void* lookup_key,
- const char* const names[],
- size_t count);
+ const base::span<const char* const>& names);
bool HasInstance(const WrapperTypeInfo* untrusted, v8::Local<v8::Value>);
v8::Local<v8::Object> FindInstanceInPrototypeChain(const WrapperTypeInfo*,
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h b/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
index 864454f18c2..bf19f476ecc 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/memory/ptr_util.h"
-#include "third_party/blink/renderer/platform/bindings/script_promise_properties.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc
new file mode 100644
index 00000000000..a80ede46d7d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc
@@ -0,0 +1,61 @@
+// 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 "third_party/blink/renderer/platform/bindings/v8_set_return_value.h"
+
+#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
+
+namespace blink {
+
+namespace bindings {
+
+v8::Local<v8::Object> CreatePropertyDescriptorObject(
+ v8::Isolate* isolate,
+ const v8::PropertyDescriptor& desc) {
+ // https://tc39.es/ecma262/#sec-frompropertydescriptor
+ v8::Local<v8::Context> current_context = isolate->GetCurrentContext();
+ v8::Local<v8::Object> object = v8::Object::New(isolate);
+
+ auto add_property = [&](const char* name, v8::Local<v8::Value> value) {
+ return object->CreateDataProperty(current_context, V8String(isolate, name),
+ value);
+ };
+ auto add_property_bool = [&](const char* name, bool value) {
+ return add_property(name, value ? v8::True(isolate) : v8::False(isolate));
+ };
+
+ bool result;
+ if (desc.has_value()) {
+ if (!(add_property("value", desc.value()).To(&result) &&
+ add_property_bool("writable", desc.writable()).To(&result)))
+ return v8::Local<v8::Object>();
+ } else {
+ if (!(add_property("get", desc.get()).To(&result) &&
+ add_property("set", desc.set()).To(&result)))
+ return v8::Local<v8::Object>();
+ }
+ if (!(add_property_bool("enumerable", desc.enumerable()).To(&result) &&
+ add_property_bool("configurable", desc.configurable()).To(&result)))
+ return v8::Local<v8::Object>();
+
+ return object;
+}
+
+v8::Local<v8::Value> GetInterfaceObjectExposedOnGlobal(
+ v8::Isolate* isolate,
+ v8::Local<v8::Object> creation_context,
+ const WrapperTypeInfo* wrapper_type_info) {
+ RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(
+ isolate, "Blink_GetInterfaceObjectExposedOnGlobal");
+ V8PerContextData* per_context_data =
+ V8PerContextData::From(creation_context->CreationContext());
+ if (!per_context_data)
+ return v8::Local<v8::Value>();
+ return per_context_data->ConstructorForType(wrapper_type_info);
+}
+
+} // namespace bindings
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h b/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
new file mode 100644
index 00000000000..6c7ffa11316
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
@@ -0,0 +1,336 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_SET_RETURN_VALUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_SET_RETURN_VALUE_H_
+
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
+#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/bindings/v8_value_cache.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+namespace bindings {
+
+// V8SetReturnValue sets a return value in a V8 callback function. The first
+// two arguments are fixed as v8::{Function,Property}CallbackInfo and the
+// return value. V8SetReturnValue may take more arguments as optimization hints
+// depending on the return value type.
+
+struct V8ReturnValue {
+ // Support compile-time overload resolution by making each value have its own
+ // type.
+
+ // Nullable or not
+ enum NonNullable { kNonNullable };
+ enum Nullable { kNullable };
+
+ // Main world or not
+ enum MainWorld { kMainWorld };
+
+ // Returns the interface object of the given type.
+ enum InterfaceObject { kInterfaceObject };
+};
+
+// V8 handle types
+template <typename CallbackInfo, typename S>
+void V8SetReturnValue(const CallbackInfo& info, const v8::Global<S> value) {
+ info.GetReturnValue().Set(value);
+}
+
+template <typename CallbackInfo, typename S>
+void V8SetReturnValue(const CallbackInfo& info, const v8::Local<S> value) {
+ info.GetReturnValue().Set(value);
+}
+
+// Property descriptor
+PLATFORM_EXPORT v8::Local<v8::Object> CreatePropertyDescriptorObject(
+ v8::Isolate* isolate,
+ const v8::PropertyDescriptor& desc);
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const v8::PropertyDescriptor& value) {
+ info.GetReturnValue().Set(
+ CreatePropertyDescriptorObject(info.GetIsolate(), value));
+}
+
+// Indexed properties and named properties
+PLATFORM_EXPORT inline void V8SetReturnValue(
+ const v8::FunctionCallbackInfo<v8::Value>& info,
+ IndexedPropertySetterResult value) {
+ // If an operation implementing indexed property setter is invoked as a
+ // regular operation, and the return type is not type void (V8SetReturnValue
+ // won't be called in case of type void), then return the given value as is.
+ info.GetReturnValue().Set(info[1]);
+}
+
+PLATFORM_EXPORT inline void V8SetReturnValue(
+ const v8::PropertyCallbackInfo<v8::Value>& info,
+ IndexedPropertySetterResult value) {
+ if (value == IndexedPropertySetterResult::kDidNotIntercept) {
+ // Do not set the return value to indicate that the request was not
+ // intercepted.
+ return;
+ }
+ info.GetReturnValue().SetNull();
+}
+
+PLATFORM_EXPORT inline void V8SetReturnValue(
+ const v8::FunctionCallbackInfo<v8::Value>& info,
+ NamedPropertySetterResult value) {
+ // If an operation implementing named property setter is invoked as a
+ // regular operation, and the return type is not type void (V8SetReturnValue
+ // won't be called in case of type void), then return the given value as is.
+ info.GetReturnValue().Set(info[1]);
+}
+
+PLATFORM_EXPORT inline void V8SetReturnValue(
+ const v8::PropertyCallbackInfo<v8::Value>& info,
+ NamedPropertySetterResult value) {
+ if (value == NamedPropertySetterResult::kDidNotIntercept) {
+ // Do not set the return value to indicate that the request was not
+ // intercepted.
+ return;
+ }
+ info.GetReturnValue().SetNull();
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ NamedPropertyDeleterResult value) {
+ if (value == NamedPropertyDeleterResult::kDidNotIntercept) {
+ // Do not set the return value to indicate that the request was not
+ // intercepted.
+ return;
+ }
+ info.GetReturnValue().Set(value == NamedPropertyDeleterResult::kDeleted);
+}
+
+// nullptr
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, std::nullptr_t) {
+ info.GetReturnValue().SetNull();
+}
+
+// Primitive types
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, bool value) {
+ info.GetReturnValue().Set(value);
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, int32_t value) {
+ info.GetReturnValue().Set(value);
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, uint32_t value) {
+ info.GetReturnValue().Set(value);
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, int64_t value) {
+ // ECMAScript doesn't support 64-bit integer in Number type.
+ info.GetReturnValue().Set(static_cast<double>(value));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, uint64_t value) {
+ // ECMAScript doesn't support 64-bit integer in Number type.
+ info.GetReturnValue().Set(static_cast<double>(value));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info, double value) {
+ info.GetReturnValue().Set(value);
+}
+
+// String types
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const AtomicString& string,
+ v8::Isolate* isolate,
+ V8ReturnValue::NonNullable) {
+ if (string.IsNull())
+ return info.GetReturnValue().SetEmptyString();
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), string.Impl());
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const String& string,
+ v8::Isolate* isolate,
+ V8ReturnValue::NonNullable) {
+ if (string.IsNull())
+ return info.GetReturnValue().SetEmptyString();
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), string.Impl());
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const WebString& string,
+ v8::Isolate* isolate,
+ V8ReturnValue::NonNullable) {
+ if (string.IsNull())
+ return info.GetReturnValue().SetEmptyString();
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), static_cast<String>(string).Impl());
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const AtomicString& string,
+ v8::Isolate* isolate,
+ V8ReturnValue::Nullable) {
+ if (string.IsNull())
+ return info.GetReturnValue().SetNull();
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), string.Impl());
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const String& string,
+ v8::Isolate* isolate,
+ V8ReturnValue::Nullable) {
+ if (string.IsNull())
+ return info.GetReturnValue().SetNull();
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), string.Impl());
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const WebString& string,
+ v8::Isolate* isolate,
+ V8ReturnValue::Nullable) {
+ if (string.IsNull())
+ return info.GetReturnValue().SetNull();
+ V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString(
+ info.GetReturnValue(), static_cast<String>(string).Impl());
+}
+
+// ScriptWrappable
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const ScriptWrappable* value,
+ V8ReturnValue::MainWorld) {
+ DCHECK(DOMWrapperWorld::Current(info.GetIsolate()).IsMainWorld());
+ if (UNLIKELY(!value))
+ return info.GetReturnValue().SetNull();
+
+ ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(value);
+ if (DOMDataStore::SetReturnValueForMainWorld(info.GetReturnValue(),
+ wrappable))
+ return;
+
+ info.GetReturnValue().Set(wrappable->Wrap(info.GetIsolate(), info.This()));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const ScriptWrappable& value,
+ V8ReturnValue::MainWorld) {
+ DCHECK(DOMWrapperWorld::Current(info.GetIsolate()).IsMainWorld());
+ ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(&value);
+ if (DOMDataStore::SetReturnValueForMainWorld(info.GetReturnValue(),
+ wrappable))
+ return;
+
+ info.GetReturnValue().Set(wrappable->Wrap(info.GetIsolate(), info.This()));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const ScriptWrappable* value,
+ const ScriptWrappable* receiver) {
+ if (UNLIKELY(!value))
+ return info.GetReturnValue().SetNull();
+
+ ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(value);
+ if (DOMDataStore::SetReturnValueFast(info.GetReturnValue(), wrappable,
+ info.This(), receiver)) {
+ return;
+ }
+
+ info.GetReturnValue().Set(wrappable->Wrap(info.GetIsolate(), info.This()));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const ScriptWrappable& value,
+ const ScriptWrappable* receiver) {
+ ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(&value);
+ if (DOMDataStore::SetReturnValueFast(info.GetReturnValue(), wrappable,
+ info.This(), receiver)) {
+ return;
+ }
+
+ info.GetReturnValue().Set(wrappable->Wrap(info.GetIsolate(), info.This()));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const ScriptWrappable* value,
+ v8::Local<v8::Context> creation_context) {
+ if (UNLIKELY(!value))
+ return info.GetReturnValue().SetNull();
+
+ ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(value);
+ if (DOMDataStore::SetReturnValue(info.GetReturnValue(), wrappable))
+ return;
+
+ info.GetReturnValue().Set(
+ wrappable->Wrap(info.GetIsolate(), creation_context->Global()));
+}
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ ScriptWrappable& value,
+ v8::Local<v8::Context> creation_context) {
+ ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(&value);
+ if (DOMDataStore::SetReturnValue(info.GetReturnValue(), wrappable))
+ return;
+
+ info.GetReturnValue().Set(
+ wrappable->Wrap(info.GetIsolate(), creation_context->Global()));
+}
+
+// Interface object
+PLATFORM_EXPORT v8::Local<v8::Value> GetInterfaceObjectExposedOnGlobal(
+ v8::Isolate* isolate,
+ v8::Local<v8::Object> creation_context,
+ const WrapperTypeInfo* wrapper_type_info);
+
+template <typename CallbackInfo>
+void V8SetReturnValue(const CallbackInfo& info,
+ const WrapperTypeInfo* wrapper_type_info,
+ V8ReturnValue::InterfaceObject) {
+ info.GetReturnValue().Set(GetInterfaceObjectExposedOnGlobal(
+ info.GetIsolate(), info.This(), wrapper_type_info));
+}
+
+// Nullable types
+template <typename CallbackInfo, typename T>
+void V8SetReturnValue(const CallbackInfo& info, base::Optional<T> value) {
+ if (value.has_value())
+ V8SetReturnValue(info, value.value());
+ else
+ info.GetReturnValue().SetNull();
+}
+
+} // namespace bindings
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_SET_RETURN_VALUE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_value_or_script_wrappable_adapter.h b/chromium/third_party/blink/renderer/platform/bindings/v8_value_or_script_wrappable_adapter.h
index b2d53160dfb..b8aa4bd15b7 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_value_or_script_wrappable_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_value_or_script_wrappable_adapter.h
@@ -51,7 +51,7 @@ class PLATFORM_EXPORT V8ValueOrScriptWrappableAdapter {
private:
v8::Local<v8::Value> v8_value_;
- Member<ScriptWrappable> script_wrappable_;
+ ScriptWrappable* script_wrappable_ = nullptr;
};
} // namespace bindings
diff --git a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc
index a9ce328a3b6..d621fa0345c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc
@@ -27,14 +27,14 @@ void WrapperTypeInfo::WrapperDestroyed() {
stats_collector->IncreaseCollectedWrapperCount(1);
}
-void WrapperTypeInfo::Trace(Visitor* visitor, void* impl) const {
+void WrapperTypeInfo::Trace(Visitor* visitor, const void* impl) const {
switch (wrapper_class_id) {
case WrapperTypeInfo::kNodeClassId:
case WrapperTypeInfo::kObjectClassId:
- visitor->Trace(reinterpret_cast<ScriptWrappable*>(impl));
+ visitor->Trace(reinterpret_cast<const ScriptWrappable*>(impl));
break;
case WrapperTypeInfo::kCustomWrappableId:
- visitor->Trace(reinterpret_cast<CustomWrappable*>(impl));
+ visitor->Trace(reinterpret_cast<const CustomWrappable*>(impl));
break;
default:
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h
index 4782a9e4557..f0b2232622b 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h
@@ -153,7 +153,7 @@ struct WrapperTypeInfo {
// Garbage collection support for when the type depends the WrapperTypeInfo
// object.
- PLATFORM_EXPORT void Trace(Visitor*, void*) const;
+ PLATFORM_EXPORT void Trace(Visitor*, const void*) const;
// This field must be the first member of the struct WrapperTypeInfo.
// See also static_assert() in .cpp file.
diff --git a/chromium/third_party/blink/renderer/platform/blob/BUILD.gn b/chromium/third_party/blink/renderer/platform/blob/BUILD.gn
index 635665ec38c..0f744c876b8 100644
--- a/chromium/third_party/blink/renderer/platform/blob/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/blob/BUILD.gn
@@ -33,9 +33,7 @@ blink_platform_sources("blob") {
"serialized_blob_mojom_traits.h",
]
- deps = [
- "//services/network/public/mojom:mojom_blink",
- ]
+ deps = [ "//services/network/public/mojom:mojom_blink" ]
}
jumbo_source_set("unit_tests") {
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
index 22cac3dac0e..833971da422 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
@@ -4,8 +4,10 @@
#include "third_party/blink/renderer/platform/blob/blob_bytes_provider.h"
+#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -117,8 +119,8 @@ constexpr size_t BlobBytesProvider::kMaxConsolidatedItemSizeInBytes;
// static
BlobBytesProvider* BlobBytesProvider::CreateAndBind(
mojo::PendingReceiver<mojom::blink::BytesProvider> receiver) {
- auto task_runner = base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
auto provider = base::WrapUnique(new BlobBytesProvider(task_runner));
auto* result = provider.get();
// TODO(mek): Consider binding BytesProvider on the IPC thread instead, only
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
index 1b5e7a11cc6..a381dbc3140 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -38,11 +38,11 @@
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/data_element.mojom-blink.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/blob/blob_bytes_provider.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -85,10 +85,10 @@ mojom::blink::BlobRegistry* GetThreadSpecificRegistry() {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
ThreadSpecific<mojo::Remote<mojom::blink::BlobRegistry>>, registry, ());
if (UNLIKELY(!registry.IsSet())) {
- // TODO(mek): Going through InterfaceProvider to get a
+ // TODO(mek): Going through BrowserInterfaceBroker to get a
// mojom::blink::BlobRegistry ends up going through the main thread. Ideally
// workers wouldn't need to do that.
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
(*registry).BindNewPipeAndPassReceiver());
}
return registry->get();
@@ -103,7 +103,7 @@ RawData::RawData() = default;
BlobData::BlobData(FileCompositionStatus composition)
: file_composition_(composition) {}
-BlobData::~BlobData() {}
+BlobData::~BlobData() = default;
Vector<mojom::blink::DataElementPtr> BlobData::ReleaseElements() {
return std::move(elements_);
@@ -173,6 +173,7 @@ void BlobData::AppendFile(
"create a blob with a single file with unknown size, use "
"BlobData::createForFileWithUnknownSize. Otherwise please provide the "
"file size.";
+ DCHECK_GE(length, 0);
// Skip zero-byte items, as they don't matter for the contents of the blob.
if (length == 0)
return;
@@ -201,6 +202,7 @@ void BlobData::AppendFileSystemURL(
const base::Optional<base::Time>& expected_modification_time) {
DCHECK_EQ(file_composition_, FileCompositionStatus::NO_UNKNOWN_SIZE_FILES)
<< "Blobs with a unknown-size file cannot have other items.";
+ DCHECK_GE(length, 0);
// Skip zero-byte items, as they don't matter for the contents of the blob.
if (length == 0)
return;
@@ -359,8 +361,7 @@ BlobDataHandle::BlobDataHandle(
DCHECK(blob_remote_.is_valid());
}
-BlobDataHandle::~BlobDataHandle() {
-}
+BlobDataHandle::~BlobDataHandle() = default;
mojo::PendingRemote<mojom::blink::Blob> BlobDataHandle::CloneBlobRemote() {
MutexLocker locker(blob_remote_mutex_);
@@ -415,6 +416,16 @@ void BlobDataHandle::ReadRange(
blob_remote_ = blob.Unbind();
}
+bool BlobDataHandle::CaptureSnapshot(
+ uint64_t* snapshot_size,
+ base::Optional<base::Time>* snapshot_modification_time) {
+ // This method operates on a cloned blob remote; this lets us avoid holding
+ // the |blob_remote_mutex_| locked during the duration of the (synchronous)
+ // CaptureSnapshot call.
+ mojo::Remote<mojom::blink::Blob> remote(CloneBlobRemote());
+ return remote->CaptureSnapshot(snapshot_size, snapshot_modification_time);
+}
+
// static
mojom::blink::BlobRegistry* BlobDataHandle::GetBlobRegistry() {
return GetThreadSpecificRegistry();
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data.h b/chromium/third_party/blink/renderer/platform/blob/blob_data.h
index 9965fe9c64b..33c842a9510 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.h
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.h
@@ -219,6 +219,16 @@ class PLATFORM_EXPORT BlobDataHandle
mojo::ScopedDataPipeProducerHandle,
mojo::PendingRemote<mojom::blink::BlobReaderClient>);
+ // This does synchronous IPC, and possibly synchronous file operations. Think
+ // twice before calling this function.
+ bool CaptureSnapshot(uint64_t* snapshot_size,
+ base::Optional<base::Time>* snapshot_modification_time);
+
+ void SetBlobRemoteForTesting(mojo::PendingRemote<mojom::blink::Blob> remote) {
+ MutexLocker locker(blob_remote_mutex_);
+ blob_remote_ = std::move(remote);
+ }
+
static mojom::blink::BlobRegistry* GetBlobRegistry();
static void SetBlobRegistryForTesting(mojom::blink::BlobRegistry*);
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc b/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc
index aa375aa798d..b515e0b11ad 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc
@@ -15,7 +15,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/renderer/platform/blob/blob_bytes_provider.h"
#include "third_party/blink/renderer/platform/blob/testing/fake_blob_registry.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
index 733798e9c77..5dd4ae6b61e 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
@@ -80,6 +80,10 @@ void FakeBlob::ReadSideData(ReadSideDataCallback callback) {
NOTREACHED();
}
+void FakeBlob::CaptureSnapshot(CaptureSnapshotCallback callback) {
+ std::move(callback).Run(body_.length(), base::nullopt);
+}
+
void FakeBlob::GetInternalUUID(GetInternalUUIDCallback callback) {
std::move(callback).Run(uuid_);
}
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
index 8ec5c7654c1..845330f9ee4 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
@@ -32,8 +32,10 @@ class FakeBlob : public mojom::blink::Blob {
void ReadAll(mojo::ScopedDataPipeProducerHandle,
mojo::PendingRemote<mojom::blink::BlobReaderClient>) override;
void ReadSideData(ReadSideDataCallback) override;
+ void CaptureSnapshot(CaptureSnapshotCallback) override;
void GetInternalUUID(GetInternalUUIDCallback) override;
- private:
+
+ protected:
String uuid_;
String body_;
State* state_;
diff --git a/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h b/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h
index d9d00569546..5bcfa0a11ea 100644
--- a/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h
+++ b/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h
@@ -36,7 +36,7 @@ class ContentDecryptionModuleResult
return WebContentDecryptionModuleResult(this);
}
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/context_lifecycle_notifier.h b/chromium/third_party/blink/renderer/platform/context_lifecycle_notifier.h
new file mode 100644
index 00000000000..6b16cfe76bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/context_lifecycle_notifier.h
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_CONTEXT_LIFECYCLE_NOTIFIER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_CONTEXT_LIFECYCLE_NOTIFIER_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ContextLifecycleObserver;
+
+// Notifier interface for ContextLifecycleObserver.
+class PLATFORM_EXPORT ContextLifecycleNotifier : public GarbageCollectedMixin {
+ public:
+ virtual void AddContextLifecycleObserver(ContextLifecycleObserver*) = 0;
+ virtual void RemoveContextLifecycleObserver(ContextLifecycleObserver*) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_CONTEXT_LIFECYCLE_NOTIFIER_H_
diff --git a/chromium/third_party/blink/renderer/platform/context_lifecycle_observer.cc b/chromium/third_party/blink/renderer/platform/context_lifecycle_observer.cc
new file mode 100644
index 00000000000..9387ae06507
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/context_lifecycle_observer.cc
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
+
+#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
+
+namespace blink {
+
+void ContextLifecycleObserver::ObserverListWillBeCleared() {
+ notifier_ = nullptr;
+}
+
+void ContextLifecycleObserver::SetContextLifecycleNotifier(
+ ContextLifecycleNotifier* notifier) {
+ if (notifier == notifier_)
+ return;
+
+ if (notifier_)
+ notifier_->RemoveContextLifecycleObserver(this);
+
+ notifier_ = notifier;
+
+ if (notifier_)
+ notifier_->AddContextLifecycleObserver(this);
+}
+
+void ContextLifecycleObserver::Trace(Visitor* visitor) {
+ visitor->Trace(notifier_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/context_lifecycle_observer.h b/chromium/third_party/blink/renderer/platform/context_lifecycle_observer.h
new file mode 100644
index 00000000000..cc5ef14ff92
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/context_lifecycle_observer.h
@@ -0,0 +1,41 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_CONTEXT_LIFECYCLE_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_CONTEXT_LIFECYCLE_OBSERVER_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ContextLifecycleNotifier;
+
+// Observer that gets notified when the context is destroyed. Used to observe
+// ExecutionContext from platform/.
+class PLATFORM_EXPORT ContextLifecycleObserver : public GarbageCollectedMixin {
+ public:
+ virtual void ContextDestroyed() = 0;
+
+ // Call before clearing an observer list.
+ void ObserverListWillBeCleared();
+
+ ContextLifecycleNotifier* GetContextLifecycleNotifier() const {
+ return notifier_;
+ }
+ void SetContextLifecycleNotifier(ContextLifecycleNotifier*);
+
+ virtual bool IsExecutionContextLifecycleObserver() const { return false; }
+
+ void Trace(Visitor*) override;
+
+ protected:
+ ContextLifecycleObserver() = default;
+
+ private:
+ WeakMember<ContextLifecycleNotifier> notifier_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_CONTEXT_LIFECYCLE_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/crypto_result.h b/chromium/third_party/blink/renderer/platform/crypto_result.h
index 2fc6b5aa1ee..9b4e3d54825 100644
--- a/chromium/third_party/blink/renderer/platform/crypto_result.h
+++ b/chromium/third_party/blink/renderer/platform/crypto_result.h
@@ -61,7 +61,7 @@ class PLATFORM_EXPORT CryptoResult : public GarbageCollected<CryptoResult> {
virtual void CompleteWithKeyPair(const WebCryptoKey& public_key,
const WebCryptoKey& private_key) = 0;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/cursor.cc b/chromium/third_party/blink/renderer/platform/cursor.cc
deleted file mode 100644
index e8eb0874b09..00000000000
--- a/chromium/third_party/blink/renderer/platform/cursor.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/cursor.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-
-IntPoint DetermineHotSpot(Image* image,
- bool hot_spot_specified,
- const IntPoint& specified_hot_spot) {
- if (image->IsNull())
- return IntPoint();
-
- IntRect image_rect = image->Rect();
-
- // Hot spot must be inside cursor rectangle.
- if (hot_spot_specified) {
- if (image_rect.Contains(specified_hot_spot)) {
- return specified_hot_spot;
- }
-
- return IntPoint(clampTo<int>(specified_hot_spot.X(), image_rect.X(),
- image_rect.MaxX() - 1),
- clampTo<int>(specified_hot_spot.Y(), image_rect.Y(),
- image_rect.MaxY() - 1));
- }
-
- // If hot spot is not specified externally, it can be extracted from some
- // image formats (e.g. .cur).
- IntPoint intrinsic_hot_spot;
- bool image_has_intrinsic_hot_spot = image->GetHotSpot(intrinsic_hot_spot);
- if (image_has_intrinsic_hot_spot && image_rect.Contains(intrinsic_hot_spot))
- return intrinsic_hot_spot;
-
- // If neither is provided, use a default value of (0, 0).
- return IntPoint();
-}
-
-Cursor::Cursor(Image* image, bool hot_spot_specified, const IntPoint& hot_spot)
- : type_(ui::CursorType::kCustom),
- image_(image),
- hot_spot_(DetermineHotSpot(image, hot_spot_specified, hot_spot)),
- image_scale_factor_(1) {}
-
-Cursor::Cursor(Image* image,
- bool hot_spot_specified,
- const IntPoint& hot_spot,
- float scale)
- : type_(ui::CursorType::kCustom),
- image_(image),
- hot_spot_(DetermineHotSpot(image, hot_spot_specified, hot_spot)),
- image_scale_factor_(scale) {}
-
-Cursor::Cursor(ui::CursorType type) : type_(type), image_scale_factor_(1) {}
-
-Cursor::Cursor(const Cursor& other) = default;
-
-Cursor& Cursor::operator=(const Cursor& other) {
- type_ = other.type_;
- image_ = other.image_;
- hot_spot_ = other.hot_spot_;
- image_scale_factor_ = other.image_scale_factor_;
- return *this;
-}
-
-Cursor::~Cursor() = default;
-
-const Cursor& PointerCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kPointer));
- return c;
-}
-
-const Cursor& CrossCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kCross));
- return c;
-}
-
-const Cursor& HandCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kHand));
- return c;
-}
-
-const Cursor& MoveCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kMove));
- return c;
-}
-
-const Cursor& VerticalTextCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kVerticalText));
- return c;
-}
-
-const Cursor& CellCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kCell));
- return c;
-}
-
-const Cursor& ContextMenuCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kContextMenu));
- return c;
-}
-
-const Cursor& AliasCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kAlias));
- return c;
-}
-
-const Cursor& ZoomInCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kZoomIn));
- return c;
-}
-
-const Cursor& ZoomOutCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kZoomOut));
- return c;
-}
-
-const Cursor& CopyCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kCopy));
- return c;
-}
-
-const Cursor& NoneCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNone));
- return c;
-}
-
-const Cursor& ProgressCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kProgress));
- return c;
-}
-
-const Cursor& NoDropCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNoDrop));
- return c;
-}
-
-const Cursor& NotAllowedCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNotAllowed));
- return c;
-}
-
-const Cursor& IBeamCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kIBeam));
- return c;
-}
-
-const Cursor& WaitCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kWait));
- return c;
-}
-
-const Cursor& HelpCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kHelp));
- return c;
-}
-
-const Cursor& EastResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kEastResize));
- return c;
-}
-
-const Cursor& NorthResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthResize));
- return c;
-}
-
-const Cursor& NorthEastResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthEastResize));
- return c;
-}
-
-const Cursor& NorthWestResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthWestResize));
- return c;
-}
-
-const Cursor& SouthResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kSouthResize));
- return c;
-}
-
-const Cursor& SouthEastResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kSouthEastResize));
- return c;
-}
-
-const Cursor& SouthWestResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kSouthWestResize));
- return c;
-}
-
-const Cursor& WestResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kWestResize));
- return c;
-}
-
-const Cursor& NorthSouthResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthSouthResize));
- return c;
-}
-
-const Cursor& EastWestResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kEastWestResize));
- return c;
-}
-
-const Cursor& NorthEastSouthWestResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthEastSouthWestResize));
- return c;
-}
-
-const Cursor& NorthWestSouthEastResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthWestSouthEastResize));
- return c;
-}
-
-const Cursor& ColumnResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kColumnResize));
- return c;
-}
-
-const Cursor& RowResizeCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kRowResize));
- return c;
-}
-
-const Cursor& MiddlePanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kMiddlePanning));
- return c;
-}
-
-const Cursor& MiddlePanningVerticalCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kMiddlePanningVertical));
- return c;
-}
-
-const Cursor& MiddlePanningHorizontalCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kMiddlePanningHorizontal));
- return c;
-}
-
-const Cursor& EastPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kEastPanning));
- return c;
-}
-
-const Cursor& NorthPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthPanning));
- return c;
-}
-
-const Cursor& NorthEastPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthEastPanning));
- return c;
-}
-
-const Cursor& NorthWestPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kNorthWestPanning));
- return c;
-}
-
-const Cursor& SouthPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kSouthPanning));
- return c;
-}
-
-const Cursor& SouthEastPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kSouthEastPanning));
- return c;
-}
-
-const Cursor& SouthWestPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kSouthWestPanning));
- return c;
-}
-
-const Cursor& WestPanningCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kWestPanning));
- return c;
-}
-
-const Cursor& GrabCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kGrab));
- return c;
-}
-
-const Cursor& GrabbingCursor() {
- DEFINE_STATIC_LOCAL(Cursor, c, (ui::CursorType::kGrabbing));
- return c;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/cursor.h b/chromium/third_party/blink/renderer/platform/cursor.h
deleted file mode 100644
index 4317df0a668..00000000000
--- a/chromium/third_party/blink/renderer/platform/cursor.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_CURSOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_CURSOR_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/web_cursor_info.h"
-#include "third_party/blink/renderer/platform/geometry/int_point.h"
-#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-// To avoid conflicts with the CreateWindow macro from the Windows SDK...
-#undef CopyCursor
-
-namespace blink {
-
-class PLATFORM_EXPORT Cursor {
- USING_FAST_MALLOC(Cursor);
-
- public:
- Cursor()
- // This is an invalid Cursor and should never actually get used.
- : type_(ui::CursorType::kNull) {}
-
- Cursor(Image*, bool hot_spot_specified, const IntPoint& hot_spot);
-
- // Hot spot is in image pixels.
- Cursor(Image*,
- bool hot_spot_specified,
- const IntPoint& hot_spot,
- float image_scale_factor);
-
- Cursor(const Cursor&);
- ~Cursor();
- Cursor& operator=(const Cursor&);
-
- explicit Cursor(ui::CursorType);
- ui::CursorType GetType() const {
- DCHECK_GE(type_, static_cast<ui::CursorType>(0));
- DCHECK_LE(type_, ui::CursorType::kCustom);
- return type_;
- }
- Image* GetImage() const { return image_.get(); }
- const IntPoint& HotSpot() const { return hot_spot_; }
- // Image scale in image pixels per logical (UI) pixel.
- float ImageScaleFactor() const { return image_scale_factor_; }
-
- private:
- ui::CursorType type_;
- scoped_refptr<Image> image_;
- IntPoint hot_spot_;
- float image_scale_factor_;
-};
-
-PLATFORM_EXPORT IntPoint DetermineHotSpot(Image*,
- bool hot_spot_specified,
- const IntPoint& specified_hot_spot);
-
-PLATFORM_EXPORT const Cursor& PointerCursor();
-PLATFORM_EXPORT const Cursor& CrossCursor();
-PLATFORM_EXPORT const Cursor& HandCursor();
-PLATFORM_EXPORT const Cursor& MoveCursor();
-PLATFORM_EXPORT const Cursor& IBeamCursor();
-PLATFORM_EXPORT const Cursor& WaitCursor();
-PLATFORM_EXPORT const Cursor& HelpCursor();
-PLATFORM_EXPORT const Cursor& EastResizeCursor();
-PLATFORM_EXPORT const Cursor& NorthResizeCursor();
-PLATFORM_EXPORT const Cursor& NorthEastResizeCursor();
-PLATFORM_EXPORT const Cursor& NorthWestResizeCursor();
-PLATFORM_EXPORT const Cursor& SouthResizeCursor();
-PLATFORM_EXPORT const Cursor& SouthEastResizeCursor();
-PLATFORM_EXPORT const Cursor& SouthWestResizeCursor();
-PLATFORM_EXPORT const Cursor& WestResizeCursor();
-PLATFORM_EXPORT const Cursor& NorthSouthResizeCursor();
-PLATFORM_EXPORT const Cursor& EastWestResizeCursor();
-PLATFORM_EXPORT const Cursor& NorthEastSouthWestResizeCursor();
-PLATFORM_EXPORT const Cursor& NorthWestSouthEastResizeCursor();
-PLATFORM_EXPORT const Cursor& ColumnResizeCursor();
-PLATFORM_EXPORT const Cursor& RowResizeCursor();
-PLATFORM_EXPORT const Cursor& MiddlePanningCursor();
-PLATFORM_EXPORT const Cursor& MiddlePanningVerticalCursor();
-PLATFORM_EXPORT const Cursor& MiddlePanningHorizontalCursor();
-PLATFORM_EXPORT const Cursor& EastPanningCursor();
-PLATFORM_EXPORT const Cursor& NorthPanningCursor();
-PLATFORM_EXPORT const Cursor& NorthEastPanningCursor();
-PLATFORM_EXPORT const Cursor& NorthWestPanningCursor();
-PLATFORM_EXPORT const Cursor& SouthPanningCursor();
-PLATFORM_EXPORT const Cursor& SouthEastPanningCursor();
-PLATFORM_EXPORT const Cursor& SouthWestPanningCursor();
-PLATFORM_EXPORT const Cursor& WestPanningCursor();
-PLATFORM_EXPORT const Cursor& VerticalTextCursor();
-PLATFORM_EXPORT const Cursor& CellCursor();
-PLATFORM_EXPORT const Cursor& ContextMenuCursor();
-PLATFORM_EXPORT const Cursor& NoDropCursor();
-PLATFORM_EXPORT const Cursor& NotAllowedCursor();
-PLATFORM_EXPORT const Cursor& ProgressCursor();
-PLATFORM_EXPORT const Cursor& AliasCursor();
-PLATFORM_EXPORT const Cursor& ZoomInCursor();
-PLATFORM_EXPORT const Cursor& ZoomOutCursor();
-PLATFORM_EXPORT const Cursor& CopyCursor();
-PLATFORM_EXPORT const Cursor& NoneCursor();
-PLATFORM_EXPORT const Cursor& GrabCursor();
-PLATFORM_EXPORT const Cursor& GrabbingCursor();
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_CURSOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/cursors.cc b/chromium/third_party/blink/renderer/platform/cursors.cc
new file mode 100644
index 00000000000..a3a9c9f7fe9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/cursors.cc
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/cursors.h"
+
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/mojom/cursor_type.mojom-blink.h"
+
+// To avoid conflicts with the CreateWindow macro from the Windows SDK...
+#undef CopyCursor
+
+namespace blink {
+
+const ui::Cursor& PointerCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kPointer));
+ return c;
+}
+
+const ui::Cursor& CrossCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kCross));
+ return c;
+}
+
+const ui::Cursor& HandCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kHand));
+ return c;
+}
+
+const ui::Cursor& MoveCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kMove));
+ return c;
+}
+
+const ui::Cursor& VerticalTextCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kVerticalText));
+ return c;
+}
+
+const ui::Cursor& CellCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kCell));
+ return c;
+}
+
+const ui::Cursor& ContextMenuCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kContextMenu));
+ return c;
+}
+
+const ui::Cursor& AliasCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kAlias));
+ return c;
+}
+
+const ui::Cursor& ZoomInCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kZoomIn));
+ return c;
+}
+
+const ui::Cursor& ZoomOutCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kZoomOut));
+ return c;
+}
+
+const ui::Cursor& CopyCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kCopy));
+ return c;
+}
+
+const ui::Cursor& NoneCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kNone));
+ return c;
+}
+
+const ui::Cursor& ProgressCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kProgress));
+ return c;
+}
+
+const ui::Cursor& NoDropCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kNoDrop));
+ return c;
+}
+
+const ui::Cursor& NotAllowedCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNotAllowed));
+ return c;
+}
+
+const ui::Cursor& IBeamCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kIBeam));
+ return c;
+}
+
+const ui::Cursor& WaitCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kWait));
+ return c;
+}
+
+const ui::Cursor& HelpCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kHelp));
+ return c;
+}
+
+const ui::Cursor& EastResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kEastResize));
+ return c;
+}
+
+const ui::Cursor& NorthResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthResize));
+ return c;
+}
+
+const ui::Cursor& NorthEastResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthEastResize));
+ return c;
+}
+
+const ui::Cursor& NorthWestResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthWestResize));
+ return c;
+}
+
+const ui::Cursor& SouthResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kSouthResize));
+ return c;
+}
+
+const ui::Cursor& SouthEastResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kSouthEastResize));
+ return c;
+}
+
+const ui::Cursor& SouthWestResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kSouthWestResize));
+ return c;
+}
+
+const ui::Cursor& WestResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kWestResize));
+ return c;
+}
+
+const ui::Cursor& NorthSouthResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthSouthResize));
+ return c;
+}
+
+const ui::Cursor& EastWestResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kEastWestResize));
+ return c;
+}
+
+const ui::Cursor& NorthEastSouthWestResizeCursor() {
+ DEFINE_STATIC_LOCAL(
+ ui::Cursor, c, (ui::mojom::blink::CursorType::kNorthEastSouthWestResize));
+ return c;
+}
+
+const ui::Cursor& NorthWestSouthEastResizeCursor() {
+ DEFINE_STATIC_LOCAL(
+ ui::Cursor, c, (ui::mojom::blink::CursorType::kNorthWestSouthEastResize));
+ return c;
+}
+
+const ui::Cursor& ColumnResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kColumnResize));
+ return c;
+}
+
+const ui::Cursor& RowResizeCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kRowResize));
+ return c;
+}
+
+const ui::Cursor& MiddlePanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kMiddlePanning));
+ return c;
+}
+
+const ui::Cursor& MiddlePanningVerticalCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kMiddlePanningVertical));
+ return c;
+}
+
+const ui::Cursor& MiddlePanningHorizontalCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kMiddlePanningHorizontal));
+ return c;
+}
+
+const ui::Cursor& EastPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kEastPanning));
+ return c;
+}
+
+const ui::Cursor& NorthPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthPanning));
+ return c;
+}
+
+const ui::Cursor& NorthEastPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthEastPanning));
+ return c;
+}
+
+const ui::Cursor& NorthWestPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kNorthWestPanning));
+ return c;
+}
+
+const ui::Cursor& SouthPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kSouthPanning));
+ return c;
+}
+
+const ui::Cursor& SouthEastPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kSouthEastPanning));
+ return c;
+}
+
+const ui::Cursor& SouthWestPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kSouthWestPanning));
+ return c;
+}
+
+const ui::Cursor& WestPanningCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c,
+ (ui::mojom::blink::CursorType::kWestPanning));
+ return c;
+}
+
+const ui::Cursor& GrabCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kGrab));
+ return c;
+}
+
+const ui::Cursor& GrabbingCursor() {
+ DEFINE_STATIC_LOCAL(ui::Cursor, c, (ui::mojom::blink::CursorType::kGrabbing));
+ return c;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/cursors.h b/chromium/third_party/blink/renderer/platform/cursors.h
new file mode 100644
index 00000000000..8cfba611ec7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/cursors.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_CURSORS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_CURSORS_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+// To avoid conflicts with the CreateWindow macro from the Windows SDK...
+#undef CopyCursor
+
+namespace ui {
+class Cursor;
+}
+
+namespace blink {
+
+PLATFORM_EXPORT const ui::Cursor& PointerCursor();
+PLATFORM_EXPORT const ui::Cursor& CrossCursor();
+PLATFORM_EXPORT const ui::Cursor& HandCursor();
+PLATFORM_EXPORT const ui::Cursor& MoveCursor();
+PLATFORM_EXPORT const ui::Cursor& IBeamCursor();
+PLATFORM_EXPORT const ui::Cursor& WaitCursor();
+PLATFORM_EXPORT const ui::Cursor& HelpCursor();
+PLATFORM_EXPORT const ui::Cursor& EastResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthEastResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthWestResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& SouthResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& SouthEastResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& SouthWestResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& WestResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthSouthResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& EastWestResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthEastSouthWestResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthWestSouthEastResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& ColumnResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& RowResizeCursor();
+PLATFORM_EXPORT const ui::Cursor& MiddlePanningCursor();
+PLATFORM_EXPORT const ui::Cursor& MiddlePanningVerticalCursor();
+PLATFORM_EXPORT const ui::Cursor& MiddlePanningHorizontalCursor();
+PLATFORM_EXPORT const ui::Cursor& EastPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthEastPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& NorthWestPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& SouthPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& SouthEastPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& SouthWestPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& WestPanningCursor();
+PLATFORM_EXPORT const ui::Cursor& VerticalTextCursor();
+PLATFORM_EXPORT const ui::Cursor& CellCursor();
+PLATFORM_EXPORT const ui::Cursor& ContextMenuCursor();
+PLATFORM_EXPORT const ui::Cursor& NoDropCursor();
+PLATFORM_EXPORT const ui::Cursor& NotAllowedCursor();
+PLATFORM_EXPORT const ui::Cursor& ProgressCursor();
+PLATFORM_EXPORT const ui::Cursor& AliasCursor();
+PLATFORM_EXPORT const ui::Cursor& ZoomInCursor();
+PLATFORM_EXPORT const ui::Cursor& ZoomOutCursor();
+PLATFORM_EXPORT const ui::Cursor& CopyCursor();
+PLATFORM_EXPORT const ui::Cursor& NoneCursor();
+PLATFORM_EXPORT const ui::Cursor& GrabCursor();
+PLATFORM_EXPORT const ui::Cursor& GrabbingCursor();
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_CURSORS_H_
diff --git a/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc b/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc
new file mode 100644
index 00000000000..2ca595652a0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/disk_data_allocator.cc
@@ -0,0 +1,206 @@
+// 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 "third_party/blink/renderer/platform/disk_data_allocator.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+
+DiskDataAllocator::DiskDataAllocator()
+ : free_chunks_size_(0), file_tail_(0), may_write_(false) {}
+
+DiskDataAllocator::~DiskDataAllocator() = default;
+
+bool DiskDataAllocator::may_write() {
+ MutexLocker locker(mutex_);
+ return may_write_;
+}
+
+void DiskDataAllocator::set_may_write_for_testing(bool may_write) {
+ MutexLocker locker(mutex_);
+ may_write_ = may_write;
+}
+
+DiskDataAllocator::Metadata DiskDataAllocator::FindChunk(size_t size) {
+ // Try to reuse some space. Policy:
+ // 1. Exact fit
+ // 2. Worst fit
+ Metadata chosen_chunk{-1, 0};
+
+ size_t worst_fit_size = 0;
+ for (const auto& chunk : free_chunks_) {
+ size_t chunk_size = chunk.second;
+ if (size == chunk_size) {
+ chosen_chunk = {chunk.first, chunk.second};
+ break;
+ } else if (chunk_size > size && chunk_size > worst_fit_size) {
+ chosen_chunk = {chunk.first, chunk.second};
+ worst_fit_size = chunk.second;
+ }
+ }
+
+ if (chosen_chunk.start_offset() != -1) {
+ free_chunks_size_ -= size;
+ free_chunks_.erase(chosen_chunk.start_offset());
+ if (chosen_chunk.size() > size) {
+ std::pair<int64_t, size_t> remainder_chunk = {
+ chosen_chunk.start_offset() + size, chosen_chunk.size() - size};
+ auto result = free_chunks_.insert(remainder_chunk);
+ DCHECK(result.second);
+ chosen_chunk.size_ = size;
+ }
+ } else {
+ chosen_chunk = {file_tail_, size};
+ file_tail_ += size;
+ }
+
+ return chosen_chunk;
+}
+
+void DiskDataAllocator::ReleaseChunk(const Metadata& metadata) {
+ Metadata chunk = metadata;
+ DCHECK(free_chunks_.find(chunk.start_offset()) == free_chunks_.end());
+
+ auto lower_bound = free_chunks_.lower_bound(chunk.start_offset());
+ DCHECK(free_chunks_.upper_bound(chunk.start_offset()) ==
+ free_chunks_.lower_bound(chunk.start_offset()));
+ if (lower_bound != free_chunks_.begin()) {
+ // There is a chunk left.
+ auto left = --lower_bound;
+ // Can merge with the left chunk.
+ int64_t left_chunk_end = left->first + left->second;
+ DCHECK_LE(left_chunk_end, chunk.start_offset());
+ if (left_chunk_end == chunk.start_offset()) {
+ chunk = {left->first, left->second + chunk.size()};
+ free_chunks_size_ -= left->second;
+ free_chunks_.erase(left);
+ }
+ }
+
+ auto right = free_chunks_.upper_bound(chunk.start_offset());
+ if (right != free_chunks_.end()) {
+ DCHECK_NE(right->first, chunk.start_offset());
+ int64_t chunk_end = chunk.start_offset() + chunk.size();
+ DCHECK_LE(chunk_end, right->first);
+ if (right->first == chunk_end) {
+ chunk = {chunk.start_offset(), chunk.size() + right->second};
+ free_chunks_size_ -= right->second;
+ free_chunks_.erase(right);
+ }
+ }
+
+ auto result = free_chunks_.insert({chunk.start_offset(), chunk.size()});
+ DCHECK(result.second);
+ free_chunks_size_ += chunk.size();
+}
+
+std::unique_ptr<DiskDataAllocator::Metadata> DiskDataAllocator::Write(
+ const void* data,
+ size_t size) {
+ Metadata chosen_chunk = {0, 0};
+
+ {
+ MutexLocker locker(mutex_);
+ if (!may_write_)
+ return nullptr;
+
+ chosen_chunk = FindChunk(size);
+ } // Don't hold the lock during the actual Write().
+
+ int size_int = static_cast<int>(size);
+ const char* data_char = reinterpret_cast<const char*>(data);
+ int written = DoWrite(chosen_chunk.start_offset(), data_char, size_int);
+
+ MutexLocker locker(mutex_);
+ if (size_int != written) {
+ // Assume that the error is not transient. This can happen if the disk is
+ // full for instance, in which case it is likely better not to try writing
+ // later.
+ may_write_ = false;
+ return nullptr;
+ }
+
+#if DCHECK_IS_ON()
+ allocated_chunks_.insert({chosen_chunk.start_offset(), chosen_chunk.size()});
+#endif
+
+ return std::unique_ptr<Metadata>(
+ new Metadata(chosen_chunk.start_offset(), chosen_chunk.size()));
+}
+
+bool DiskDataAllocator::Read(const Metadata& metadata, void* data) {
+ DCHECK(IsMainThread());
+
+ // Doesn't need locking as files support concurrent access, and we don't
+ // update metadata.
+ char* data_char = reinterpret_cast<char*>(data);
+ DoRead(metadata.start_offset(), data_char, metadata.size());
+
+#if DCHECK_IS_ON()
+ {
+ MutexLocker locker(mutex_);
+ auto it = allocated_chunks_.find(metadata.start_offset());
+ DCHECK(it != allocated_chunks_.end());
+ DCHECK_EQ(metadata.size(), it->second);
+ }
+#endif
+
+ return true;
+}
+
+void DiskDataAllocator::Discard(std::unique_ptr<Metadata> metadata) {
+ MutexLocker locker(mutex_);
+ DCHECK(may_write_ || file_.IsValid());
+
+#if DCHECK_IS_ON()
+ auto it = allocated_chunks_.find(metadata->start_offset());
+ DCHECK(it != allocated_chunks_.end());
+ DCHECK_EQ(metadata->size(), it->second);
+ allocated_chunks_.erase(it);
+#endif
+
+ ReleaseChunk(*metadata);
+}
+
+int DiskDataAllocator::DoWrite(int64_t offset, const char* data, int size) {
+ int rv = file_.Write(offset, data, size);
+
+ // No PCHECK(), since a file writing error is recoverable.
+ if (rv != size) {
+ LOG(ERROR) << "DISK: Cannot write to disk. written = " << rv << " "
+ << base::File::ErrorToString(base::File::GetLastFileError());
+ }
+ return rv;
+}
+
+void DiskDataAllocator::DoRead(int64_t offset, char* data, int size) {
+ int rv = file_.Read(offset, data, size);
+ // Can only crash, since we cannot continue without the data.
+ PCHECK(rv == size) << "Likely file corruption.";
+}
+
+void DiskDataAllocator::ProvideTemporaryFile(base::File file) {
+ MutexLocker locker(mutex_);
+ DCHECK(IsMainThread());
+ DCHECK(!file_.IsValid());
+ DCHECK(!may_write_);
+
+ file_ = std::move(file);
+ if (file_.IsValid())
+ may_write_ = true;
+}
+
+// static
+DiskDataAllocator& DiskDataAllocator::Instance() {
+ DEFINE_STATIC_LOCAL(DiskDataAllocator, instance, ());
+ return instance;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/disk_data_allocator.h b/chromium/third_party/blink/renderer/platform/disk_data_allocator.h
new file mode 100644
index 00000000000..5c53a04738e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/disk_data_allocator.h
@@ -0,0 +1,116 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_DISK_DATA_ALLOCATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_DISK_DATA_ALLOCATOR_H_
+
+#include <map>
+#include <memory>
+
+#include "base/files/file.h"
+#include "base/synchronization/lock.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/threading.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+
+namespace blink {
+
+// Stores data onto a single file.
+//
+// The file is provided after construction. As a consequence, the allocator
+// initially does not accept writes, that is |Write()| returns nullptr. It may
+// also become not usable later, for instance if disk space is no longer
+// available.
+//
+// Threading:
+// - Reads must be done from the main thread
+// - Writes can be done from any thread.
+// - public methods are thread-safe, and unless otherwise noted, can be called
+// from any thread.
+class PLATFORM_EXPORT DiskDataAllocator {
+ public:
+ class Metadata {
+ public:
+ int64_t start_offset() const { return start_offset_; }
+ size_t size() const { return size_; }
+ Metadata(Metadata&& other) = delete;
+
+ private:
+ Metadata(int64_t start_offset, size_t size)
+ : start_offset_(start_offset), size_(size) {}
+ Metadata(const Metadata& other) = default;
+ Metadata& operator=(const Metadata& other) = default;
+
+ int64_t start_offset_;
+ size_t size_;
+
+ friend class DiskDataAllocator;
+ };
+
+ // Must be called on the main thread.
+ void ProvideTemporaryFile(::base::File file);
+
+ // Whether writes may succeed. This is not a guarantee. However, when this
+ // returns false, writes will fail.
+ bool may_write() LOCKS_EXCLUDED(mutex_);
+
+ // Returns |nullptr| in case of error.
+ // Note that this performs a blocking disk write.
+ std::unique_ptr<Metadata> Write(const void* data, size_t size);
+
+ // Returns |false| in case of error.
+ // Must be called from the main thread.
+ // Can be called at any time before |Discard()| destroys |metadata|.
+ //
+ // |data| must point to an area large enough to fit a |metadata.size|-ed
+ // array. Note that this performs a blocking disk read.
+ bool Read(const Metadata& metadata, void* data);
+
+ // Discards existing data pointed at by |metadata|.
+ void Discard(std::unique_ptr<Metadata> metadata);
+
+ virtual ~DiskDataAllocator();
+ static DiskDataAllocator& Instance();
+
+ protected:
+ // Protected methods for testing.
+ DiskDataAllocator();
+ void set_may_write_for_testing(bool may_write) LOCKS_EXCLUDED(mutex_);
+
+ private:
+ Metadata FindChunk(size_t size) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ void ReleaseChunk(const Metadata& metadata) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Virtual for testing.
+ virtual int DoWrite(int64_t offset, const char* data, int size)
+ LOCKS_EXCLUDED(mutex_);
+ // CHECK()s that the read is successful.
+ virtual void DoRead(int64_t offset, char* data, int size);
+
+ base::File file_; // May be invalid.
+
+ protected: // For testing.
+ Mutex mutex_;
+ // Using a std::map because we rely on |{lower,upper}_bound()|.
+ std::map<int64_t, size_t> free_chunks_ GUARDED_BY(mutex_);
+ size_t free_chunks_size_ GUARDED_BY(mutex_);
+
+ private:
+ int64_t file_tail_ GUARDED_BY(mutex_);
+ // Whether writing is possible now. This can be true if:
+ // - |set_may_write_for_testing()| was called, or
+ // - |file_.IsValid()| and no write error occurred (which would set
+ // |may_write_| to false).
+ bool may_write_ GUARDED_BY(mutex_);
+#if DCHECK_IS_ON()
+ std::map<int64_t, size_t> allocated_chunks_ GUARDED_BY(mutex_);
+#endif
+
+ FRIEND_TEST_ALL_PREFIXES(DiskDataAllocatorTest, ProvideInvalidFile);
+ FRIEND_TEST_ALL_PREFIXES(DiskDataAllocatorTest, ProvideValidFile);
+};
+
+} // namespace blink
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_DISK_DATA_ALLOCATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/disk_data_allocator_test.cc b/chromium/third_party/blink/renderer/platform/disk_data_allocator_test.cc
new file mode 100644
index 00000000000..b1ac3b51e4e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/disk_data_allocator_test.cc
@@ -0,0 +1,266 @@
+// 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 "third_party/blink/renderer/platform/disk_data_allocator.h"
+
+#include <cstring>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/rand_util.h"
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/disk_data_allocator_test_utils.h"
+
+using ThreadPoolExecutionMode =
+ base::test::TaskEnvironment::ThreadPoolExecutionMode;
+
+namespace blink {
+
+class DiskDataAllocatorTest : public ::testing::Test {
+ public:
+ explicit DiskDataAllocatorTest(
+ ThreadPoolExecutionMode thread_pool_execution_mode =
+ ThreadPoolExecutionMode::DEFAULT)
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME,
+ thread_pool_execution_mode) {}
+
+ static std::vector<std::unique_ptr<DiskDataAllocator::Metadata>>
+ Allocate(InMemoryDataAllocator* allocator, size_t size, size_t count) {
+ std::string random_data = base::RandBytesAsString(size);
+
+ std::vector<std::unique_ptr<DiskDataAllocator::Metadata>> all_metadata;
+ for (size_t i = 0; i < count; i++) {
+ auto metadata = allocator->Write(random_data.c_str(), random_data.size());
+ EXPECT_EQ(metadata->start_offset(), static_cast<int64_t>(i * size));
+ all_metadata.push_back(std::move(metadata));
+ }
+ return all_metadata;
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(DiskDataAllocatorTest, ReadWrite) {
+ InMemoryDataAllocator allocator;
+
+ constexpr size_t kSize = 1000;
+ std::string random_data = base::RandBytesAsString(kSize);
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ EXPECT_TRUE(metadata);
+ EXPECT_EQ(kSize, metadata->size());
+
+ auto read_data = std::vector<char>(kSize);
+ bool ok = allocator.Read(*metadata, &read_data[0]);
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, memcmp(&read_data[0], random_data.c_str(), kSize));
+}
+
+TEST_F(DiskDataAllocatorTest, ReadWriteDiscardMultiple) {
+ InMemoryDataAllocator allocator;
+
+ std::vector<
+ std::pair<std::unique_ptr<DiskDataAllocator::Metadata>, std::string>>
+ data_written;
+
+ for (int i = 0; i < 10; i++) {
+ int size = base::RandInt(100, 1000);
+ auto data = base::RandBytesAsString(size);
+ auto metadata = allocator.Write(&data[0], size);
+ ASSERT_TRUE(metadata);
+ data_written.emplace_back(std::move(metadata), data);
+ }
+
+ base::RandomShuffle(data_written.begin(), data_written.end());
+
+ for (const auto& p : data_written) {
+ size_t size = p.first->size();
+ auto read_data = std::vector<char>(size);
+ bool ok = allocator.Read(*p.first, &read_data[0]);
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, memcmp(&read_data[0], &p.second[0], size));
+ }
+
+ base::RandomShuffle(data_written.begin(), data_written.end());
+
+ for (auto& p : data_written) {
+ auto metadata = std::move(p.first);
+ allocator.Discard(std::move(metadata));
+ }
+}
+
+TEST_F(DiskDataAllocatorTest, WriteEventuallyFail) {
+ InMemoryDataAllocator allocator;
+
+ constexpr size_t kSize = 1 << 18;
+ std::string random_data = base::RandBytesAsString(kSize);
+
+ static_assert(4 * kSize == InMemoryDataAllocator::kMaxSize, "");
+ for (int i = 0; i < 4; i++) {
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ EXPECT_TRUE(metadata);
+ }
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ EXPECT_FALSE(metadata);
+ EXPECT_FALSE(allocator.may_write());
+}
+
+TEST_F(DiskDataAllocatorTest, CanReuseFreedChunk) {
+ InMemoryDataAllocator allocator;
+
+ constexpr size_t kSize = 1 << 10;
+ std::vector<std::unique_ptr<DiskDataAllocator::Metadata>> all_metadata;
+
+ for (int i = 0; i < 10; i++) {
+ std::string random_data = base::RandBytesAsString(kSize);
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ ASSERT_TRUE(metadata);
+ all_metadata.push_back(std::move(metadata));
+ }
+
+ auto metadata = std::move(all_metadata[4]);
+ ASSERT_TRUE(metadata);
+ int64_t start_offset = metadata->start_offset();
+ allocator.Discard(std::move(metadata));
+
+ std::string random_data = base::RandBytesAsString(kSize);
+ auto new_metadata = allocator.Write(random_data.c_str(), random_data.size());
+ ASSERT_TRUE(new_metadata);
+ EXPECT_EQ(new_metadata->start_offset(), start_offset);
+}
+
+TEST_F(DiskDataAllocatorTest, ExactThenWorstFit) {
+ InMemoryDataAllocator allocator;
+
+ int count = 10;
+ size_t size_increment = 1000;
+ std::vector<std::unique_ptr<DiskDataAllocator::Metadata>> all_metadata;
+
+ size_t size = 10000;
+ // Allocate a bunch of random-sized
+ for (int i = 0; i < count; i++) {
+ std::string random_data = base::RandBytesAsString(size);
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ ASSERT_TRUE(metadata);
+ all_metadata.push_back(std::move(metadata));
+ size += size_increment;
+ }
+
+ auto& hole_metadata = all_metadata[4];
+ size_t hole_size = hole_metadata->size();
+ int64_t hole_offset = hole_metadata->start_offset();
+ allocator.Discard(std::move(hole_metadata));
+
+ auto& larger_hole_metadata = all_metadata[9];
+ int64_t larger_hole_offset = larger_hole_metadata->start_offset();
+ allocator.Discard(std::move(larger_hole_metadata));
+
+ std::string random_data = base::RandBytesAsString(hole_size);
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ // Exact fit.
+ EXPECT_EQ(metadata->start_offset(), hole_offset);
+ allocator.Discard(std::move(metadata));
+
+ // -1 to check that this is not best fit.
+ random_data = base::RandBytesAsString(hole_size - 1);
+ metadata = allocator.Write(random_data.c_str(), random_data.size());
+ EXPECT_EQ(metadata->start_offset(), larger_hole_offset);
+}
+
+TEST_F(DiskDataAllocatorTest, FreeChunksMerging) {
+ constexpr size_t kSize = 100;
+
+ auto allocator = std::make_unique<InMemoryDataAllocator>();
+ auto chunks = Allocate(allocator.get(), kSize, 4);
+
+ // Layout is (indices in |chunks|):
+ // | 0 | 1 | 2 | 3 |
+ // Discarding a higher index after a lower one triggers merging on the left.
+
+ // Merge left.
+ allocator->Discard(std::move(chunks[0]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+ allocator->Discard(std::move(chunks[1]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+ EXPECT_EQ(2 * kSize, allocator->FreeChunks().begin()->second);
+ allocator->Discard(std::move(chunks[2]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+ EXPECT_EQ(3 * kSize, allocator->FreeChunks().begin()->second);
+ allocator->Discard(std::move(chunks[3]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+ EXPECT_EQ(4 * kSize, allocator->FreeChunks().begin()->second);
+
+ allocator = std::make_unique<InMemoryDataAllocator>();
+ chunks = Allocate(allocator.get(), kSize, 4);
+
+ // Merge right.
+ allocator->Discard(std::move(chunks[3]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+ allocator->Discard(std::move(chunks[2]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+ EXPECT_EQ(2 * kSize, allocator->FreeChunks().begin()->second);
+ allocator->Discard(std::move(chunks[0]));
+ EXPECT_EQ(2u, allocator->FreeChunks().size());
+ // Multiple merges: left, then right.
+ allocator->Discard(std::move(chunks[1]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+
+ allocator = std::make_unique<InMemoryDataAllocator>();
+ chunks = Allocate(allocator.get(), kSize, 4);
+
+ // Left then right merging.
+ allocator->Discard(std::move(chunks[0]));
+ allocator->Discard(std::move(chunks[2]));
+ EXPECT_EQ(2u, allocator->FreeChunks().size());
+ allocator->Discard(std::move(chunks[1]));
+ EXPECT_EQ(1u, allocator->FreeChunks().size());
+}
+
+TEST_F(DiskDataAllocatorTest, ProvideInvalidFile) {
+ DiskDataAllocator allocator;
+ EXPECT_FALSE(allocator.may_write());
+ allocator.ProvideTemporaryFile(base::File());
+ EXPECT_FALSE(allocator.may_write());
+}
+
+TEST_F(DiskDataAllocatorTest, ProvideValidFile) {
+ base::FilePath path;
+ if (!base::CreateTemporaryFile(&path))
+ GTEST_SKIP() << "Cannot create temporary file.";
+
+ int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ |
+ base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE;
+ auto file = base::File(base::FilePath(path), flags);
+ if (!file.IsValid())
+ GTEST_SKIP() << "Cannot create temporary file.";
+
+ DiskDataAllocator allocator;
+ EXPECT_FALSE(allocator.may_write());
+ allocator.ProvideTemporaryFile(std::move(file));
+ EXPECT_TRUE(allocator.may_write());
+
+ // Test read/write with a real file.
+ constexpr size_t kSize = 1000;
+ std::string random_data = base::RandBytesAsString(kSize);
+ auto metadata = allocator.Write(random_data.c_str(), random_data.size());
+ if (!metadata)
+ GTEST_SKIP() << "Disk full?";
+
+ EXPECT_EQ(kSize, metadata->size());
+
+ auto read_data = std::vector<char>(kSize);
+ bool ok = allocator.Read(*metadata, &read_data[0]);
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, memcmp(&read_data[0], random_data.c_str(), kSize));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/disk_data_allocator_test_utils.h b/chromium/third_party/blink/renderer/platform/disk_data_allocator_test_utils.h
new file mode 100644
index 00000000000..4c7bb2f37da
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/disk_data_allocator_test_utils.h
@@ -0,0 +1,66 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_DISK_DATA_ALLOCATOR_TEST_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_DISK_DATA_ALLOCATOR_TEST_UTILS_H_
+
+#include "third_party/blink/renderer/platform/disk_data_allocator.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <map>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class InMemoryDataAllocator : public DiskDataAllocator {
+ public:
+ constexpr static size_t kMaxSize = 1 << 20;
+
+ InMemoryDataAllocator() : max_offset_(0), data_(kMaxSize) {
+ set_may_write_for_testing(true);
+ }
+ ~InMemoryDataAllocator() override = default;
+
+ std::map<int64_t, size_t> FreeChunks() {
+ MutexLocker locker(mutex_);
+
+ size_t free_size = 0;
+ for (const auto& p : free_chunks_)
+ free_size += p.second;
+
+ EXPECT_EQ(free_size, free_chunks_size_);
+
+ return free_chunks_;
+ }
+
+ private:
+ int DoWrite(int64_t offset, const char* data, int size) override {
+ int64_t end_offset = offset + size;
+ if (static_cast<size_t>(end_offset) > kMaxSize)
+ return -1;
+
+ memcpy(&data_[0] + offset, data, size);
+ max_offset_ = std::max(end_offset, max_offset_);
+ return size;
+ }
+
+ void DoRead(int64_t offset, char* data, int size) override {
+ int64_t end_offset = offset + size;
+ ASSERT_LE(end_offset, max_offset_);
+
+ memcpy(data, &data_[0] + offset, size);
+ }
+
+ private:
+ int64_t max_offset_;
+ std::vector<char> data_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_DISK_DATA_ALLOCATOR_TEST_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/platform/encrypted_media_request.h b/chromium/third_party/blink/renderer/platform/encrypted_media_request.h
index 25770c1e020..be409773273 100644
--- a/chromium/third_party/blink/renderer/platform/encrypted_media_request.h
+++ b/chromium/third_party/blink/renderer/platform/encrypted_media_request.h
@@ -32,7 +32,7 @@ class EncryptedMediaRequest : public GarbageCollected<EncryptedMediaRequest> {
std::unique_ptr<WebContentDecryptionModuleAccess>) = 0;
virtual void RequestNotSupported(const WebString& error_message) = 0;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/OWNERS b/chromium/third_party/blink/renderer/platform/exported/OWNERS
index 9a717779420..f80e768428d 100644
--- a/chromium/third_party/blink/renderer/platform/exported/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/exported/OWNERS
@@ -1,2 +1,7 @@
per-file notification_data_conversions*=peter@chromium.org
per-file web_rtc_*=hbos@chromium.org
+
+# Any core owner can also approve changes to runtime-enabled features.
+# Please make sure to get a review from someone with expertise on the feature
+# you are changing.
+per-file web_runtime_features*=file://third_party/blink/renderer/core/OWNERS
diff --git a/chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_test.cc b/chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_test.cc
index c5825eed5ef..e6c83416711 100644
--- a/chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_test.cc
@@ -13,12 +13,12 @@
#include "media/base/audio_bus.h"
#include "media/base/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/exported/platform.cc b/chromium/third_party/blink/renderer/platform/exported/platform.cc
index 55f9e8146b7..d498e7d31b7 100644
--- a/chromium/third_party/blink/renderer/platform/exported/platform.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/platform.cc
@@ -38,13 +38,11 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
-#include "third_party/blink/public/platform/web_prerendering_support.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
+#include "third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.h"
@@ -69,22 +67,6 @@ namespace blink {
namespace {
-class DefaultInterfaceProvider : public InterfaceProvider {
- USING_FAST_MALLOC(DefaultInterfaceProvider);
-
- public:
- DefaultInterfaceProvider() = default;
- ~DefaultInterfaceProvider() = default;
-
- // InterfaceProvider implementation:
- void GetInterface(const char* interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override {
- Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
- mojo::GenericPendingReceiver(interface_name,
- std::move(interface_pipe)));
- }
-};
-
class DefaultBrowserInterfaceBrokerProxy
: public ThreadSafeBrowserInterfaceBrokerProxy {
USING_FAST_MALLOC(DefaultBrowserInterfaceBrokerProxy);
@@ -140,13 +122,6 @@ static Platform* g_platform = nullptr;
static GCTaskRunner* g_gc_task_runner = nullptr;
-static void CallOnMainThreadFunction(WTF::MainThreadFunction function,
- void* context) {
- PostCrossThreadTask(
- *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
- CrossThreadBindOnce(function, CrossThreadUnretained(context)));
-}
-
Platform::Platform() {
WTF::Partitions::Initialize();
}
@@ -157,6 +132,8 @@ namespace {
class SimpleMainThread : public Thread {
public:
+ SimpleMainThread() : isolate_(WebIsolate::Create()) {}
+
// We rely on base::ThreadTaskRunnerHandle for tasks posted on the main
// thread. The task runner handle may not be available on Blink's startup
// (== on SimpleMainThread's construction), because some tests like
@@ -190,6 +167,7 @@ class SimpleMainThread : public Thread {
private:
bool IsSimpleMainThread() const override { return true; }
+ std::unique_ptr<WebIsolate> isolate_;
scheduler::SimpleThreadScheduler scheduler_;
scoped_refptr<base::SingleThreadTaskRunner>
main_thread_task_runner_for_testing_;
@@ -215,7 +193,7 @@ void Platform::CreateMainThreadAndInitialize(Platform* platform) {
void Platform::InitializeCommon(Platform* platform,
std::unique_ptr<Thread> main_thread) {
- WTF::Initialize(CallOnMainThreadFunction);
+ WTF::Initialize();
Thread::SetMainThread(std::move(main_thread));
@@ -287,11 +265,6 @@ Platform* Platform::Current() {
return g_platform;
}
-InterfaceProvider* Platform::GetInterfaceProvider() {
- DEFINE_STATIC_LOCAL(DefaultInterfaceProvider, provider, ());
- return &provider;
-}
-
ThreadSafeBrowserInterfaceBrokerProxy* Platform::GetBrowserInterfaceBroker() {
DEFINE_STATIC_LOCAL(DefaultBrowserInterfaceBrokerProxy, proxy, ());
return &proxy;
diff --git a/chromium/third_party/blink/renderer/platform/exported/url_conversion.cc b/chromium/third_party/blink/renderer/platform/exported/url_conversion.cc
index 5980f067a4a..4b149343d90 100644
--- a/chromium/third_party/blink/renderer/platform/exported/url_conversion.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/url_conversion.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "url/gurl.h"
@@ -27,15 +26,4 @@ GURL WebStringToGURL(const WebString& web_string) {
return GURL(base::StringPiece16(str.Characters16(), str.length()));
}
-mojo::ScopedMessagePipeHandle DataURLToMessagePipeHandle(
- const WebString& data_url) {
- auto blob_data = std::make_unique<blink::BlobData>();
- blob_data->AppendBytes(data_url.Utf8().data(), data_url.length());
- scoped_refptr<blink::BlobDataHandle> blob_data_handle =
- blink::BlobDataHandle::Create(std::move(blob_data), data_url.length());
- mojo::PendingRemote<mojom::blink::Blob> data_url_blob =
- blob_data_handle->CloneBlobRemote();
- return data_url_blob.PassPipe();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc b/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
index 3c104d77bf2..ecaddbf977b 100644
--- a/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
+#include "base/test/gmock_callback_support.h"
#include "base/test/task_environment.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/mojom/video_capture.mojom-blink.h"
@@ -21,6 +22,7 @@
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+using base::test::RunOnceClosure;
using media::BindToCurrentLoop;
using ::testing::_;
using ::testing::DoAll;
@@ -29,10 +31,6 @@ using ::testing::SaveArg;
namespace blink {
-ACTION_P(RunClosure, closure) {
- closure.Run();
-}
-
namespace {
// Callback interface to be implemented by VideoCaptureImplManagerTest.
@@ -166,7 +164,7 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
.RetiresOnSaturation();
}
EXPECT_CALL(*this, OnStarted(_))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
std::array<base::OnceClosure, kNumClients> stop_callbacks;
media::VideoCaptureParams params;
@@ -189,7 +187,7 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
.Times(kNumClients - 1)
.RetiresOnSaturation();
EXPECT_CALL(*this, OnStopped(_))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
for (auto& stop_callback : *stop_callbacks)
std::move(stop_callback).Run();
@@ -281,7 +279,7 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*this, OnPaused(session_ids_[2]))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
manager_->SuspendDevices(video_devices, true);
run_loop.Run();
@@ -299,7 +297,7 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*this, OnResumed(session_ids_[2]))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
manager_->SuspendDevices(video_devices, false);
run_loop.Run();
@@ -312,7 +310,7 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
base::RepeatingClosure quit_closure =
BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*this, OnPaused(session_ids_[0]))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
manager_->Suspend(session_ids_[0]);
run_loop.Run();
@@ -328,7 +326,7 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*this, OnPaused(session_ids_[2]))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
manager_->SuspendDevices(video_devices, true);
run_loop.Run();
@@ -353,7 +351,7 @@ TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*this, OnResumed(session_ids_[2]))
- .WillOnce(RunClosure(std::move(quit_closure)))
+ .WillOnce(RunOnceClosure(std::move(quit_closure)))
.RetiresOnSaturation();
manager_->SuspendDevices(video_devices, false);
run_loop.Run();
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc b/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc
index b6d911afba9..28d5befee6e 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc
@@ -23,7 +23,6 @@ WebBlobInfo::WebBlobInfo(const WebString& uuid,
mojom::blink::Blob::Version_))) {}
WebBlobInfo::WebBlobInfo(const WebString& uuid,
- const WebString& file_path,
const WebString& file_name,
const WebString& type,
const base::Optional<base::Time>& last_modified,
@@ -36,7 +35,6 @@ WebBlobInfo::WebBlobInfo(const WebString& uuid,
mojo::PendingRemote<mojom::blink::Blob>(
std::move(handle),
mojom::blink::Blob::Version_)),
- file_path,
file_name,
last_modified) {}
@@ -49,10 +47,9 @@ WebBlobInfo WebBlobInfo::BlobForTesting(const WebString& uuid,
// static
WebBlobInfo WebBlobInfo::FileForTesting(const WebString& uuid,
- const WebString& file_path,
const WebString& file_name,
const WebString& type) {
- return WebBlobInfo(uuid, file_path, file_name, type, base::nullopt,
+ return WebBlobInfo(uuid, file_name, type, base::nullopt,
std::numeric_limits<uint64_t>::max(),
mojo::MessagePipe().handle0);
}
@@ -77,11 +74,9 @@ WebBlobInfo::WebBlobInfo(scoped_refptr<BlobDataHandle> handle)
: WebBlobInfo(handle, handle->GetType(), handle->size()) {}
WebBlobInfo::WebBlobInfo(scoped_refptr<BlobDataHandle> handle,
- const WebString& file_path,
const WebString& file_name,
const base::Optional<base::Time>& last_modified)
: WebBlobInfo(handle,
- file_path,
file_name,
handle->GetType(),
last_modified,
@@ -97,7 +92,6 @@ WebBlobInfo::WebBlobInfo(scoped_refptr<BlobDataHandle> handle,
blob_handle_(std::move(handle)) {}
WebBlobInfo::WebBlobInfo(scoped_refptr<BlobDataHandle> handle,
- const WebString& file_path,
const WebString& file_name,
const WebString& type,
const base::Optional<base::Time>& last_modified,
@@ -107,7 +101,6 @@ WebBlobInfo::WebBlobInfo(scoped_refptr<BlobDataHandle> handle,
type_(type),
size_(size),
blob_handle_(std::move(handle)),
- file_path_(file_path),
file_name_(file_name),
last_modified_(last_modified) {}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
index 807a31c6a34..21edc5fe307 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
@@ -4,54 +4,14 @@
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
-#include "third_party/blink/public/platform/web_gesture_event.h"
-#include "third_party/blink/public/platform/web_keyboard_event.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-#include "third_party/blink/public/platform/web_pointer_event.h"
-#include "third_party/blink/public/platform/web_touch_event.h"
+#include "third_party/blink/public/common/input/web_gesture_event.h"
+#include "third_party/blink/public/common/input/web_keyboard_event.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
+#include "third_party/blink/public/common/input/web_pointer_event.h"
+#include "third_party/blink/public/common/input/web_touch_event.h"
namespace blink {
-namespace {
-
-struct WebInputEventDelete {
- template <class EventType>
- bool Execute(WebInputEvent* event) const {
- if (!event)
- return false;
- DCHECK_EQ(sizeof(EventType), event->size());
- delete static_cast<EventType*>(event);
- return true;
- }
-};
-
-template <typename Operator, typename ArgIn>
-bool Apply(Operator op, WebInputEvent::Type type, const ArgIn& arg_in) {
- if (WebInputEvent::IsMouseEventType(type))
- return op.template Execute<WebMouseEvent>(arg_in);
- if (type == WebInputEvent::kMouseWheel)
- return op.template Execute<WebMouseWheelEvent>(arg_in);
- if (WebInputEvent::IsKeyboardEventType(type))
- return op.template Execute<WebKeyboardEvent>(arg_in);
- if (WebInputEvent::IsTouchEventType(type))
- return op.template Execute<WebTouchEvent>(arg_in);
- if (WebInputEvent::IsGestureEventType(type))
- return op.template Execute<WebGestureEvent>(arg_in);
- if (WebInputEvent::IsPointerEventType(type))
- return op.template Execute<WebPointerEvent>(arg_in);
-
- NOTREACHED() << "Unknown webkit event type " << type;
- return false;
-}
-}
-
-void WebCoalescedInputEvent::WebInputEventDeleter::operator()(
- WebInputEvent* event) const {
- if (!event)
- return;
- Apply(WebInputEventDelete(), event->GetType(), event);
-}
-
WebInputEvent* WebCoalescedInputEvent::EventPointer() {
return event_.get();
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc b/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
index 67b793f5ca1..1628116da5b 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
@@ -286,6 +286,40 @@ constexpr WebCryptoAlgorithmInfo kAlgorithmIdToInfo[] = {
WebCryptoAlgorithmInfo::kUndefined, // WrapKey
WebCryptoAlgorithmInfo::kUndefined // UnwrapKey
}},
+ {// Index 16
+ // TODO(crbug.com/1032821): Ed25519 is experimental behind a flag. See
+ // https://chromestatus.com/feature/4913922408710144 for the status.
+ "ED25519",
+ {
+ WebCryptoAlgorithmInfo::kUndefined, // Encrypt
+ WebCryptoAlgorithmInfo::kUndefined, // Decrypt
+ kWebCryptoAlgorithmParamsTypeEd25519Params, // Sign
+ kWebCryptoAlgorithmParamsTypeEd25519Params, // Verify
+ WebCryptoAlgorithmInfo::kUndefined, // Digest
+ kWebCryptoAlgorithmParamsTypeNone, // GenerateKey
+ kWebCryptoAlgorithmParamsTypeNone, // ImportKey
+ WebCryptoAlgorithmInfo::kUndefined, // GetKeyLength
+ WebCryptoAlgorithmInfo::kUndefined, // DeriveBits
+ WebCryptoAlgorithmInfo::kUndefined, // WrapKey
+ WebCryptoAlgorithmInfo::kUndefined // UnwrapKey
+ }},
+ {// Index 17
+ // TODO(crbug.com/1032821): X25519 is experimental behind a flag. See
+ // https://chromestatus.com/feature/4913922408710144 for the status.
+ "X25519",
+ {
+ WebCryptoAlgorithmInfo::kUndefined, // Encrypt
+ WebCryptoAlgorithmInfo::kUndefined, // Decrypt
+ WebCryptoAlgorithmInfo::kUndefined, // Sign
+ WebCryptoAlgorithmInfo::kUndefined, // Verify
+ WebCryptoAlgorithmInfo::kUndefined, // Digest
+ kWebCryptoAlgorithmParamsTypeNone, // GenerateKey
+ kWebCryptoAlgorithmParamsTypeNone, // ImportKey
+ WebCryptoAlgorithmInfo::kUndefined, // GetKeyLength
+ kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams, // DeriveBits
+ WebCryptoAlgorithmInfo::kUndefined, // WrapKey
+ WebCryptoAlgorithmInfo::kUndefined // UnwrapKey
+ }},
};
// Initializing the algorithmIdToInfo table above depends on knowing the enum
@@ -308,7 +342,9 @@ static_assert(kWebCryptoAlgorithmIdEcdsa == 12, "ECDSA id must match");
static_assert(kWebCryptoAlgorithmIdEcdh == 13, "ECDH id must match");
static_assert(kWebCryptoAlgorithmIdHkdf == 14, "HKDF id must match");
static_assert(kWebCryptoAlgorithmIdPbkdf2 == 15, "Pbkdf2 id must match");
-static_assert(kWebCryptoAlgorithmIdLast == 15, "last id must match");
+static_assert(kWebCryptoAlgorithmIdEd25519 == 16, "X25519 id must match");
+static_assert(kWebCryptoAlgorithmIdX25519 == 17, "Ed25519 id must match");
+static_assert(kWebCryptoAlgorithmIdLast == 17, "last id must match");
static_assert(10 == kWebCryptoOperationLast,
"the parameter mapping needs to be updated");
@@ -489,6 +525,21 @@ const WebCryptoPbkdf2Params* WebCryptoAlgorithm::Pbkdf2Params() const {
return nullptr;
}
+const WebCryptoEd25519Params* WebCryptoAlgorithm::Ed25519Params() const {
+ DCHECK(!IsNull());
+ if (ParamsType() == kWebCryptoAlgorithmParamsTypeEd25519Params)
+ return static_cast<WebCryptoEd25519Params*>(private_->params.get());
+ return nullptr;
+}
+
+const WebCryptoX25519KeyDeriveParams*
+WebCryptoAlgorithm::X25519KeyDeriveParams() const {
+ DCHECK(!IsNull());
+ if (ParamsType() == kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams)
+ return static_cast<WebCryptoX25519KeyDeriveParams*>(private_->params.get());
+ return nullptr;
+}
+
bool WebCryptoAlgorithm::IsHash(WebCryptoAlgorithmId id) {
switch (id) {
case kWebCryptoAlgorithmIdSha1:
@@ -508,6 +559,8 @@ bool WebCryptoAlgorithm::IsHash(WebCryptoAlgorithmId id) {
case kWebCryptoAlgorithmIdEcdh:
case kWebCryptoAlgorithmIdHkdf:
case kWebCryptoAlgorithmIdPbkdf2:
+ case kWebCryptoAlgorithmIdEd25519:
+ case kWebCryptoAlgorithmIdX25519:
break;
}
return false;
@@ -532,6 +585,8 @@ bool WebCryptoAlgorithm::IsKdf(WebCryptoAlgorithmId id) {
case kWebCryptoAlgorithmIdRsaPss:
case kWebCryptoAlgorithmIdEcdsa:
case kWebCryptoAlgorithmIdEcdh:
+ case kWebCryptoAlgorithmIdEd25519:
+ case kWebCryptoAlgorithmIdX25519:
break;
}
return false;
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc b/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc
deleted file mode 100644
index c26adc1f2f1..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_cursor_info.h"
-
-#include "third_party/blink/renderer/platform/cursor.h"
-
-namespace blink {
-
-static SkBitmap GetCursorBitmap(const Cursor& cursor) {
- if (!cursor.GetImage())
- return {};
- return cursor.GetImage()->AsSkBitmapForCurrentFrame(
- kDoNotRespectImageOrientation);
-}
-
-WebCursorInfo::WebCursorInfo(const Cursor& cursor)
- : type(static_cast<ui::CursorType>(cursor.GetType())),
- hot_spot(cursor.HotSpot()),
- image_scale_factor(cursor.ImageScaleFactor()),
- custom_image(GetCursorBitmap(cursor)) {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_failing_url_loader_factory.cc b/chromium/third_party/blink/renderer/platform/exported/web_failing_url_loader_factory.cc
new file mode 100644
index 00000000000..e1633daf19b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/web_failing_url_loader_factory.cc
@@ -0,0 +1,88 @@
+// 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 "third_party/blink/public/platform/web_failing_url_loader_factory.h"
+
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/platform/web_url_loader_client.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+namespace {
+
+// A WebURLLoader which always fails loading.
+class FailingLoader final : public WebURLLoader {
+ public:
+ explicit FailingLoader(
+ std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+ task_runner_handle)
+ : task_runner_handle_(std::move(task_runner_handle)) {}
+ ~FailingLoader() override = default;
+
+ // WebURLLoader implementation:
+ void LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient*,
+ WebURLResponse&,
+ base::Optional<WebURLError>& error,
+ WebData&,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ WebBlobInfo& downloaded_blob) override {
+ error = ResourceError::Failure(KURL(request->url));
+ }
+ void LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool no_mime_sniffing,
+ WebURLLoaderClient* client) override {
+ GetTaskRunner()->PostTask(
+ FROM_HERE, WTF::Bind(&FailingLoader::Fail, weak_factory_.GetWeakPtr(),
+ KURL(request->url), WTF::Unretained(client)));
+ }
+ void SetDefersLoading(bool) override {}
+ void DidChangePriority(WebURLRequest::Priority, int) override {}
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
+ return task_runner_handle_->GetTaskRunner();
+ }
+
+ private:
+ void Fail(const KURL& url, WebURLLoaderClient* client) {
+ client->DidFail(ResourceError::Failure(url), 0, 0, 0);
+ }
+
+ const std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+ task_runner_handle_;
+
+ // This must be the last member.
+ base::WeakPtrFactory<FailingLoader> weak_factory_{this};
+};
+
+} // namespace
+
+std::unique_ptr<WebURLLoader> WebFailingURLLoaderFactory::CreateURLLoader(
+ const WebURLRequest&,
+ std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle> handle) {
+ return std::make_unique<FailingLoader>(std::move(handle));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_font.cc b/chromium/third_party/blink/renderer/platform/exported/web_font.cc
index 96ad579b538..f8fee0c8b30 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_font.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_font.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/public/platform/web_font.h"
-#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_font_description.h"
#include "third_party/blink/public/platform/web_rect.h"
@@ -30,7 +29,6 @@ class WebFont::Impl final {
public:
explicit Impl(const WebFontDescription& description) : font_(description) {
- font_.Update(nullptr);
}
const Font& GetFont() const { return font_; }
@@ -82,7 +80,7 @@ float WebFont::XHeight() const {
void WebFont::DrawText(cc::PaintCanvas* canvas,
const WebTextRun& run,
- const WebFloatPoint& left_baseline,
+ const gfx::PointF& left_baseline,
SkColor color) const {
FontCachePurgePreventer font_cache_purge_preventer;
TextRun text_run(run);
@@ -95,7 +93,7 @@ void WebFont::DrawText(cc::PaintCanvas* canvas,
DrawingRecorder recorder(context, builder, DisplayItem::kWebFont);
context.Save();
context.SetFillColor(color);
- context.DrawText(private_->GetFont(), run_info, left_baseline,
+ context.DrawText(private_->GetFont(), run_info, FloatPoint(left_baseline),
kInvalidDOMNodeId);
context.Restore();
}
@@ -113,12 +111,12 @@ int WebFont::OffsetForPosition(const WebTextRun& run, float position) const {
}
WebFloatRect WebFont::SelectionRectForText(const WebTextRun& run,
- const WebFloatPoint& left_baseline,
+ const gfx::PointF& left_baseline,
int height,
int from,
int to) const {
- return private_->GetFont().SelectionRectForText(run, left_baseline, height,
- from, to);
+ return private_->GetFont().SelectionRectForText(
+ run, FloatPoint(left_baseline), height, from, to);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_gesture_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_gesture_event.cc
deleted file mode 100644
index 406e279d2c5..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_gesture_event.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_gesture_event.h"
-
-namespace blink {
-
-float WebGestureEvent::DeltaXInRootFrame() const {
- if (type_ == WebInputEvent::kGestureScrollBegin)
- return data.scroll_begin.delta_x_hint / frame_scale_;
- DCHECK(type_ == WebInputEvent::kGestureScrollUpdate);
- return data.scroll_update.delta_x / frame_scale_;
-}
-
-float WebGestureEvent::DeltaYInRootFrame() const {
- if (type_ == WebInputEvent::kGestureScrollBegin)
- return data.scroll_begin.delta_y_hint / frame_scale_;
- DCHECK(type_ == WebInputEvent::kGestureScrollUpdate);
- return data.scroll_update.delta_y / frame_scale_;
-}
-
-ui::input_types::ScrollGranularity WebGestureEvent::DeltaUnits() const {
- if (type_ == WebInputEvent::kGestureScrollBegin)
- return data.scroll_begin.delta_hint_units;
- if (type_ == WebInputEvent::kGestureScrollUpdate)
- return data.scroll_update.delta_units;
- DCHECK(type_ == WebInputEvent::kGestureScrollEnd);
- return data.scroll_end.delta_units;
-}
-
-WebGestureEvent::InertialPhaseState WebGestureEvent::InertialPhase() const {
- if (type_ == WebInputEvent::kGestureScrollBegin)
- return data.scroll_begin.inertial_phase;
- if (type_ == WebInputEvent::kGestureScrollUpdate)
- return data.scroll_update.inertial_phase;
- DCHECK(type_ == WebInputEvent::kGestureScrollEnd);
- return data.scroll_end.inertial_phase;
-}
-
-bool WebGestureEvent::Synthetic() const {
- if (type_ == WebInputEvent::kGestureScrollBegin)
- return data.scroll_begin.synthetic;
- DCHECK(type_ == WebInputEvent::kGestureScrollEnd);
- return data.scroll_end.synthetic;
-}
-
-float WebGestureEvent::VelocityX() const {
- if (type_ == WebInputEvent::kGestureScrollUpdate)
- return data.scroll_update.velocity_x;
- DCHECK(type_ == WebInputEvent::kGestureFlingStart);
- return data.fling_start.velocity_x;
-}
-
-float WebGestureEvent::VelocityY() const {
- if (type_ == WebInputEvent::kGestureScrollUpdate)
- return data.scroll_update.velocity_y;
- DCHECK(type_ == WebInputEvent::kGestureFlingStart);
- return data.fling_start.velocity_y;
-}
-
-WebFloatSize WebGestureEvent::TapAreaInRootFrame() const {
- if (type_ == WebInputEvent::kGestureTwoFingerTap) {
- return WebFloatSize(data.two_finger_tap.first_finger_width / frame_scale_,
- data.two_finger_tap.first_finger_height / frame_scale_);
- } else if (type_ == WebInputEvent::kGestureLongPress ||
- type_ == WebInputEvent::kGestureLongTap) {
- return WebFloatSize(data.long_press.width / frame_scale_,
- data.long_press.height / frame_scale_);
- } else if (type_ == WebInputEvent::kGestureTap ||
- type_ == WebInputEvent::kGestureTapUnconfirmed ||
- type_ == WebInputEvent::kGestureDoubleTap) {
- return WebFloatSize(data.tap.width / frame_scale_,
- data.tap.height / frame_scale_);
- } else if (type_ == WebInputEvent::kGestureTapDown) {
- return WebFloatSize(data.tap_down.width / frame_scale_,
- data.tap_down.height / frame_scale_);
- } else if (type_ == WebInputEvent::kGestureShowPress) {
- return WebFloatSize(data.show_press.width / frame_scale_,
- data.show_press.height / frame_scale_);
- }
- // This function is called for all gestures and determined if the tap
- // area is empty or not; so return an empty rect here.
- return WebFloatSize();
-}
-
-WebFloatPoint WebGestureEvent::PositionInRootFrame() const {
- return WebFloatPoint(
- (position_in_widget_.x / frame_scale_) + frame_translate_.x,
- (position_in_widget_.y / frame_scale_) + frame_translate_.y);
-}
-
-int WebGestureEvent::TapCount() const {
- DCHECK(type_ == WebInputEvent::kGestureTap);
- return data.tap.tap_count;
-}
-
-void WebGestureEvent::ApplyTouchAdjustment(WebFloatPoint root_frame_coords) {
- // Update the window-relative position of the event so that the node that
- // was ultimately hit is under this point (i.e. elementFromPoint for the
- // client co-ordinates in a 'click' event should yield the target). The
- // global position is intentionally left unmodified because it's intended to
- // reflect raw co-ordinates unrelated to any content.
- frame_translate_.x =
- root_frame_coords.x - (position_in_widget_.x / frame_scale_);
- frame_translate_.y =
- root_frame_coords.y - (position_in_widget_.y / frame_scale_);
-}
-
-void WebGestureEvent::FlattenTransform() {
- if (frame_scale_ != 1) {
- switch (type_) {
- case WebInputEvent::kGestureScrollBegin:
- data.scroll_begin.delta_x_hint /= frame_scale_;
- data.scroll_begin.delta_y_hint /= frame_scale_;
- break;
- case WebInputEvent::kGestureScrollUpdate:
- data.scroll_update.delta_x /= frame_scale_;
- data.scroll_update.delta_y /= frame_scale_;
- break;
- case WebInputEvent::kGestureTwoFingerTap:
- data.two_finger_tap.first_finger_width /= frame_scale_;
- data.two_finger_tap.first_finger_height /= frame_scale_;
- break;
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap:
- data.long_press.width /= frame_scale_;
- data.long_press.height /= frame_scale_;
- break;
- case WebInputEvent::kGestureTap:
- case WebInputEvent::kGestureTapUnconfirmed:
- case WebInputEvent::kGestureDoubleTap:
- data.tap.width /= frame_scale_;
- data.tap.height /= frame_scale_;
- break;
- case WebInputEvent::kGestureTapDown:
- data.tap_down.width /= frame_scale_;
- data.tap_down.height /= frame_scale_;
- break;
- case WebInputEvent::kGestureShowPress:
- data.show_press.width /= frame_scale_;
- data.show_press.height /= frame_scale_;
- break;
- default:
- break;
- }
- }
-
- SetPositionInWidget(PositionInRootFrame());
- frame_translate_.x = 0;
- frame_translate_.y = 0;
- frame_scale_ = 1;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc b/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc
index f60fa03f4c9..83c1f68f7d3 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_http_body.cc
@@ -121,11 +121,6 @@ void WebHTTPBody::AppendData(const WebData& data) {
});
}
-void WebHTTPBody::AppendFile(const WebString& file_path) {
- EnsureMutable();
- private_->AppendFile(file_path);
-}
-
void WebHTTPBody::AppendFileRange(
const WebString& file_path,
int64_t file_start,
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc b/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc
index 9d1960e18cf..ec882242c25 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc
@@ -50,10 +50,10 @@ static inline int PartialStringToInt(const String& string,
} // namespace
-WebVector<WebSize> WebIconSizesParser::ParseIconSizes(
+WebVector<gfx::Size> WebIconSizesParser::ParseIconSizes(
const WebString& web_sizes_string) {
String sizes_string = web_sizes_string;
- Vector<WebSize> icon_sizes;
+ Vector<gfx::Size> icon_sizes;
if (sizes_string.IsEmpty())
return icon_sizes;
@@ -67,7 +67,7 @@ WebVector<WebSize> WebIconSizesParser::ParseIconSizes(
// See if the current size is "any".
if (sizes_string.Substring(i, 3).StartsWithIgnoringCase("any") &&
(i + 3 == length || IsWhitespace(sizes_string[i + 3]))) {
- icon_sizes.push_back(WebSize(0, 0));
+ icon_sizes.push_back(gfx::Size());
i = i + 3;
continue;
}
@@ -100,8 +100,8 @@ WebVector<WebSize> WebIconSizesParser::ParseIconSizes(
// Append the parsed size to iconSizes.
icon_sizes.push_back(
- WebSize(PartialStringToInt(sizes_string, width_start, width_end),
- PartialStringToInt(sizes_string, height_start, height_end)));
+ gfx::Size(PartialStringToInt(sizes_string, width_start, width_end),
+ PartialStringToInt(sizes_string, height_start, height_end)));
}
return icon_sizes;
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser_test.cc
index 53959c6c10e..d35d2f3431b 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser_test.cc
@@ -5,9 +5,9 @@
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "ui/gfx/geometry/size.h"
namespace blink {
@@ -15,17 +15,17 @@ class WebIconSizesParserTest : public testing::Test {};
TEST(WebIconSizesParserTest, parseSizes) {
WebString sizes_attribute = "32x33";
- WebVector<WebSize> sizes;
+ WebVector<gfx::Size> sizes;
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
sizes_attribute = " 10x11 ";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1u, sizes.size());
- EXPECT_EQ(10, sizes[0].width);
- EXPECT_EQ(11, sizes[0].height);
+ EXPECT_EQ(10, sizes[0].width());
+ EXPECT_EQ(11, sizes[0].height());
sizes_attribute = "0x33";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
@@ -35,18 +35,18 @@ TEST(WebIconSizesParserTest, parseSizes) {
sizes_attribute = AtomicString(attribute);
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
sizes_attribute = " 32x33 16X17 128x129 ";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(3U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
- EXPECT_EQ(16, sizes[1].width);
- EXPECT_EQ(17, sizes[1].height);
- EXPECT_EQ(128, sizes[2].width);
- EXPECT_EQ(129, sizes[2].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
+ EXPECT_EQ(16, sizes[1].width());
+ EXPECT_EQ(17, sizes[1].height());
+ EXPECT_EQ(128, sizes[2].width());
+ EXPECT_EQ(129, sizes[2].height());
sizes_attribute = " \n 32x33 \r 16X17 \t 128x129 \f ";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
@@ -55,8 +55,8 @@ TEST(WebIconSizesParserTest, parseSizes) {
sizes_attribute = "any";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(0, sizes[0].width);
- EXPECT_EQ(0, sizes[0].height);
+ EXPECT_EQ(0, sizes[0].width());
+ EXPECT_EQ(0, sizes[0].height());
sizes_attribute = "ANY";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
@@ -69,22 +69,22 @@ TEST(WebIconSizesParserTest, parseSizes) {
sizes_attribute = " any";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(0, sizes[0].width);
- EXPECT_EQ(0, sizes[0].height);
+ EXPECT_EQ(0, sizes[0].width());
+ EXPECT_EQ(0, sizes[0].height());
sizes_attribute = " any ";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(0, sizes[0].width);
- EXPECT_EQ(0, sizes[0].height);
+ EXPECT_EQ(0, sizes[0].width());
+ EXPECT_EQ(0, sizes[0].height());
sizes_attribute = "any 10x10";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(2u, sizes.size());
- EXPECT_EQ(0, sizes[0].width);
- EXPECT_EQ(0, sizes[0].height);
- EXPECT_EQ(10, sizes[1].width);
- EXPECT_EQ(10, sizes[1].height);
+ EXPECT_EQ(0, sizes[0].width());
+ EXPECT_EQ(0, sizes[0].height());
+ EXPECT_EQ(10, sizes[1].width());
+ EXPECT_EQ(10, sizes[1].height());
sizes_attribute = "an";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
@@ -129,34 +129,34 @@ TEST(WebIconSizesParserTest, parseSizes) {
sizes_attribute = "32x33 32";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
sizes_attribute = "32x33 32x";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
sizes_attribute = "32x33 x32";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
sizes_attribute = "32x33 any";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(2U, sizes.size());
- EXPECT_EQ(32, sizes[0].width);
- EXPECT_EQ(33, sizes[0].height);
- EXPECT_EQ(0, sizes[1].width);
- EXPECT_EQ(0, sizes[1].height);
+ EXPECT_EQ(32, sizes[0].width());
+ EXPECT_EQ(33, sizes[0].height());
+ EXPECT_EQ(0, sizes[1].width());
+ EXPECT_EQ(0, sizes[1].height());
sizes_attribute = "32x33, 64x64";
sizes = WebIconSizesParser::ParseIconSizes(sizes_attribute);
ASSERT_EQ(1U, sizes.size());
- EXPECT_EQ(64, sizes[0].width);
- EXPECT_EQ(64, sizes[0].height);
+ EXPECT_EQ(64, sizes[0].width());
+ EXPECT_EQ(64, sizes[0].height());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_input_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_input_event.cc
deleted file mode 100644
index 85661bc1203..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_input_event.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_input_event.h"
-
-#include <ctype.h>
-#include "third_party/blink/public/platform/web_gesture_event.h"
-#include "third_party/blink/public/platform/web_keyboard_event.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-#include "third_party/blink/public/platform/web_touch_event.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
-
-namespace blink {
-
-struct SameSizeAsWebInputEvent {
- int input_data[8];
-};
-
-struct SameSizeAsWebKeyboardEvent : public SameSizeAsWebInputEvent {
- int keyboard_data[9];
-};
-
-struct SameSizeAsWebMouseEvent : public SameSizeAsWebInputEvent {
- int mouse_data[17];
-};
-
-struct SameSizeAsWebMouseWheelEvent : public SameSizeAsWebMouseEvent {
- int mousewheel_data[12];
-};
-
-struct SameSizeAsWebGestureEvent : public SameSizeAsWebInputEvent {
- int gesture_data[14];
-};
-
-struct SameSizeAsWebTouchEvent : public SameSizeAsWebInputEvent {
- WebTouchPoint touch_points[WebTouchEvent::kTouchesLengthCap];
- int touch_data[4];
-};
-
-static_assert(sizeof(WebInputEvent) == sizeof(SameSizeAsWebInputEvent),
- "WebInputEvent should not have gaps");
-static_assert(sizeof(WebKeyboardEvent) == sizeof(SameSizeAsWebKeyboardEvent),
- "WebKeyboardEvent should not have gaps");
-static_assert(sizeof(WebMouseEvent) == sizeof(SameSizeAsWebMouseEvent),
- "WebMouseEvent should not have gaps");
-static_assert(sizeof(WebMouseWheelEvent) ==
- sizeof(SameSizeAsWebMouseWheelEvent),
- "WebMouseWheelEvent should not have gaps");
-static_assert(sizeof(WebGestureEvent) == sizeof(SameSizeAsWebGestureEvent),
- "WebGestureEvent should not have gaps");
-static_assert(sizeof(WebTouchEvent) == sizeof(SameSizeAsWebTouchEvent),
- "WebTouchEvent should not have gaps");
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_isolate.cc b/chromium/third_party/blink/renderer/platform/exported/web_isolate.cc
new file mode 100644
index 00000000000..a61fda7ca44
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/web_isolate.cc
@@ -0,0 +1,13 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/bindings/blink_isolate/blink_isolate.h"
+
+namespace blink {
+
+std::unique_ptr<WebIsolate> WebIsolate::Create() {
+ return std::unique_ptr<WebIsolate>(new BlinkIsolate());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_media_stream_audio_sink.cc b/chromium/third_party/blink/renderer/platform/exported/web_media_stream_audio_sink.cc
index 7276a8bd885..083bc2b1d8f 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_media_stream_audio_sink.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_media_stream_audio_sink.cc
@@ -5,9 +5,9 @@
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h"
#include "base/logging.h"
-#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_media_stream_source.cc b/chromium/third_party/blink/renderer/platform/exported/web_media_stream_source.cc
index 75a6efcc795..27e4fda4194 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_media_stream_source.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_media_stream_source.cc
@@ -34,12 +34,12 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/platform/web_audio_destination_consumer.h"
-#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
+#include "third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -182,7 +182,7 @@ void ConsumerWrapper::ConsumeAudio(AudioBus* bus, size_t number_of_frames) {
// Wrap AudioBus.
size_t number_of_channels = bus->NumberOfChannels();
- WebVector<const float*> bus_vector(number_of_channels);
+ Vector<const float*> bus_vector(number_of_channels);
for (size_t i = 0; i < number_of_channels; ++i)
bus_vector[i] = bus->Channel(i)->Data();
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_media_stream_track.cc b/chromium/third_party/blink/renderer/platform/exported/web_media_stream_track.cc
index 4e51ff18abc..340b06a12a9 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_media_stream_track.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_media_stream_track.cc
@@ -29,11 +29,11 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/public/platform/web_audio_source_provider.h"
-#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
@@ -84,13 +84,12 @@ WebMediaStreamTrack::ContentHintType WebMediaStreamTrack::ContentHint() const {
return private_->ContentHint();
}
-WebMediaConstraints WebMediaStreamTrack::Constraints() const {
+MediaConstraints WebMediaStreamTrack::Constraints() const {
DCHECK(!private_.IsNull());
return private_->Constraints();
}
-void WebMediaStreamTrack::SetConstraints(
- const WebMediaConstraints& constraints) {
+void WebMediaStreamTrack::SetConstraints(const MediaConstraints& constraints) {
DCHECK(!private_.IsNull());
return private_->SetConstraints(constraints);
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_mouse_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_mouse_event.cc
deleted file mode 100644
index ff5338a2fd4..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_mouse_event.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_mouse_event.h"
-
-#include "third_party/blink/public/platform/web_gesture_event.h"
-
-namespace blink {
-
-WebMouseEvent::WebMouseEvent(WebInputEvent::Type type,
- const WebGestureEvent& gesture_event,
- Button button_param,
- int click_count_param,
- int modifiers,
- base::TimeTicks time_stamp,
- PointerId id_param)
- : WebInputEvent(sizeof(WebMouseEvent), type, modifiers, time_stamp),
- WebPointerProperties(id_param,
- WebPointerProperties::PointerType::kMouse,
- button_param),
- click_count(click_count_param) {
- DCHECK_GE(type, kMouseTypeFirst);
- DCHECK_LE(type, kMouseTypeLast);
- SetPositionInWidget(gesture_event.PositionInWidget());
- SetPositionInScreen(gesture_event.PositionInScreen());
- SetFrameScale(gesture_event.FrameScale());
- SetFrameTranslate(gesture_event.FrameTranslate());
- SetMenuSourceType(gesture_event.GetType());
-}
-
-WebFloatPoint WebMouseEvent::PositionInRootFrame() const {
- return WebFloatPoint(
- (position_in_widget_.x / frame_scale_) + frame_translate_.x,
- (position_in_widget_.y / frame_scale_) + frame_translate_.y);
-}
-
-WebMouseEvent WebMouseEvent::FlattenTransform() const {
- WebMouseEvent result = *this;
- result.FlattenTransformSelf();
- return result;
-}
-
-void WebMouseEvent::FlattenTransformSelf() {
- position_in_widget_ = PositionInRootFrame();
- frame_translate_.x = 0;
- frame_translate_.y = 0;
- frame_scale_ = 1;
-}
-
-void WebMouseEvent::SetMenuSourceType(WebInputEvent::Type type) {
- switch (type) {
- case kGestureTapDown:
- case kGestureTap:
- case kGestureDoubleTap:
- menu_source_type = kMenuSourceTouch;
- break;
- case kGestureLongPress:
- menu_source_type = kMenuSourceLongPress;
- break;
- case kGestureLongTap:
- menu_source_type = kMenuSourceLongTap;
- break;
- default:
- menu_source_type = kMenuSourceNone;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_mouse_wheel_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_mouse_wheel_event.cc
deleted file mode 100644
index cc02b1e4947..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_mouse_wheel_event.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-
-namespace blink {
-
-float WebMouseWheelEvent::DeltaXInRootFrame() const {
- return delta_x / frame_scale_;
-}
-
-float WebMouseWheelEvent::DeltaYInRootFrame() const {
- return delta_y / frame_scale_;
-}
-
-WebMouseWheelEvent WebMouseWheelEvent::FlattenTransform() const {
- WebMouseWheelEvent result = *this;
- result.delta_x /= result.frame_scale_;
- result.delta_y /= result.frame_scale_;
- result.FlattenTransformSelf();
- return result;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_pointer_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_pointer_event.cc
deleted file mode 100644
index 8c710c12480..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_pointer_event.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_pointer_event.h"
-
-#include "third_party/blink/public/platform/web_float_point.h"
-
-namespace blink {
-
-namespace {
-
-WebInputEvent::Type PointerEventTypeForTouchPointState(
- WebTouchPoint::State state) {
- switch (state) {
- case WebTouchPoint::kStateReleased:
- return WebInputEvent::Type::kPointerUp;
- case WebTouchPoint::kStateCancelled:
- return WebInputEvent::Type::kPointerCancel;
- case WebTouchPoint::kStatePressed:
- return WebInputEvent::Type::kPointerDown;
- case WebTouchPoint::kStateMoved:
- return WebInputEvent::Type::kPointerMove;
- case WebTouchPoint::kStateStationary:
- default:
- NOTREACHED();
- return WebInputEvent::Type::kUndefined;
- }
-}
-
-} // namespace
-
-WebPointerEvent::WebPointerEvent(const WebTouchEvent& touch_event,
- const WebTouchPoint& touch_point)
- : WebInputEvent(sizeof(WebPointerEvent),
- PointerEventTypeForTouchPointState(touch_point.state),
- touch_event.GetModifiers(),
- touch_event.TimeStamp()),
-
- WebPointerProperties(touch_point),
- hovering(touch_event.hovering),
- width(touch_point.radius_x * 2.f),
- height(touch_point.radius_y * 2.f) {
- // WebInutEvent attributes
- SetFrameScale(touch_event.FrameScale());
- SetFrameTranslate(touch_event.FrameTranslate());
- // WebTouchEvent attributes
- dispatch_type = touch_event.dispatch_type;
- moved_beyond_slop_region = touch_event.moved_beyond_slop_region;
- touch_start_or_first_touch_move = touch_event.touch_start_or_first_touch_move;
- unique_touch_event_id = touch_event.unique_touch_event_id;
- // WebTouchPoint attributes
- rotation_angle = touch_point.rotation_angle;
- // TODO(crbug.com/816504): Touch point button is not set at this point yet.
- button = (GetType() == WebInputEvent::kPointerDown ||
- GetType() == WebInputEvent::kPointerUp)
- ? WebPointerProperties::Button::kLeft
- : WebPointerProperties::Button::kNoButton;
-}
-
-WebPointerEvent::WebPointerEvent(WebInputEvent::Type type,
- const WebMouseEvent& mouse_event)
- : WebInputEvent(sizeof(WebPointerEvent),
- type,
- mouse_event.GetModifiers(),
- mouse_event.TimeStamp()),
- WebPointerProperties(mouse_event),
- hovering(true),
- width(std::numeric_limits<float>::quiet_NaN()),
- height(std::numeric_limits<float>::quiet_NaN()) {
- DCHECK_GE(type, WebInputEvent::kPointerTypeFirst);
- DCHECK_LE(type, WebInputEvent::kPointerTypeLast);
- SetFrameScale(mouse_event.FrameScale());
- SetFrameTranslate(mouse_event.FrameTranslate());
-}
-
-WebPointerEvent WebPointerEvent::CreatePointerCausesUaActionEvent(
- WebPointerProperties::PointerType type,
- base::TimeTicks time_stamp) {
- WebPointerEvent event;
- event.pointer_type = type;
- event.SetTimeStamp(time_stamp);
- event.SetType(WebInputEvent::Type::kPointerCausedUaAction);
- return event;
-}
-
-WebPointerEvent WebPointerEvent::WebPointerEventInRootFrame() const {
- WebPointerEvent transformed_event = *this;
- if (HasWidth())
- transformed_event.width /= frame_scale_;
- if (HasHeight())
- transformed_event.height /= frame_scale_;
- transformed_event.position_in_widget_ =
- WebFloatPoint((transformed_event.PositionInWidget().x / frame_scale_) +
- frame_translate_.x,
- (transformed_event.PositionInWidget().y / frame_scale_) +
- frame_translate_.y);
- return transformed_event;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_prerender.cc b/chromium/third_party/blink/renderer/platform/exported/web_prerender.cc
deleted file mode 100644
index 36f7daee909..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_prerender.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_prerender.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/prerender.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-
-namespace blink {
-
-namespace {
-
-class PrerenderExtraDataContainer : public Prerender::ExtraData {
- public:
- static scoped_refptr<PrerenderExtraDataContainer> Create(
- WebPrerender::ExtraData* extra_data) {
- return base::AdoptRef(new PrerenderExtraDataContainer(extra_data));
- }
-
- ~PrerenderExtraDataContainer() override = default;
-
- WebPrerender::ExtraData* GetExtraData() const { return extra_data_.get(); }
-
- private:
- explicit PrerenderExtraDataContainer(WebPrerender::ExtraData* extra_data)
- : extra_data_(base::WrapUnique(extra_data)) {}
-
- std::unique_ptr<WebPrerender::ExtraData> extra_data_;
-};
-
-} // namespace
-
-WebPrerender::WebPrerender(Prerender* prerender) : private_(prerender) {}
-
-const Prerender* WebPrerender::ToPrerender() const {
- return private_.Get();
-}
-
-void WebPrerender::Reset() {
- private_.Reset();
-}
-
-void WebPrerender::Assign(const WebPrerender& other) {
- private_ = other.private_;
-}
-
-bool WebPrerender::IsNull() const {
- return private_.IsNull();
-}
-
-WebURL WebPrerender::Url() const {
- return WebURL(private_->Url());
-}
-
-unsigned WebPrerender::RelTypes() const {
- return private_->RelTypes();
-}
-
-WebString WebPrerender::GetReferrer() const {
- return private_->GetReferrer();
-}
-
-url::Origin WebPrerender::SecurityOrigin() const {
- auto* security_origin = private_->GetSecurityOrigin();
- return security_origin ? security_origin->ToUrlOrigin() : url::Origin();
-}
-
-network::mojom::ReferrerPolicy WebPrerender::GetReferrerPolicy() const {
- return private_->GetReferrerPolicy();
-}
-
-void WebPrerender::SetExtraData(WebPrerender::ExtraData* extra_data) {
- private_->SetExtraData(PrerenderExtraDataContainer::Create(extra_data));
-}
-
-const WebPrerender::ExtraData* WebPrerender::GetExtraData() const {
- scoped_refptr<Prerender::ExtraData> webcore_extra_data =
- private_->GetExtraData();
- if (!webcore_extra_data)
- return nullptr;
- return static_cast<PrerenderExtraDataContainer*>(webcore_extra_data.get())
- ->GetExtraData();
-}
-
-void WebPrerender::DidStartPrerender() {
- private_->DidStartPrerender();
-}
-
-void WebPrerender::DidStopPrerender() {
- private_->DidStopPrerender();
-}
-
-void WebPrerender::DidSendLoadForPrerender() {
- private_->DidSendLoadForPrerender();
-}
-
-void WebPrerender::DidSendDOMContentLoadedForPrerender() {
- private_->DidSendDOMContentLoadedForPrerender();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc b/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc
deleted file mode 100644
index edc12ec2d3c..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_prerendering_support.h"
-
-namespace blink {
-
-WebPrerenderingSupport* WebPrerenderingSupport::platform_ = nullptr;
-
-// static
-void WebPrerenderingSupport::Initialize(WebPrerenderingSupport* platform) {
- platform_ = platform;
-}
-
-// static
-void WebPrerenderingSupport::Shutdown() {
- platform_ = nullptr;
-}
-
-// static
-WebPrerenderingSupport* WebPrerenderingSupport::Current() {
- return platform_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc b/chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc
deleted file mode 100644
index ac11337e73a..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_resource_timing_info.h"
-
-#include "third_party/blink/public/platform/web_url_load_timing.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-namespace {
-
-bool IsSameServerTimingInfo(const WebVector<WebServerTimingInfo>& lhs,
- const WebVector<WebServerTimingInfo>& rhs) {
- if (lhs.size() != rhs.size())
- return false;
- for (size_t i = 0; i < lhs.size(); ++i) {
- if (lhs[i] != rhs[i])
- return false;
- }
- return true;
-}
-
-} // namespace
-
-bool WebServerTimingInfo::operator==(const WebServerTimingInfo& other) const {
- return name == other.name && duration == other.duration &&
- description == other.description;
-}
-
-bool WebServerTimingInfo::operator!=(const WebServerTimingInfo& other) const {
- return !(*this == other);
-}
-
-bool WebResourceTimingInfo::operator==(
- const WebResourceTimingInfo& other) const {
- return name == other.name && start_time == other.start_time &&
- alpn_negotiated_protocol == other.alpn_negotiated_protocol &&
- connection_info == other.connection_info && timing == other.timing &&
- last_redirect_end_time == other.last_redirect_end_time &&
- response_end == other.response_end &&
- transfer_size == other.transfer_size &&
- encoded_body_size == other.encoded_body_size &&
- decoded_body_size == other.decoded_body_size &&
- context_type == other.context_type &&
- did_reuse_connection == other.did_reuse_connection &&
- is_secure_context == other.is_secure_context &&
- allow_timing_details == other.allow_timing_details &&
- allow_redirect_details == other.allow_redirect_details &&
- allow_negative_values == other.allow_negative_values &&
- IsSameServerTimingInfo(server_timing, other.server_timing);
-}
-
-} // namespace blink
-
-namespace WTF {
-#if INSIDE_BLINK
-CrossThreadCopier<blink::WebResourceTimingInfo>::Type
-CrossThreadCopier<blink::WebResourceTimingInfo>::Copy(
- const blink::WebResourceTimingInfo& info) {
- blink::WebResourceTimingInfo copy;
-
- copy.name = String(info.name).IsolatedCopy();
- copy.start_time = info.start_time;
-
- copy.alpn_negotiated_protocol =
- String(info.alpn_negotiated_protocol).IsolatedCopy();
- copy.connection_info = String(info.connection_info).IsolatedCopy();
-
- if (!info.timing.IsNull())
- copy.timing = CrossThreadCopier<blink::WebURLLoadTiming>::Copy(info.timing);
-
- copy.last_redirect_end_time = info.last_redirect_end_time;
- copy.response_end = info.response_end;
-
- copy.transfer_size = info.transfer_size;
- copy.encoded_body_size = info.encoded_body_size;
- copy.decoded_body_size = info.decoded_body_size;
- copy.context_type = info.context_type;
-
- copy.did_reuse_connection = info.did_reuse_connection;
- copy.is_secure_context = info.is_secure_context;
-
- copy.allow_timing_details = info.allow_timing_details;
- copy.allow_redirect_details = info.allow_redirect_details;
-
- copy.allow_negative_values = info.allow_negative_values;
- for (auto& entry : info.server_timing) {
- blink::WebServerTimingInfo entry_copy(
- String(entry.name).IsolatedCopy(), entry.duration,
- String(entry.description).IsolatedCopy());
- copy.server_timing.emplace_back(std::move(entry_copy));
- }
-
- return copy;
-}
-#endif
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc
deleted file mode 100644
index 1caab47f81c..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_resource_timing_info.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-
-namespace blink {
-
-namespace {
-
-scoped_refptr<ResourceLoadTiming> CreateResourceLoadTiming(
- const base::TimeTicks pseudo_time) {
- auto timing = ResourceLoadTiming::Create();
- timing->SetRequestTime(pseudo_time);
- timing->SetProxyStart(pseudo_time);
- timing->SetProxyEnd(pseudo_time);
- timing->SetDnsStart(pseudo_time);
- timing->SetDnsEnd(pseudo_time);
- timing->SetConnectStart(pseudo_time);
- timing->SetConnectEnd(pseudo_time);
- timing->SetWorkerStart(pseudo_time);
- timing->SetWorkerReady(pseudo_time);
- timing->SetSendStart(pseudo_time);
- timing->SetSendEnd(pseudo_time);
- timing->SetReceiveHeadersStart(pseudo_time);
- timing->SetReceiveHeadersEnd(pseudo_time);
- timing->SetSslStart(pseudo_time);
- timing->SetSslStart(pseudo_time);
- timing->SetSslEnd(pseudo_time);
- timing->SetPushEnd(pseudo_time);
- return timing;
-}
-
-WebResourceTimingInfo CreateWebResourceTimingInfo(
- const base::TimeTicks pseudo_time) {
- WebVector<WebServerTimingInfo> server_timing;
- server_timing.emplace_back(WebServerTimingInfo("server_timing_name", 1.0,
- "server_timing_description"));
-
- WebResourceTimingInfo info = {
- .name = "name",
- .start_time = pseudo_time,
-
- .alpn_negotiated_protocol = "protocol",
- .connection_info = "info",
-
- .timing = CreateResourceLoadTiming(pseudo_time),
- .last_redirect_end_time = pseudo_time,
- .response_end = pseudo_time,
-
- .transfer_size = 1,
- .encoded_body_size = 2,
- .decoded_body_size = 3,
-
- .did_reuse_connection = true,
- .is_secure_context = true,
-
- .allow_timing_details = true,
- .allow_redirect_details = true,
-
- .allow_negative_values = true,
-
- .server_timing = server_timing,
- };
- return info;
-}
-
-void CheckWebResourceTimingInfoOnThread(const WebResourceTimingInfo& info,
- const base::TimeTicks pseudo_time) {
- WebResourceTimingInfo expected = CreateWebResourceTimingInfo(pseudo_time);
- EXPECT_EQ(expected, info);
-
- EXPECT_EQ("name", info.name);
- EXPECT_EQ(pseudo_time, info.start_time);
-
- EXPECT_EQ("protocol", info.alpn_negotiated_protocol);
- EXPECT_EQ("info", info.connection_info);
-
- WebURLLoadTiming expected_timing(CreateResourceLoadTiming(pseudo_time));
- EXPECT_EQ(expected_timing, info.timing);
- EXPECT_EQ(pseudo_time, info.last_redirect_end_time);
- EXPECT_EQ(pseudo_time, info.response_end);
-
- EXPECT_EQ(1u, info.transfer_size);
- EXPECT_EQ(2u, info.encoded_body_size);
- EXPECT_EQ(3u, info.decoded_body_size);
-
- EXPECT_TRUE(info.did_reuse_connection);
- EXPECT_TRUE(info.is_secure_context);
-
- EXPECT_TRUE(info.allow_timing_details);
- EXPECT_TRUE(info.allow_redirect_details);
-
- EXPECT_TRUE(info.allow_negative_values);
-
- EXPECT_EQ(1u, info.server_timing.size());
-
- auto& entry = info.server_timing[0];
- EXPECT_EQ("server_timing_name", entry.name);
- EXPECT_EQ(1.0, entry.duration);
- EXPECT_EQ("server_timing_description", entry.description);
-}
-
-} // namespace
-
-TEST(WebResourceTimingInfoTest, CrossThreadCopy) {
- ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
- platform;
-
- base::TimeTicks pseudo_time = base::TimeTicks::Now();
- WebResourceTimingInfo info = CreateWebResourceTimingInfo(pseudo_time);
-
- std::unique_ptr<Thread> thread = Platform::Current()->CreateThread(
- ThreadCreationParams(ThreadType::kTestThread)
- .SetThreadNameForTest("TestThread"));
- PostCrossThreadTask(*thread->GetTaskRunner(), FROM_HERE,
- CrossThreadBindOnce(&CheckWebResourceTimingInfoOnThread,
- info, pseudo_time));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_rtc_peer_connection_handler_client.cc b/chromium/third_party/blink/renderer/platform/exported/web_rtc_peer_connection_handler_client.cc
deleted file mode 100644
index 9b3be0525c0..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_rtc_peer_connection_handler_client.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h"
-
-namespace blink {
-
-WebRTCPeerConnectionHandlerClient::~WebRTCPeerConnectionHandlerClient() =
- default;
-
-void WebRTCPeerConnectionHandlerClient::ClosePeerConnection() {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_rtc_stats.cc b/chromium/third_party/blink/renderer/platform/exported/web_rtc_stats.cc
deleted file mode 100644
index 52175634f23..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_rtc_stats.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_rtc_stats.h"
-
-namespace blink {
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index a9da7db2638..8eae6d43357 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -40,6 +40,16 @@ void WebRuntimeFeatures::EnableBlockingFocusWithoutUserActivation(bool enable) {
RuntimeEnabledFeatures::SetBlockingFocusWithoutUserActivationEnabled(enable);
}
+void WebRuntimeFeatures::EnableBrowserVerifiedUserActivationKeyboard(
+ bool enable) {
+ RuntimeEnabledFeatures::SetBrowserVerifiedUserActivationKeyboardEnabled(
+ enable);
+}
+
+void WebRuntimeFeatures::EnableBrowserVerifiedUserActivationMouse(bool enable) {
+ RuntimeEnabledFeatures::SetBrowserVerifiedUserActivationMouseEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableExperimentalFeatures(bool enable) {
RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(enable);
}
@@ -105,6 +115,10 @@ void WebRuntimeFeatures::EnableAccessibilityExposeDisplayNone(bool enable) {
RuntimeEnabledFeatures::SetAccessibilityExposeDisplayNoneEnabled(enable);
}
+void WebRuntimeFeatures::EnableAccessibilityExposeHTMLElement(bool enable) {
+ RuntimeEnabledFeatures::SetAccessibilityExposeHTMLElementEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableAccessibilityObjectModel(bool enable) {
RuntimeEnabledFeatures::SetAccessibilityObjectModelEnabled(enable);
}
@@ -141,10 +155,6 @@ void WebRuntimeFeatures::EnableCookiesWithoutSameSiteMustBeSecure(bool enable) {
RuntimeEnabledFeatures::SetCookiesWithoutSameSiteMustBeSecureEnabled(enable);
}
-void WebRuntimeFeatures::EnableWasmCodeCache(bool enable) {
- RuntimeEnabledFeatures::SetWasmCodeCacheEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableCanvas2dImageChromium(bool enable) {
RuntimeEnabledFeatures::SetCanvas2dImageChromiumEnabled(enable);
}
@@ -209,10 +219,6 @@ void WebRuntimeFeatures::EnableForceTallerSelectPopup(bool enable) {
RuntimeEnabledFeatures::SetForceTallerSelectPopupEnabled(enable);
}
-void WebRuntimeFeatures::EnableFormControlsRefresh(bool enable) {
- RuntimeEnabledFeatures::SetFormControlsRefreshEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableGenericSensorExtraClasses(bool enable) {
RuntimeEnabledFeatures::SetSensorExtraClassesEnabled(enable);
}
@@ -229,18 +235,6 @@ void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) {
RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable);
}
-void WebRuntimeFeatures::EnableBuiltInModuleAll(bool enable) {
- RuntimeEnabledFeatures::SetBuiltInModuleAllEnabled(enable);
-}
-
-void WebRuntimeFeatures::EnableBuiltInModuleInfra(bool enable) {
- RuntimeEnabledFeatures::SetBuiltInModuleInfraEnabled(enable);
-}
-
-void WebRuntimeFeatures::EnableBuiltInModuleKvStorage(bool enable) {
- RuntimeEnabledFeatures::SetBuiltInModuleKvStorageEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableLayoutNG(bool enable) {
RuntimeEnabledFeatures::SetLayoutNGEnabled(enable);
}
@@ -329,15 +323,24 @@ void WebRuntimeFeatures::EnablePaymentApp(bool enable) {
RuntimeEnabledFeatures::SetPaymentAppEnabled(enable);
}
+void WebRuntimeFeatures::EnablePaymentHandlerMinimalUI(bool enable) {
+ RuntimeEnabledFeatures::SetPaymentHandlerMinimalUIEnabled(enable);
+}
+
void WebRuntimeFeatures::EnablePaymentRequest(bool enable) {
RuntimeEnabledFeatures::SetPaymentRequestEnabled(enable);
if (!enable) {
// Disable features that depend on Payment Request API.
- RuntimeEnabledFeatures::SetPaymentMethodChangeEventEnabled(false);
RuntimeEnabledFeatures::SetPaymentAppEnabled(false);
+ RuntimeEnabledFeatures::SetPaymentHandlerMinimalUIEnabled(false);
+ RuntimeEnabledFeatures::SetPaymentMethodChangeEventEnabled(false);
}
}
+void WebRuntimeFeatures::EnablePercentBasedScrolling(bool enable) {
+ RuntimeEnabledFeatures::SetPercentBasedScrollingEnabled(enable);
+}
+
void WebRuntimeFeatures::EnablePerformanceManagerInstrumentation(bool enable) {
RuntimeEnabledFeatures::SetPerformanceManagerInstrumentationEnabled(enable);
}
@@ -374,10 +377,6 @@ void WebRuntimeFeatures::EnableScriptedSpeechSynthesis(bool enable) {
RuntimeEnabledFeatures::SetScriptedSpeechSynthesisEnabled(enable);
}
-void WebRuntimeFeatures::EnableUpdateHoverAtBeginFrame(bool enable) {
- RuntimeEnabledFeatures::SetUpdateHoverAtBeginFrameEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableUserActivationPostMessageTransfer(bool enable) {
RuntimeEnabledFeatures::SetUserActivationPostMessageTransferEnabled(enable);
}
@@ -430,10 +429,6 @@ void WebRuntimeFeatures::EnablePreciseMemoryInfo(bool enable) {
RuntimeEnabledFeatures::SetPreciseMemoryInfoEnabled(enable);
}
-void WebRuntimeFeatures::EnablePrintBrowser(bool enable) {
- RuntimeEnabledFeatures::SetPrintBrowserEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableV8IdleTasks(bool enable) {
RuntimeEnabledFeatures::SetV8IdleTasksEnabled(enable);
}
@@ -466,24 +461,12 @@ void WebRuntimeFeatures::EnableWebXRARModule(bool enable) {
RuntimeEnabledFeatures::SetWebXRARModuleEnabled(enable);
}
-void WebRuntimeFeatures::EnableWebXRARDOMOverlay(bool enable) {
- RuntimeEnabledFeatures::SetWebXRARDOMOverlayEnabled(enable);
-}
-
-void WebRuntimeFeatures::EnableWebXRAnchors(bool enable) {
- RuntimeEnabledFeatures::SetWebXRAnchorsEnabled(enable);
-}
-
-void WebRuntimeFeatures::EnableWebXrGamepadModule(bool enable) {
- RuntimeEnabledFeatures::SetWebXrGamepadModuleEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableWebXRHitTest(bool enable) {
RuntimeEnabledFeatures::SetWebXRHitTestEnabled(enable);
}
-void WebRuntimeFeatures::EnableWebXRPlaneDetection(bool enable) {
- RuntimeEnabledFeatures::SetWebXRPlaneDetectionEnabled(enable);
+void WebRuntimeFeatures::EnableWebXRIncubations(bool enable) {
+ RuntimeEnabledFeatures::SetWebXRIncubationsEnabled(enable);
}
void WebRuntimeFeatures::EnablePresentationAPI(bool enable) {
@@ -514,14 +497,6 @@ void WebRuntimeFeatures::EnableExpensiveBackgroundTimerThrottling(bool enable) {
RuntimeEnabledFeatures::SetExpensiveBackgroundTimerThrottlingEnabled(enable);
}
-void WebRuntimeFeatures::EnableFetchMetadata(bool enable) {
- RuntimeEnabledFeatures::SetFetchMetadataEnabled(enable);
-}
-
-void WebRuntimeFeatures::EnableFetchMetadataDestination(bool enable) {
- RuntimeEnabledFeatures::SetFetchMetadataDestinationEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableTimerThrottlingForBackgroundTabs(bool enable) {
RuntimeEnabledFeatures::SetTimerThrottlingForBackgroundTabsEnabled(enable);
}
@@ -552,10 +527,6 @@ void WebRuntimeFeatures::EnableVideoRotateToFullscreen(bool enable) {
RuntimeEnabledFeatures::SetVideoRotateToFullscreenEnabled(enable);
}
-void WebRuntimeFeatures::EnableVideoFullscreenDetection(bool enable) {
- RuntimeEnabledFeatures::SetVideoFullscreenDetectionEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableVideoPlaybackQuality(bool enable) {
RuntimeEnabledFeatures::SetVideoPlaybackQualityEnabled(enable);
}
@@ -668,10 +639,6 @@ void WebRuntimeFeatures::EnableSmsReceiver(bool enable) {
RuntimeEnabledFeatures::SetSmsReceiverEnabled(enable);
}
-void WebRuntimeFeatures::EnableDisplayLocking(bool enable) {
- RuntimeEnabledFeatures::SetDisplayLockingEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableConsolidatedMovementXY(bool enable) {
RuntimeEnabledFeatures::SetConsolidatedMovementXYEnabled(enable);
}
@@ -696,4 +663,12 @@ void WebRuntimeFeatures::EnableAcceleratedSmallCanvases(bool enable) {
RuntimeEnabledFeatures::SetAcceleratedSmallCanvasesEnabled(enable);
}
+void WebRuntimeFeatures::EnableTrustTokens(bool enable) {
+ RuntimeEnabledFeatures::SetTrustTokensEnabled(enable);
+}
+
+void WebRuntimeFeatures::EnableInstalledApp(bool enable) {
+ RuntimeEnabledFeatures::SetInstalledAppEnabled(enable);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_touch_event.cc b/chromium/third_party/blink/renderer/platform/exported/web_touch_event.cc
deleted file mode 100644
index e358ccb9d5f..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_touch_event.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/web_touch_event.h"
-
-namespace blink {
-
-WebTouchEvent WebTouchEvent::FlattenTransform() const {
- WebTouchEvent transformed_event = *this;
- for (unsigned i = 0; i < touches_length; ++i) {
- transformed_event.touches[i] = TouchPointInRootFrame(i);
- }
- transformed_event.frame_translate_.x = 0;
- transformed_event.frame_translate_.y = 0;
- transformed_event.frame_scale_ = 1;
-
- return transformed_event;
-}
-
-WebTouchPoint WebTouchEvent::TouchPointInRootFrame(unsigned point) const {
- DCHECK_LT(point, touches_length);
- if (point >= touches_length)
- return WebTouchPoint();
-
- WebTouchPoint transformed_point = touches[point];
- transformed_point.radius_x /= frame_scale_;
- transformed_point.radius_y /= frame_scale_;
- transformed_point.SetPositionInWidget(
- (transformed_point.PositionInWidget().x / frame_scale_) +
- frame_translate_.x,
- (transformed_point.PositionInWidget().y / frame_scale_) +
- frame_translate_.y);
- return transformed_point;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_error.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_error.cc
index 9bc40c70762..c06728263cb 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_error.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_url_error.cc
@@ -15,11 +15,13 @@ WebURLError::WebURLError(int reason, const WebURL& url)
WebURLError::WebURLError(int reason,
int extended_reason,
+ net::ResolveErrorInfo resolve_error_info,
HasCopyInCache has_copy_in_cache,
IsWebSecurityViolation is_web_security_violation,
const WebURL& url)
: reason_(reason),
extended_reason_(extended_reason),
+ resolve_error_info_(resolve_error_info),
has_copy_in_cache_(has_copy_in_cache == HasCopyInCache::kTrue),
is_web_security_violation_(is_web_security_violation ==
IsWebSecurityViolation::kTrue),
@@ -27,6 +29,18 @@ WebURLError::WebURLError(int reason,
DCHECK_NE(reason_, 0);
}
+WebURLError::WebURLError(network::BlockedByResponseReason blocked_reason,
+ net::ResolveErrorInfo resolve_error_info,
+ HasCopyInCache has_copy_in_cache,
+ const WebURL& url)
+ : reason_(net::ERR_BLOCKED_BY_RESPONSE),
+ extended_reason_(0),
+ resolve_error_info_(resolve_error_info),
+ has_copy_in_cache_(has_copy_in_cache == HasCopyInCache::kTrue),
+ is_web_security_violation_(false),
+ url_(url),
+ blocked_by_response_reason_(blocked_reason) {}
+
WebURLError::WebURLError(const network::CorsErrorStatus& cors_error_status,
HasCopyInCache has_copy_in_cache,
const WebURL& url)
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_load_timing.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_load_timing.cc
deleted file mode 100644
index 861cbdc1f72..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_load_timing.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_url_load_timing.h"
-
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
-
-namespace blink {
-
-void WebURLLoadTiming::Initialize() {
- private_ = ResourceLoadTiming::Create();
-}
-
-void WebURLLoadTiming::Reset() {
- private_.Reset();
-}
-
-void WebURLLoadTiming::Assign(const WebURLLoadTiming& other) {
- private_ = other.private_;
-}
-
-base::TimeTicks WebURLLoadTiming::RequestTime() const {
- return private_->RequestTime();
-}
-
-void WebURLLoadTiming::SetRequestTime(base::TimeTicks time) {
- private_->SetRequestTime(time);
-}
-
-base::TimeTicks WebURLLoadTiming::ProxyStart() const {
- return private_->ProxyStart();
-}
-
-void WebURLLoadTiming::SetProxyStart(base::TimeTicks start) {
- private_->SetProxyStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::ProxyEnd() const {
- return private_->ProxyEnd();
-}
-
-void WebURLLoadTiming::SetProxyEnd(base::TimeTicks end) {
- private_->SetProxyEnd(end);
-}
-
-base::TimeTicks WebURLLoadTiming::DnsStart() const {
- return private_->DnsStart();
-}
-
-void WebURLLoadTiming::SetDNSStart(base::TimeTicks start) {
- private_->SetDnsStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::DnsEnd() const {
- return private_->DnsEnd();
-}
-
-void WebURLLoadTiming::SetDNSEnd(base::TimeTicks end) {
- private_->SetDnsEnd(end);
-}
-
-base::TimeTicks WebURLLoadTiming::ConnectStart() const {
- return private_->ConnectStart();
-}
-
-void WebURLLoadTiming::SetConnectStart(base::TimeTicks start) {
- private_->SetConnectStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::ConnectEnd() const {
- return private_->ConnectEnd();
-}
-
-void WebURLLoadTiming::SetConnectEnd(base::TimeTicks end) {
- private_->SetConnectEnd(end);
-}
-
-base::TimeTicks WebURLLoadTiming::WorkerStart() const {
- return private_->WorkerStart();
-}
-
-void WebURLLoadTiming::SetWorkerStart(base::TimeTicks start) {
- private_->SetWorkerStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::WorkerReady() const {
- return private_->WorkerReady();
-}
-
-void WebURLLoadTiming::SetWorkerReady(base::TimeTicks ready) {
- private_->SetWorkerReady(ready);
-}
-
-base::TimeTicks WebURLLoadTiming::SendStart() const {
- return private_->SendStart();
-}
-
-void WebURLLoadTiming::SetSendStart(base::TimeTicks start) {
- private_->SetSendStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::SendEnd() const {
- return private_->SendEnd();
-}
-
-void WebURLLoadTiming::SetSendEnd(base::TimeTicks end) {
- private_->SetSendEnd(end);
-}
-
-base::TimeTicks WebURLLoadTiming::ReceiveHeadersStart() const {
- return private_->ReceiveHeadersStart();
-}
-
-void WebURLLoadTiming::SetReceiveHeadersStart(base::TimeTicks start) {
- private_->SetReceiveHeadersStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::ReceiveHeadersEnd() const {
- return private_->ReceiveHeadersEnd();
-}
-
-void WebURLLoadTiming::SetReceiveHeadersEnd(base::TimeTicks end) {
- private_->SetReceiveHeadersEnd(end);
-}
-
-base::TimeTicks WebURLLoadTiming::SslStart() const {
- return private_->SslStart();
-}
-
-void WebURLLoadTiming::SetSSLStart(base::TimeTicks start) {
- private_->SetSslStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::SslEnd() const {
- return private_->SslEnd();
-}
-
-void WebURLLoadTiming::SetSSLEnd(base::TimeTicks end) {
- private_->SetSslEnd(end);
-}
-
-base::TimeTicks WebURLLoadTiming::PushStart() const {
- return private_->PushStart();
-}
-
-void WebURLLoadTiming::SetPushStart(base::TimeTicks start) {
- private_->SetPushStart(start);
-}
-
-base::TimeTicks WebURLLoadTiming::PushEnd() const {
- return private_->PushEnd();
-}
-
-void WebURLLoadTiming::SetPushEnd(base::TimeTicks end) {
- private_->SetPushEnd(end);
-}
-
-WebURLLoadTiming::WebURLLoadTiming(scoped_refptr<ResourceLoadTiming> value)
- : private_(std::move(value)) {}
-
-WebURLLoadTiming& WebURLLoadTiming::operator=(
- scoped_refptr<ResourceLoadTiming> value) {
- private_ = std::move(value);
- return *this;
-}
-
-WebURLLoadTiming::operator scoped_refptr<ResourceLoadTiming>() const {
- return private_.Get();
-}
-
-WebURLLoadTiming WebURLLoadTiming::DeepCopy() const {
- return private_->DeepCopy();
-}
-
-bool WebURLLoadTiming::operator==(const WebURLLoadTiming& other) const {
- return *private_ == *other.private_;
-}
-
-} // namespace blink
-
-namespace WTF {
-
-CrossThreadCopier<blink::WebURLLoadTiming>::Type CrossThreadCopier<
- blink::WebURLLoadTiming>::Copy(const blink::WebURLLoadTiming& timing) {
- return timing.DeepCopy();
-}
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc
index 50ebdbbad7c..651e79a8859 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -35,12 +35,15 @@
#include "base/time/time.h"
#include "net/base/load_flags.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/optional_trust_token_params.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -50,43 +53,74 @@ using blink::mojom::FetchCacheMode;
namespace blink {
-WebURLRequest::ExtraData::ExtraData() : render_frame_id_(MSG_ROUTING_NONE) {}
+// This is complementary to ConvertNetPriorityToWebKitPriority, defined in
+// service_worker_context_client.cc.
+net::RequestPriority ConvertWebKitPriorityToNetPriority(
+ WebURLRequest::Priority priority) {
+ switch (priority) {
+ case WebURLRequest::Priority::kVeryHigh:
+ return net::HIGHEST;
+
+ case WebURLRequest::Priority::kHigh:
+ return net::MEDIUM;
+
+ case WebURLRequest::Priority::kMedium:
+ return net::LOW;
-// The purpose of this struct is to permit allocating a ResourceRequest on the
-// heap, which is otherwise disallowed by DISALLOW_NEW annotation on
-// ResourceRequest.
-// TODO(keishi): Replace with GCWrapper<ResourceRequest>
-struct WebURLRequest::ResourceRequestContainer {
- ResourceRequestContainer() = default;
- explicit ResourceRequestContainer(const ResourceRequest& r)
- : resource_request(r) {}
+ case WebURLRequest::Priority::kLow:
+ return net::LOWEST;
- ResourceRequest resource_request;
-};
+ case WebURLRequest::Priority::kVeryLow:
+ return net::IDLE;
+
+ case WebURLRequest::Priority::kUnresolved:
+ default:
+ NOTREACHED();
+ return net::LOW;
+ }
+}
+
+WebURLRequest::ExtraData::ExtraData() : render_frame_id_(MSG_ROUTING_NONE) {}
WebURLRequest::~WebURLRequest() = default;
WebURLRequest::WebURLRequest()
- : owned_resource_request_(new ResourceRequestContainer()),
- resource_request_(&owned_resource_request_->resource_request) {}
+ : owned_resource_request_(std::make_unique<ResourceRequest>()),
+ resource_request_(owned_resource_request_.get()) {}
+
+WebURLRequest::WebURLRequest(WebURLRequest&& src) {
+ *this = std::move(src);
+}
-WebURLRequest::WebURLRequest(const WebURLRequest& r)
- : owned_resource_request_(
- new ResourceRequestContainer(*r.resource_request_)),
- resource_request_(&owned_resource_request_->resource_request) {}
+WebURLRequest& WebURLRequest::operator=(WebURLRequest&& src) {
+ if (this == &src) {
+ return *this;
+ }
+ if (src.owned_resource_request_) {
+ owned_resource_request_ = std::move(src.owned_resource_request_);
+ resource_request_ = owned_resource_request_.get();
+ } else {
+ owned_resource_request_ = std::make_unique<ResourceRequest>();
+ resource_request_ = owned_resource_request_.get();
+ CopyFrom(src);
+ }
+ src.resource_request_ = nullptr;
+ return *this;
+}
WebURLRequest::WebURLRequest(const WebURL& url) : WebURLRequest() {
SetUrl(url);
}
-WebURLRequest& WebURLRequest::operator=(const WebURLRequest& r) {
+void WebURLRequest::CopyFrom(const WebURLRequest& r) {
// Copying subclasses that have different m_resourceRequest ownership
// semantics via this operator is just not supported.
DCHECK(owned_resource_request_);
- DCHECK(resource_request_);
- if (&r != this)
- *resource_request_ = *r.resource_request_;
- return *this;
+ DCHECK_EQ(owned_resource_request_.get(), resource_request_);
+ DCHECK(owned_resource_request_->IsNull());
+ DCHECK(this != &r);
+ resource_request_->CopyHeadFrom(*r.resource_request_);
+ resource_request_->SetHttpBody(r.resource_request_->HttpBody());
}
bool WebURLRequest::IsNull() const {
@@ -101,11 +135,12 @@ void WebURLRequest::SetUrl(const WebURL& url) {
resource_request_->SetUrl(url);
}
-WebURL WebURLRequest::SiteForCookies() const {
+const net::SiteForCookies& WebURLRequest::SiteForCookies() const {
return resource_request_->SiteForCookies();
}
-void WebURLRequest::SetSiteForCookies(const WebURL& site_for_cookies) {
+void WebURLRequest::SetSiteForCookies(
+ const net::SiteForCookies& site_for_cookies) {
resource_request_->SetSiteForCookies(site_for_cookies);
}
@@ -166,24 +201,10 @@ WebString WebURLRequest::HttpHeaderField(const WebString& name) const {
void WebURLRequest::SetHttpHeaderField(const WebString& name,
const WebString& value) {
- CHECK(!DeprecatedEqualIgnoringCase(name, "referer"));
+ CHECK(!EqualIgnoringASCIICase(name, "referer"));
resource_request_->SetHttpHeaderField(name, value);
}
-void WebURLRequest::SetHttpReferrer(
- const WebString& web_referrer,
- network::mojom::ReferrerPolicy referrer_policy) {
- // WebString doesn't have the distinction between empty and null. We use
- // the null WTFString for referrer.
- DCHECK_EQ(Referrer::NoReferrer(), String());
- String referrer =
- web_referrer.IsEmpty() ? Referrer::NoReferrer() : String(web_referrer);
- // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
- // header and instead use a separate member. See https://crbug.com/850813.
- resource_request_->SetHttpReferrer(Referrer(referrer, referrer_policy));
- resource_request_->SetReferrerString(referrer);
-}
-
void WebURLRequest::AddHttpHeaderField(const WebString& name,
const WebString& value) {
resource_request_->AddHttpHeaderField(name, value);
@@ -227,6 +248,24 @@ mojom::RequestContextType WebURLRequest::GetRequestContext() const {
return resource_request_->GetRequestContext();
}
+network::mojom::RequestDestination WebURLRequest::GetRequestDestination()
+ const {
+ return resource_request_->GetRequestDestination();
+}
+
+void WebURLRequest::SetReferrerString(const WebString& referrer) {
+ resource_request_->SetReferrerString(referrer);
+}
+
+void WebURLRequest::SetReferrerPolicy(
+ network::mojom::ReferrerPolicy referrer_policy) {
+ resource_request_->SetReferrerPolicy(referrer_policy);
+}
+
+WebString WebURLRequest::ReferrerString() const {
+ return resource_request_->ReferrerString();
+}
+
network::mojom::ReferrerPolicy WebURLRequest::GetReferrerPolicy() const {
return resource_request_->GetReferrerPolicy();
}
@@ -248,6 +287,11 @@ void WebURLRequest::SetRequestContext(
resource_request_->SetRequestContext(request_context);
}
+void WebURLRequest::SetRequestDestination(
+ network::mojom::RequestDestination destination) {
+ resource_request_->SetRequestDestination(destination);
+}
+
int WebURLRequest::RequestorID() const {
return resource_request_->RequestorID();
}
@@ -333,11 +377,12 @@ void WebURLRequest::SetPreviewsState(
return resource_request_->SetPreviewsState(previews_state);
}
-WebURLRequest::ExtraData* WebURLRequest::GetExtraData() const {
+const scoped_refptr<WebURLRequest::ExtraData>& WebURLRequest::GetExtraData()
+ const {
return resource_request_->GetExtraData();
}
-void WebURLRequest::SetExtraData(std::unique_ptr<ExtraData> extra_data) {
+void WebURLRequest::SetExtraData(scoped_refptr<ExtraData> extra_data) {
resource_request_->SetExtraData(std::move(extra_data));
}
@@ -504,6 +549,10 @@ base::Optional<base::UnguessableToken> WebURLRequest::RecursivePrefetchToken()
return resource_request_->RecursivePrefetchToken();
}
+network::OptionalTrustTokenParams WebURLRequest::TrustTokenParams() const {
+ return ConvertTrustTokenParams(resource_request_->TrustTokenParams());
+}
+
WebURLRequest::WebURLRequest(ResourceRequest& r) : resource_request_(&r) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_request_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_request_test.cc
index bce21fa0f57..c03d48e319c 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_request_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_url_request_test.cc
@@ -40,9 +40,9 @@ class RequestTestExtraData : public WebURLRequest::ExtraData {
public:
explicit RequestTestExtraData(bool* alive) : alive_(alive) { *alive = true; }
+ private:
~RequestTestExtraData() override { *alive_ = false; }
- private:
bool* alive_;
};
@@ -52,14 +52,15 @@ TEST(WebURLRequestTest, ExtraData) {
bool alive = false;
{
WebURLRequest url_request;
- auto extra_data = std::make_unique<RequestTestExtraData>(&alive);
+ auto extra_data = base::MakeRefCounted<RequestTestExtraData>(&alive);
EXPECT_TRUE(alive);
auto* raw_extra_data_pointer = extra_data.get();
url_request.SetExtraData(std::move(extra_data));
EXPECT_EQ(raw_extra_data_pointer, url_request.GetExtraData());
{
- WebURLRequest other_url_request = url_request;
+ WebURLRequest other_url_request;
+ other_url_request.CopyFrom(url_request);
EXPECT_TRUE(alive);
EXPECT_EQ(raw_extra_data_pointer, other_url_request.GetExtraData());
EXPECT_EQ(raw_extra_data_pointer, url_request.GetExtraData());
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
index e8eca6afa73..6723c059edb 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -36,11 +36,11 @@
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
+#include "services/network/public/mojom/load_timing_info.mojom.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
#include "third_party/blink/public/platform/web_http_load_info.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/platform/web_url_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -99,10 +99,27 @@ void WebURLResponse::SetConnectionReused(bool connection_reused) {
resource_response_->SetConnectionReused(connection_reused);
}
-void WebURLResponse::SetLoadTiming(const WebURLLoadTiming& timing) {
- scoped_refptr<ResourceLoadTiming> load_timing =
- scoped_refptr<ResourceLoadTiming>(timing);
- resource_response_->SetResourceLoadTiming(std::move(load_timing));
+void WebURLResponse::SetLoadTiming(
+ const network::mojom::LoadTimingInfo& mojo_timing) {
+ auto timing = ResourceLoadTiming::Create();
+ timing->SetRequestTime(mojo_timing.request_start);
+ timing->SetProxyStart(mojo_timing.proxy_resolve_start);
+ timing->SetProxyEnd(mojo_timing.proxy_resolve_end);
+ timing->SetDnsStart(mojo_timing.connect_timing.dns_start);
+ timing->SetDnsEnd(mojo_timing.connect_timing.dns_end);
+ timing->SetConnectStart(mojo_timing.connect_timing.connect_start);
+ timing->SetConnectEnd(mojo_timing.connect_timing.connect_end);
+ timing->SetWorkerStart(mojo_timing.service_worker_start_time);
+ timing->SetWorkerReady(mojo_timing.service_worker_ready_time);
+ timing->SetSendStart(mojo_timing.send_start);
+ timing->SetSendEnd(mojo_timing.send_end);
+ timing->SetReceiveHeadersStart(mojo_timing.receive_headers_start);
+ timing->SetReceiveHeadersEnd(mojo_timing.receive_headers_end);
+ timing->SetSslStart(mojo_timing.connect_timing.ssl_start);
+ timing->SetSslEnd(mojo_timing.connect_timing.ssl_end);
+ timing->SetPushStart(mojo_timing.push_start);
+ timing->SetPushEnd(mojo_timing.push_end);
+ resource_response_->SetResourceLoadTiming(std::move(timing));
}
void WebURLResponse::SetHTTPLoadInfo(const WebHTTPLoadInfo& value) {
@@ -244,6 +261,10 @@ void WebURLResponse::SetIsLegacyTLSVersion(bool value) {
resource_response_->SetIsLegacyTLSVersion(value);
}
+void WebURLResponse::SetTimingAllowPassed(bool value) {
+ resource_response_->SetTimingAllowPassed(value);
+}
+
void WebURLResponse::SetSecurityStyle(SecurityStyle security_style) {
resource_response_->SetSecurityStyle(security_style);
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc b/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc
index 93a3d2217ae..df11208b5df 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_video_frame_submitter.cc
@@ -26,10 +26,12 @@ namespace blink {
std::unique_ptr<WebVideoFrameSubmitter> WebVideoFrameSubmitter::Create(
WebContextProviderCallback context_provider_callback,
+ cc::PlaybackRoughnessReportingCallback roughness_reporting_callback,
const cc::LayerTreeSettings& settings,
bool use_sync_primitives) {
return std::make_unique<VideoFrameSubmitter>(
std::move(context_provider_callback),
+ std::move(roughness_reporting_callback),
std::make_unique<VideoFrameResourceProvider>(settings,
use_sync_primitives));
}
diff --git a/chromium/third_party/blink/renderer/platform/file_metadata.cc b/chromium/third_party/blink/renderer/platform/file_metadata.cc
index c78e471f403..51d0190b0b9 100644
--- a/chromium/third_party/blink/renderer/platform/file_metadata.cc
+++ b/chromium/third_party/blink/renderer/platform/file_metadata.cc
@@ -36,9 +36,9 @@
#include "base/optional.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/filename_util.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/file/file_utilities.mojom-blink.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
@@ -92,14 +92,14 @@ void RebindFileUtilitiesForTesting() {
if (host) {
host.Unbind().reset();
}
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
host.BindNewPipeAndPassReceiver());
}
bool GetFileMetadata(const String& path, FileMetadata& metadata) {
auto& host = GetFileUtilitiesHost();
if (!host) {
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
host.BindNewPipeAndPassReceiver());
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc
index c9a48d57f2f..48295090b57 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h"
#include "mojo/public/mojom/base/shared_memory.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -86,7 +86,7 @@ void FontUniqueNameLookupAndroid::EnsureServiceConnected() {
if (service_)
return;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
service_.BindNewPipeAndPassReceiver());
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.cc b/chromium/third_party/blink/renderer/platform/fonts/font.cc
index 2b110b2e0e0..7a9414845a0 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.cc
@@ -48,27 +48,20 @@
namespace blink {
-Font::Font() : can_shape_word_by_word_(0), shape_word_by_word_computed_(0) {}
-
-Font::Font(const FontDescription& fd)
- : font_description_(fd),
- can_shape_word_by_word_(0),
- shape_word_by_word_computed_(0) {}
-
-Font::Font(const Font& other)
- : font_description_(other.font_description_),
- font_fallback_list_(other.font_fallback_list_),
- // TODO(yosin): We should have a comment the reason why don't we copy
- // |m_canShapeWordByWord| and |m_shapeWordByWordComputed| from |other|,
- // since |operator=()| copies them from |other|.
- can_shape_word_by_word_(0),
- shape_word_by_word_computed_(0) {}
+Font::Font() = default;
+
+Font::Font(const FontDescription& fd) : font_description_(fd) {}
+
+Font::Font(const FontDescription& font_description, FontSelector* font_selector)
+ : font_description_(font_description),
+ font_fallback_list_(
+ font_selector ? FontFallbackList::Create(font_selector) : nullptr) {}
+
+Font::Font(const Font& other) = default;
Font& Font::operator=(const Font& other) {
font_description_ = other.font_description_;
font_fallback_list_ = other.font_fallback_list_;
- can_shape_word_by_word_ = other.can_shape_word_by_word_;
- shape_word_by_word_computed_ = other.shape_word_by_word_computed_;
return *this;
}
@@ -91,18 +84,6 @@ bool Font::operator==(const Font& other) const {
: 0);
}
-void Font::Update(FontSelector* font_selector) const {
- // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr,
- // but it ends up being reasonably safe (because inherited fonts in the render
- // tree pick up the new style anyway. Other copies are transient, e.g., the
- // state in the GraphicsContext, and won't stick around long enough to get you
- // in trouble). Still, this is pretty disgusting, and could eventually be
- // rectified by using RefPtrs for Fonts themselves.
- if (!font_fallback_list_)
- font_fallback_list_ = FontFallbackList::Create();
- font_fallback_list_->Invalidate(font_selector);
-}
-
namespace {
void DrawBlobs(cc::PaintCanvas* canvas,
@@ -217,7 +198,10 @@ bool Font::DrawBidiText(cc::PaintCanvas* canvas,
TextRunPaintInfo subrun_info(subrun);
- ShapeResultBloberizer bloberizer(*this, device_scale_factor);
+ // Fix regression with -ftrivial-auto-var-init=pattern. See
+ // crbug.com/1055652.
+ STACK_UNINITIALIZED ShapeResultBloberizer bloberizer(*this,
+ device_scale_factor);
ShapeResultBuffer buffer;
word_shaper.FillResultBuffer(subrun_info, &buffer);
float run_width = bloberizer.FillGlyphs(subrun_info, buffer);
@@ -422,31 +406,15 @@ int Font::OffsetForPosition(const TextRun& run,
}
ShapeCache* Font::GetShapeCache() const {
- return font_fallback_list_->GetShapeCache(font_description_);
+ return EnsureFontFallbackList()->GetShapeCache(font_description_);
}
bool Font::CanShapeWordByWord() const {
- if (!shape_word_by_word_computed_) {
- can_shape_word_by_word_ = ComputeCanShapeWordByWord();
- shape_word_by_word_computed_ = true;
- }
- return can_shape_word_by_word_;
-}
-
-bool Font::ComputeCanShapeWordByWord() const {
- if (!GetFontDescription().GetTypesettingFeatures())
- return true;
-
- if (!PrimaryFont())
- return false;
-
- const FontPlatformData& platform_data = PrimaryFont()->PlatformData();
- TypesettingFeatures features = GetFontDescription().GetTypesettingFeatures();
- return !platform_data.HasSpaceInLigaturesOrKerning(features);
+ return EnsureFontFallbackList()->CanShapeWordByWord(GetFontDescription());
}
void Font::ReportNotDefGlyph() const {
- FontSelector* fontSelector = font_fallback_list_->GetFontSelector();
+ FontSelector* fontSelector = EnsureFontFallbackList()->GetFontSelector();
// We have a few non-DOM usages of Font code, for example in DragImage::Create
// and in EmbeddedObjectPainter::paintReplaced. In those cases, we can't
// retrieve a font selector as our connection to a Document object to report
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.h b/chromium/third_party/blink/renderer/platform/fonts/font.h
index ca24f5f5e49..2aeb6057caa 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.h
@@ -54,7 +54,6 @@ namespace blink {
struct CharacterRange;
class FloatPoint;
class FloatRect;
-class FontData;
class FontSelector;
class ShapeCache;
class TextRun;
@@ -66,7 +65,8 @@ class PLATFORM_EXPORT Font {
public:
Font();
- Font(const FontDescription&);
+ explicit Font(const FontDescription&);
+ Font(const FontDescription&, FontSelector*);
~Font();
Font(const Font&);
@@ -79,8 +79,6 @@ class PLATFORM_EXPORT Font {
return font_description_;
}
- void Update(FontSelector*) const;
-
enum CustomFontNotReadyAction {
kDoNotPaintIfFontNotReady,
kUseFallbackIfFontNotReady
@@ -203,7 +201,6 @@ class PLATFORM_EXPORT Font {
// loaded. This *should* not happen but in reality it does ever now and then
// when, for whatever reason, the last resort font cannot be loaded.
const SimpleFontData* PrimaryFont() const;
- const FontData* FontDataAt(unsigned) const;
// Access the shape cache associated with this particular font object.
// Should *not* be retained across layout calls as it may become invalid.
@@ -215,8 +212,7 @@ class PLATFORM_EXPORT Font {
bool CanShapeWordByWord() const;
void SetCanShapeWordByWordForTesting(bool b) {
- can_shape_word_by_word_ = b;
- shape_word_by_word_computed_ = true;
+ EnsureFontFallbackList()->SetCanShapeWordByWordForTesting(b);
}
void ReportNotDefGlyph() const;
@@ -226,12 +222,11 @@ class PLATFORM_EXPORT Font {
GlyphData GetEmphasisMarkGlyphData(const AtomicString&) const;
- bool ComputeCanShapeWordByWord() const;
-
public:
FontSelector* GetFontSelector() const;
FontFallbackIterator CreateFontFallbackIterator(
FontFallbackPriority fallback_priority) const {
+ EnsureFontFallbackList();
return FontFallbackIterator(font_description_, font_fallback_list_,
fallback_priority);
}
@@ -246,25 +241,20 @@ class PLATFORM_EXPORT Font {
}
private:
+ FontFallbackList* EnsureFontFallbackList() const {
+ if (!font_fallback_list_)
+ font_fallback_list_ = FontFallbackList::Create(nullptr);
+ return font_fallback_list_.get();
+ }
+
FontDescription font_description_;
mutable scoped_refptr<FontFallbackList> font_fallback_list_;
- mutable unsigned can_shape_word_by_word_ : 1;
- mutable unsigned shape_word_by_word_computed_ : 1;
-
- // For m_fontDescription & m_fontFallbackList access.
- friend class CachingWordShaper;
};
inline Font::~Font() = default;
inline const SimpleFontData* Font::PrimaryFont() const {
- DCHECK(font_fallback_list_);
- return font_fallback_list_->PrimarySimpleFontData(font_description_);
-}
-
-inline const FontData* Font::FontDataAt(unsigned index) const {
- DCHECK(font_fallback_list_);
- return font_fallback_list_->FontDataAt(font_description_, index);
+ return EnsureFontFallbackList()->PrimarySimpleFontData(font_description_);
}
inline FontSelector* Font::GetFontSelector() const {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
index b4a7e9509cf..396a27aa4fe 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -386,6 +386,11 @@ void FontCache::InvalidateShapeCache() {
PurgeFallbackListShaperCache();
}
+void FontCache::InvalidateEnumerationCache() {
+ TRACE_EVENT0("fonts,ui", "FontCache::InvalidateEnumerationCache");
+ font_enumeration_cache_.clear();
+}
+
void FontCache::Purge(PurgeSeverity purge_severity) {
// Ideally we should never be forcing the purge while the
// FontCachePurgePreventer is in scope, but we call purge() at any timing
@@ -398,6 +403,7 @@ void FontCache::Purge(PurgeSeverity purge_severity) {
PurgePlatformFontDataCache();
PurgeFallbackListShaperCache();
+ InvalidateEnumerationCache();
}
void FontCache::AddClient(FontCacheClient* client) {
@@ -418,6 +424,10 @@ uint16_t FontCache::Generation() {
void FontCache::Invalidate() {
TRACE_EVENT0("fonts,ui", "FontCache::Invalidate");
font_platform_data_cache_.clear();
+ // TODO(https://crbug.com/1061630): Determine optimal cache invalidation
+ // strategy for enumeration. As implemented, the enumeration cache might not
+ // get invalidated when the system fonts change.
+ InvalidateEnumerationCache();
generation_++;
if (font_cache_clients_) {
@@ -524,4 +534,15 @@ FontCache::Bcp47Vector FontCache::GetBcp47LocaleForRequest(
return result;
}
+const std::vector<FontEnumerationEntry>& FontCache::EnumerateAvailableFonts() {
+ if (font_enumeration_cache_.size() == 0) {
+ base::TimeTicks enum_start = base::TimeTicks::Now();
+ font_enumeration_cache_ = EnumeratePlatformAvailableFonts();
+ base::TimeDelta time_taken = base::TimeTicks::Now() - enum_start;
+ UMA_HISTOGRAM_TIMES("Blink.Fonts.Enumeration.Duration", time_taken);
+ }
+
+ return font_enumeration_cache_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
index 08c723bc646..41c63400fbb 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
@@ -90,21 +90,24 @@ enum class AlternateFontName {
kLastResort
};
+struct FontEnumerationEntry {
+ String postscript_name;
+ String full_name;
+ String family;
+};
+
typedef HashMap<unsigned,
std::unique_ptr<FontPlatformData>,
WTF::IntHash<unsigned>,
WTF::UnsignedWithZeroKeyHashTraits<unsigned>>
SizedFontPlatformDataSet;
-typedef HashMap<FontCacheKey,
- SizedFontPlatformDataSet,
- FontCacheKeyHash,
- FontCacheKeyTraits>
- FontPlatformDataCache;
+typedef HashMap<FontCacheKey, SizedFontPlatformDataSet> FontPlatformDataCache;
typedef HashMap<FallbackListCompositeKey,
std::unique_ptr<ShapeCache>,
FallbackListCompositeKeyHash,
FallbackListCompositeKeyTraits>
FallbackListShaperCache;
+typedef std::vector<FontEnumerationEntry> FontEnumerationCache;
class PLATFORM_EXPORT FontCache {
friend class FontCachePurgePreventer;
@@ -252,7 +255,13 @@ class PLATFORM_EXPORT FontCache {
ShouldRetain = kRetain,
bool subpixel_ascent_descent = false);
+ const std::vector<FontEnumerationEntry>& EnumerateAvailableFonts();
+ size_t EnumerationCacheSizeForTesting() {
+ return font_enumeration_cache_.size();
+ }
+
void InvalidateShapeCache();
+ void InvalidateEnumerationCache();
static void CrashWithFontInfo(const FontDescription*);
@@ -312,6 +321,7 @@ class PLATFORM_EXPORT FontCache {
const FontDescription&,
const FontFaceCreationParams&,
float font_size);
+ std::vector<FontEnumerationEntry> EnumeratePlatformAvailableFonts();
sk_sp<SkTypeface> CreateTypeface(const FontDescription&,
const FontFaceCreationParams&,
@@ -366,6 +376,9 @@ class PLATFORM_EXPORT FontCache {
FontPlatformDataCache font_platform_data_cache_;
FallbackListShaperCache fallback_list_shaper_cache_;
FontDataCache font_data_cache_;
+ // TODO(https://crbug.com/1061625): Move to the browser process for better
+ // resource utilization.
+ FontEnumerationCache font_enumeration_cache_;
void PurgePlatformFontDataCache();
void PurgeFallbackListShaperCache();
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h
index 2160fcb2c3b..6b7c90a227d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h
@@ -42,7 +42,7 @@ class PLATFORM_EXPORT FontCacheClient
virtual ~FontCacheClient() = default;
virtual void FontCacheInvalidated() = 0;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h
index 90063cb2eac..a860a0ad051 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h
@@ -93,13 +93,19 @@ struct FontCacheKey {
}
bool operator==(const FontCacheKey& other) const {
+ bool variation_settings_equal =
+ (!variation_settings_ && !other.variation_settings_) ||
+ (variation_settings_ && other.variation_settings_ &&
+ *variation_settings_ == *other.variation_settings_);
return creation_params_ == other.creation_params_ &&
font_size_ == other.font_size_ && options_ == other.options_ &&
device_scale_factor_ == other.device_scale_factor_ &&
- variation_settings_ == other.variation_settings_ &&
+ variation_settings_equal &&
is_unique_match_ == other.is_unique_match_;
}
+ bool operator!=(const FontCacheKey& other) const { return !(*this == other); }
+
static constexpr unsigned PrecisionMultiplier() {
return kFontSizePrecisionMultiplier;
}
@@ -141,4 +147,23 @@ struct FontCacheKeyTraits : WTF::SimpleClassHashTraits<FontCacheKey> {
} // namespace blink
+namespace WTF {
+template <>
+struct DefaultHash<blink::FontCacheKey> {
+ STATIC_ONLY(DefaultHash);
+ typedef blink::FontCacheKeyHash Hash;
+};
+
+template <>
+struct HashTraits<blink::FontCacheKey>
+ : WTF::SimpleClassHashTraits<blink::FontCacheKey> {
+ STATIC_ONLY(HashTraits);
+
+ // std::string's empty state need not be zero in all implementations,
+ // and it is held within FontFaceCreationParams.
+ static const bool kEmptyValueIsZero = false;
+};
+
+} // namespace WTF
+
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_KEY_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc
index a9233996c15..0f2c270892c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc
@@ -89,4 +89,79 @@ TEST(FontCache, systemFont) {
}
#endif
+class EnumerationConsumer {
+ public:
+ explicit EnumerationConsumer(
+ const std::vector<FontEnumerationEntry>& expectations) {
+ for (const auto& f : expectations) {
+ ps_name_set_.insert(f.postscript_name.Utf8());
+ full_name_set_.insert(f.full_name.Utf8());
+ family_set_.insert(f.family.Utf8());
+ }
+ }
+
+ void Consume(const std::vector<FontEnumerationEntry>& entries) {
+ for (auto f : entries) {
+ ps_name_set_.erase(f.postscript_name.Utf8());
+ full_name_set_.erase(f.full_name.Utf8());
+ family_set_.erase(f.family.Utf8());
+ }
+ }
+
+ bool AllExpectationsMet() {
+ return ps_name_set_.empty() && full_name_set_.empty() &&
+ family_set_.empty();
+ }
+
+ private:
+ std::set<std::string> ps_name_set_;
+ std::set<std::string> full_name_set_;
+ std::set<std::string> family_set_;
+};
+
+TEST(FontCache, EnumerateAvailableFonts) {
+ FontCache* font_cache = FontCache::GetFontCache();
+ ASSERT_TRUE(font_cache);
+
+ std::vector<FontEnumerationEntry> expectations;
+
+#if defined(OS_MACOSX)
+ expectations.push_back(FontEnumerationEntry{"Monaco", "Monaco", "Monaco"});
+ expectations.push_back(
+ FontEnumerationEntry{"Menlo-Regular", "Menlo Regular", "Menlo"});
+ expectations.push_back(
+ FontEnumerationEntry{"Menlo-Bold", "Menlo Bold", "Menlo"});
+ expectations.push_back(
+ FontEnumerationEntry{"Menlo-BoldItalic", "Menlo Bold Italic", "Menlo"});
+#endif
+
+ auto entries = font_cache->EnumerateAvailableFonts();
+ auto consumer = EnumerationConsumer(expectations);
+
+ consumer.Consume(entries);
+ ASSERT_TRUE(consumer.AllExpectationsMet());
+}
+
+TEST(FontCache, EnumerateAvailableFontsInvalidation) {
+ FontCache* font_cache = FontCache::GetFontCache();
+ ASSERT_TRUE(font_cache);
+
+ // Make sure we start at zero.
+ font_cache->Invalidate();
+ size_t zero = 0;
+ ASSERT_EQ(zero, font_cache->EnumerationCacheSizeForTesting());
+
+ // The cache gets populated.
+ size_t enum_size_1 = font_cache->EnumerateAvailableFonts().size();
+ ASSERT_EQ(enum_size_1, font_cache->EnumerationCacheSizeForTesting());
+
+ // Invalidation clears the cache.
+ font_cache->Invalidate();
+ ASSERT_EQ(zero, font_cache->EnumerationCacheSizeForTesting());
+
+ // The cache gets re-populated.
+ size_t enum_size_2 = font_cache->EnumerateAvailableFonts().size();
+ ASSERT_EQ(enum_size_1, enum_size_2);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc b/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
index ecc8454ff02..b00c9e9b10d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
@@ -45,16 +45,6 @@
namespace blink {
-namespace {
-sk_sp<SkFontMgr> FontManagerForSubType(
- FontFormatCheck::VariableFontSubType font_sub_type) {
- CHECK_NE(font_sub_type, FontFormatCheck::VariableFontSubType::kNotVariable);
- if (font_sub_type == FontFormatCheck::VariableFontSubType::kVariableCFF2)
- return WebFontTypefaceFactory::FreeTypeFontManager();
- return WebFontTypefaceFactory::FontManagerForVariations();
-}
-} // namespace
-
FontCustomPlatformData::FontCustomPlatformData(sk_sp<SkTypeface> typeface,
size_t data_size)
: base_typeface_(std::move(typeface)), data_size_(data_size) {}
@@ -97,9 +87,14 @@ FontPlatformData FontCustomPlatformData::GetFontPlatformData(
SkSetFourByteTag('w', 'd', 't', 'h'),
SkFloatToScalar(selection_capabilities.width.clampToRange(
selection_request.width))};
+ // CSS and OpenType have opposite definitions of direction of slant
+ // angle. In OpenType positive values turn counter-clockwise, negative
+ // values clockwise - in CSS positive values are clockwise rotations /
+ // skew. See note in https://drafts.csswg.org/css-fonts/#font-style-prop -
+ // map value from CSS to OpenType here.
SkFontArguments::Axis slant_axis = {
SkSetFourByteTag('s', 'l', 'n', 't'),
- SkFloatToScalar(selection_capabilities.slope.clampToRange(
+ SkFloatToScalar(-selection_capabilities.slope.clampToRange(
selection_request.slope))};
axes.push_back(weight_axis);
@@ -124,12 +119,8 @@ FontPlatformData FontCustomPlatformData::GetFontPlatformData(
axes.push_back(opsz_axis);
}
- int index;
- std::unique_ptr<SkStreamAsset> stream(base_typeface_->openStream(&index));
- sk_sp<SkTypeface> sk_variation_font(FontManagerForSubType(font_sub_type)
- ->makeFromStream(std::move(stream),
- SkFontArguments().setCollectionIndex(index)
- .setAxes(axes.data(), axes.size())));
+ sk_sp<SkTypeface> sk_variation_font(base_typeface_->makeClone(
+ SkFontArguments().setAxes(axes.data(), axes.size())));
if (sk_variation_font) {
return_typeface = sk_variation_font;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_data.h b/chromium/third_party/blink/renderer/platform/fonts/font_data.h
index 3535115d1e4..d79e7fd5a70 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_data.h
@@ -57,15 +57,6 @@ class PLATFORM_EXPORT FontData : public RefCounted<FontData> {
DISALLOW_COPY_AND_ASSIGN(FontData);
};
-#define DEFINE_FONT_DATA_TYPE_CASTS(thisType, predicate) \
- template <typename T> \
- inline thisType* To##thisType(const scoped_refptr<T>& fontData) { \
- return To##thisType(fontData.get()); \
- } \
- DEFINE_TYPE_CASTS(thisType, FontData, fontData, \
- fontData->IsSegmented() == predicate, \
- fontData.IsSegmented() == predicate)
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_DATA_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.cc b/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.cc
index 060207ea5e5..680da1679bd 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_data_cache.cc
@@ -132,7 +132,7 @@ bool FontDataCache::PurgeLeastRecentlyUsed(int count) {
auto end = inactive_font_data_.end();
auto it = inactive_font_data_.begin();
for (int i = 0; i < count && it != end; ++it, ++i) {
- scoped_refptr<SimpleFontData>& font_data = *it.Get();
+ const scoped_refptr<SimpleFontData>& font_data = *it;
cache_.erase(&(font_data->PlatformData()));
// We should not delete SimpleFontData here because deletion can modify
// m_inactiveFontData. See http://trac.webkit.org/changeset/44011
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
index 6f20525f341..9e3ffe63834 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -436,8 +436,6 @@ String FontDescription::ToString(GenericFamilyType familyType) {
return "Cursive";
case GenericFamilyType::kFantasyFamily:
return "Fantasy";
- case GenericFamilyType::kPictographFamily:
- return "Pictograph";
}
return "Unknown";
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description.h b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
index 8d19bd6873c..782b843707b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
@@ -63,8 +63,7 @@ class PLATFORM_EXPORT FontDescription {
kSansSerifFamily,
kMonospaceFamily,
kCursiveFamily,
- kFantasyFamily,
- kPictographFamily
+ kFantasyFamily
};
static String ToString(GenericFamilyType);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc
index 737580ef6bf..1bb413937f9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc
@@ -63,6 +63,78 @@ TEST(FontDescriptionTest, TestHashCollision) {
}
}
+TEST(FontDescriptionTest, VariationSettingsIdentical) {
+ FontDescription a;
+ FontDescription b(a);
+
+ scoped_refptr<FontVariationSettings> settings_a =
+ FontVariationSettings::Create();
+ settings_a->Append(FontVariationAxis("test", 1));
+
+ scoped_refptr<FontVariationSettings> settings_b =
+ FontVariationSettings::Create();
+ settings_b->Append(FontVariationAxis("test", 1));
+
+ ASSERT_EQ(*settings_a, *settings_b);
+
+ a.SetVariationSettings(settings_a);
+ b.SetVariationSettings(settings_b);
+
+ ASSERT_EQ(a, b);
+
+ FontFaceCreationParams test_creation_params;
+ FontCacheKey cache_key_a = a.CacheKey(test_creation_params, false);
+ FontCacheKey cache_key_b = b.CacheKey(test_creation_params, false);
+
+ ASSERT_EQ(cache_key_a, cache_key_b);
+}
+
+TEST(FontDescriptionTest, VariationSettingsDifferent) {
+ FontDescription a;
+ FontDescription b(a);
+
+ scoped_refptr<FontVariationSettings> settings_a =
+ FontVariationSettings::Create();
+ settings_a->Append(FontVariationAxis("test", 1));
+
+ scoped_refptr<FontVariationSettings> settings_b =
+ FontVariationSettings::Create();
+ settings_b->Append(FontVariationAxis("0000", 1));
+
+ ASSERT_NE(*settings_a, *settings_b);
+
+ a.SetVariationSettings(settings_a);
+ b.SetVariationSettings(settings_b);
+
+ ASSERT_NE(a, b);
+
+ FontFaceCreationParams test_creation_params;
+
+ FontCacheKey cache_key_a = a.CacheKey(test_creation_params, false);
+ FontCacheKey cache_key_b = b.CacheKey(test_creation_params, false);
+
+ ASSERT_NE(cache_key_a, cache_key_b);
+
+ scoped_refptr<FontVariationSettings> second_settings_a =
+ FontVariationSettings::Create();
+ second_settings_a->Append(FontVariationAxis("test", 1));
+
+ scoped_refptr<FontVariationSettings> second_settings_b =
+ FontVariationSettings::Create();
+
+ ASSERT_NE(*second_settings_a, *second_settings_b);
+
+ a.SetVariationSettings(second_settings_a);
+ b.SetVariationSettings(second_settings_b);
+
+ ASSERT_NE(a, b);
+
+ FontCacheKey second_cache_key_a = a.CacheKey(test_creation_params, false);
+ FontCacheKey second_cache_key_b = b.CacheKey(test_creation_params, false);
+
+ ASSERT_NE(second_cache_key_a, second_cache_key_b);
+}
+
TEST(FontDescriptionTest, ToString) {
FontDescription description;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
index 1362d480c4b..eb076725400 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
@@ -153,7 +153,7 @@ scoped_refptr<FontDataForRangeSet> FontFallbackIterator::Next(
current_font_data_index_++;
if (!font_data->IsLoading()) {
scoped_refptr<SimpleFontData> non_segmented =
- const_cast<SimpleFontData*>(ToSimpleFontData(font_data));
+ const_cast<SimpleFontData*>(To<SimpleFontData>(font_data));
// The fontData object that we have here is tracked in m_fontList of
// FontFallbackList and gets released in the font cache when the
// FontFallbackList is destroyed.
@@ -165,7 +165,7 @@ scoped_refptr<FontDataForRangeSet> FontFallbackIterator::Next(
// Iterate over ranges of a segmented font below.
- const SegmentedFontData* segmented = ToSegmentedFontData(font_data);
+ const auto* segmented = To<SegmentedFontData>(font_data);
if (fallback_stage_ != kSegmentedFace) {
segmented_face_index_ = 0;
fallback_stage_ = kSegmentedFace;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
index fa1a455e591..d00d18310bb 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
@@ -39,22 +39,24 @@
namespace blink {
-FontFallbackList::FontFallbackList()
+FontFallbackList::FontFallbackList(FontSelector* font_selector)
: cached_primary_simple_font_data_(nullptr),
- font_selector_(nullptr),
- font_selector_version_(0),
+ font_selector_(font_selector),
+ font_selector_version_(font_selector ? font_selector->Version() : 0),
family_index_(0),
generation_(FontCache::GetFontCache()->Generation()),
- has_loading_fallback_(false) {}
+ has_loading_fallback_(false),
+ can_shape_word_by_word_(false),
+ can_shape_word_by_word_computed_(false) {}
-void FontFallbackList::Invalidate(FontSelector* font_selector) {
+void FontFallbackList::Invalidate() {
ReleaseFontData();
font_list_.clear();
cached_primary_simple_font_data_ = nullptr;
family_index_ = 0;
has_loading_fallback_ = false;
- if (font_selector_ != font_selector)
- font_selector_ = font_selector;
+ can_shape_word_by_word_ = false;
+ can_shape_word_by_word_computed_ = false;
font_selector_version_ = font_selector_ ? font_selector_->Version() : 0;
generation_ = FontCache::GetFontCache()->Generation();
}
@@ -65,13 +67,18 @@ void FontFallbackList::ReleaseFontData() {
if (!font_list_[i]->IsCustomFont()) {
DCHECK(!font_list_[i]->IsSegmented());
FontCache::GetFontCache()->ReleaseFontData(
- ToSimpleFontData(font_list_[i]));
+ To<SimpleFontData>(font_list_[i].get()));
}
}
shape_cache_.reset(); // Clear the weak pointer to the cache instance.
}
bool FontFallbackList::LoadingCustomFonts() const {
+ // This function is only used for style and layout invalidation purposes. We
+ // don't need it for invalidation when the feature below is enabled.
+ if (RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled())
+ return false;
+
if (!has_loading_fallback_)
return false;
@@ -84,6 +91,8 @@ bool FontFallbackList::LoadingCustomFonts() const {
}
bool FontFallbackList::ShouldSkipDrawing() const {
+ DCHECK(IsValid());
+
if (!has_loading_fallback_)
return false;
@@ -96,7 +105,7 @@ bool FontFallbackList::ShouldSkipDrawing() const {
}
const SimpleFontData* FontFallbackList::DeterminePrimarySimpleFontData(
- const FontDescription& font_description) const {
+ const FontDescription& font_description) {
bool should_load_custom_font = true;
for (unsigned font_index = 0;; ++font_index) {
@@ -114,8 +123,8 @@ const SimpleFontData* FontFallbackList::DeterminePrimarySimpleFontData(
return last_resort_fallback;
}
- if (font_data->IsSegmented() &&
- !ToSegmentedFontData(font_data)->ContainsCharacter(kSpaceCharacter))
+ const auto* segmented = DynamicTo<SegmentedFontData>(font_data);
+ if (segmented && !segmented->ContainsCharacter(kSpaceCharacter))
continue;
const SimpleFontData* font_data_for_space =
@@ -128,8 +137,7 @@ const SimpleFontData* FontFallbackList::DeterminePrimarySimpleFontData(
if (!font_data_for_space->IsLoadingFallback())
return font_data_for_space;
- if (font_data->IsSegmented()) {
- const SegmentedFontData* segmented = ToSegmentedFontData(font_data);
+ if (segmented) {
for (unsigned i = 0; i < segmented->NumFaces(); i++) {
const SimpleFontData* range_font_data =
segmented->FaceAt(i)->FontData();
@@ -212,8 +220,9 @@ FallbackListCompositeKey FontFallbackList::CompositeKey(
if (result) {
bool is_unique_match = false;
key.Add(font_description.CacheKey(params, is_unique_match));
- if (!result->IsSegmented() && !result->IsCustomFont())
- FontCache::GetFontCache()->ReleaseFontData(ToSimpleFontData(result));
+ auto* font_data = DynamicTo<SimpleFontData>(result.get());
+ if (!font_data && !result->IsCustomFont())
+ FontCache::GetFontCache()->ReleaseFontData(font_data);
}
}
current_family = current_family->Next();
@@ -224,7 +233,12 @@ FallbackListCompositeKey FontFallbackList::CompositeKey(
const FontData* FontFallbackList::FontDataAt(
const FontDescription& font_description,
- unsigned realized_font_index) const {
+ unsigned realized_font_index) {
+ if (RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()) {
+ if (!IsValid())
+ Invalidate();
+ }
+
// This fallback font is already in our list.
if (realized_font_index < font_list_.size())
return font_list_[realized_font_index].get();
@@ -250,6 +264,34 @@ const FontData* FontFallbackList::FontDataAt(
return result.get();
}
+bool FontFallbackList::ComputeCanShapeWordByWord(
+ const FontDescription& font_description) {
+ if (!font_description.GetTypesettingFeatures())
+ return true;
+
+ const SimpleFontData* primary_font = PrimarySimpleFontData(font_description);
+ if (!primary_font)
+ return false;
+
+ const FontPlatformData& platform_data = primary_font->PlatformData();
+ TypesettingFeatures features = font_description.GetTypesettingFeatures();
+ return !platform_data.HasSpaceInLigaturesOrKerning(features);
+}
+
+bool FontFallbackList::CanShapeWordByWord(
+ const FontDescription& font_description) {
+ if (RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()) {
+ if (!IsValid())
+ Invalidate();
+ }
+
+ if (!can_shape_word_by_word_computed_) {
+ can_shape_word_by_word_ = ComputeCanShapeWordByWord(font_description);
+ can_shape_word_by_word_computed_ = true;
+ }
+ return can_shape_word_by_word_;
+}
+
bool FontFallbackList::IsValid() const {
if (!font_selector_)
return font_selector_version_ == 0;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h
index 4a604216015..6ef8c3774b8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.h
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -42,13 +43,13 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
USING_FAST_MALLOC(FontFallbackList);
public:
- static scoped_refptr<FontFallbackList> Create() {
- return base::AdoptRef(new FontFallbackList());
+ static scoped_refptr<FontFallbackList> Create(FontSelector* font_selector) {
+ return base::AdoptRef(new FontFallbackList(font_selector));
}
~FontFallbackList() { ReleaseFontData(); }
bool IsValid() const;
- void Invalidate(FontSelector*);
+ void Invalidate();
bool LoadingCustomFonts() const;
bool ShouldSkipDrawing() const;
@@ -58,7 +59,12 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
unsigned FontSelectorVersion() const { return font_selector_version_; }
uint16_t Generation() const { return generation_; }
- ShapeCache* GetShapeCache(const FontDescription& font_description) const {
+ ShapeCache* GetShapeCache(const FontDescription& font_description) {
+ if (RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()) {
+ if (!IsValid())
+ Invalidate();
+ }
+
if (!shape_cache_) {
FallbackListCompositeKey key = CompositeKey(font_description);
shape_cache_ =
@@ -72,6 +78,11 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
const SimpleFontData* PrimarySimpleFontData(
const FontDescription& font_description) {
+ if (RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()) {
+ if (!IsValid())
+ Invalidate();
+ }
+
if (!cached_primary_simple_font_data_) {
cached_primary_simple_font_data_ =
DeterminePrimarySimpleFontData(font_description);
@@ -79,28 +90,37 @@ class PLATFORM_EXPORT FontFallbackList : public RefCounted<FontFallbackList> {
}
return cached_primary_simple_font_data_;
}
- const FontData* FontDataAt(const FontDescription&, unsigned index) const;
+ const FontData* FontDataAt(const FontDescription&, unsigned index);
- FallbackListCompositeKey CompositeKey(const FontDescription&) const;
+ bool CanShapeWordByWord(const FontDescription&);
+
+ void SetCanShapeWordByWordForTesting(bool b) {
+ can_shape_word_by_word_ = b;
+ can_shape_word_by_word_computed_ = true;
+ }
private:
- FontFallbackList();
+ explicit FontFallbackList(FontSelector* font_selector);
scoped_refptr<FontData> GetFontData(const FontDescription&, int& family_index) const;
- const SimpleFontData* DeterminePrimarySimpleFontData(
- const FontDescription&) const;
+ const SimpleFontData* DeterminePrimarySimpleFontData(const FontDescription&);
+
+ FallbackListCompositeKey CompositeKey(const FontDescription&) const;
void ReleaseFontData();
+ bool ComputeCanShapeWordByWord(const FontDescription&);
- mutable Vector<scoped_refptr<FontData>, 1> font_list_;
- mutable const SimpleFontData* cached_primary_simple_font_data_;
- Persistent<FontSelector> font_selector_;
+ Vector<scoped_refptr<FontData>, 1> font_list_;
+ const SimpleFontData* cached_primary_simple_font_data_;
+ const Persistent<FontSelector> font_selector_;
unsigned font_selector_version_;
- mutable int family_index_;
+ int family_index_;
uint16_t generation_;
- mutable bool has_loading_fallback_ : 1;
- mutable base::WeakPtr<ShapeCache> shape_cache_;
+ bool has_loading_fallback_ : 1;
+ bool can_shape_word_by_word_ : 1;
+ bool can_shape_word_by_word_computed_ : 1;
+ base::WeakPtr<ShapeCache> shape_cache_;
DISALLOW_COPY_AND_ASSIGN(FontFallbackList);
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc
index ff2fd249e6c..ee1cb3b220c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc
@@ -20,7 +20,9 @@ FontGlobalContext* FontGlobalContext::Get(CreateIfNeeded create_if_needed) {
return *font_persistent;
}
-FontGlobalContext::FontGlobalContext() : harfbuzz_font_funcs_(nullptr) {}
+FontGlobalContext::FontGlobalContext()
+ : harfbuzz_font_funcs_skia_advances_(nullptr),
+ harfbuzz_font_funcs_harfbuzz_advances_(nullptr) {}
FontGlobalContext::~FontGlobalContext() = default;
@@ -32,6 +34,15 @@ FontUniqueNameLookup* FontGlobalContext::GetFontUniqueNameLookup() {
return Get()->font_unique_name_lookup_.get();
}
+HarfBuzzFontCache* FontGlobalContext::GetHarfBuzzFontCache() {
+ std::unique_ptr<HarfBuzzFontCache>& global_context_harfbuzz_font_cache =
+ Get()->harfbuzz_font_cache_;
+ if (!global_context_harfbuzz_font_cache) {
+ global_context_harfbuzz_font_cache = std::make_unique<HarfBuzzFontCache>();
+ }
+ return global_context_harfbuzz_font_cache.get();
+}
+
void FontGlobalContext::ClearMemory() {
if (!Get(kDoNotCreate))
return;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h
index 63c3c861d6e..37e743c2264 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_GLOBAL_CONTEXT_H_
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/layout_locale.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -17,6 +16,7 @@ namespace blink {
class FontCache;
class FontUniqueNameLookup;
+class HarfBuzzFontCache;
enum CreateIfNeeded { kDoNotCreate, kCreate };
@@ -30,16 +30,27 @@ class PLATFORM_EXPORT FontGlobalContext {
static inline FontCache& GetFontCache() { return Get()->font_cache_; }
- static inline HarfBuzzFontCache& GetHarfBuzzFontCache() {
- return Get()->harfbuzz_font_cache_;
- }
+ static HarfBuzzFontCache* GetHarfBuzzFontCache();
+
+ enum HorizontalAdvanceSource {
+ kSkiaHorizontalAdvances,
+ kHarfBuzzHorizontalAdvances
+ };
- static hb_font_funcs_t* GetHarfBuzzFontFuncs() {
- return Get()->harfbuzz_font_funcs_;
+ static hb_font_funcs_t* GetHarfBuzzFontFuncs(
+ HorizontalAdvanceSource advance_source) {
+ if (advance_source == kHarfBuzzHorizontalAdvances) {
+ return Get()->harfbuzz_font_funcs_harfbuzz_advances_;
+ }
+ return Get()->harfbuzz_font_funcs_skia_advances_;
}
- static void SetHarfBuzzFontFuncs(hb_font_funcs_t* funcs) {
- Get()->harfbuzz_font_funcs_ = funcs;
+ static void SetHarfBuzzFontFuncs(HorizontalAdvanceSource advance_source,
+ hb_font_funcs_t* funcs) {
+ if (advance_source == kHarfBuzzHorizontalAdvances) {
+ Get()->harfbuzz_font_funcs_harfbuzz_advances_ = funcs;
+ }
+ Get()->harfbuzz_font_funcs_skia_advances_ = funcs;
}
static FontUniqueNameLookup* GetFontUniqueNameLookup();
@@ -54,8 +65,9 @@ class PLATFORM_EXPORT FontGlobalContext {
~FontGlobalContext();
FontCache font_cache_;
- HarfBuzzFontCache harfbuzz_font_cache_;
- hb_font_funcs_t* harfbuzz_font_funcs_;
+ std::unique_ptr<HarfBuzzFontCache> harfbuzz_font_cache_;
+ hb_font_funcs_t* harfbuzz_font_funcs_skia_advances_;
+ hb_font_funcs_t* harfbuzz_font_funcs_harfbuzz_advances_;
std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
DISALLOW_COPY_AND_ASSIGN(FontGlobalContext);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc b/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
index 5e1005a2e4d..a9a0511de03 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
@@ -28,6 +28,18 @@ HashSet<T> Intersection(const HashSet<T>& a, const HashSet<T>& b) {
namespace blink {
+FontMatchingMetrics::FontMatchingMetrics(bool top_level,
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id)
+ : top_level_(top_level),
+ ukm_recorder_(ukm_recorder),
+ source_id_(source_id) {
+ // Estimate of average page font use from anecdotal browsing session.
+ constexpr unsigned kEstimatedFontCount = 7;
+ local_fonts_succeeded_.ReserveCapacityForSize(kEstimatedFontCount);
+ local_fonts_failed_.ReserveCapacityForSize(kEstimatedFontCount);
+}
+
void FontMatchingMetrics::ReportSuccessfulFontFamilyMatch(
const AtomicString& font_family_name) {
successful_font_families_.insert(font_family_name);
@@ -48,6 +60,16 @@ void FontMatchingMetrics::ReportWebFontFamily(
web_font_families_.insert(font_family_name);
}
+void FontMatchingMetrics::ReportSuccessfulLocalFontMatch(
+ const AtomicString& font_name) {
+ local_fonts_succeeded_.insert(font_name);
+}
+
+void FontMatchingMetrics::ReportFailedLocalFontMatch(
+ const AtomicString& font_name) {
+ local_fonts_failed_.insert(font_name);
+}
+
void FontMatchingMetrics::PublishUkmMetrics() {
ukm::builders::FontMatchAttempts(source_id_)
.SetLoadContext(top_level_ ? kTopLevel : kSubFrame)
@@ -63,6 +85,10 @@ void FontMatchingMetrics::PublishUkmMetrics() {
.SetWebFontFamilyFailures(ukm::GetExponentialBucketMin(
Intersection(failed_font_families_, web_font_families_).size(),
kUkmFontLoadCountBucketSpacing))
+ .SetLocalFontFailures(ukm::GetExponentialBucketMin(
+ local_fonts_failed_.size(), kUkmFontLoadCountBucketSpacing))
+ .SetLocalFontSuccesses(ukm::GetExponentialBucketMin(
+ local_fonts_succeeded_.size(), kUkmFontLoadCountBucketSpacing))
.Record(ukm_recorder_);
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.h b/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
index c31be1c51b5..59827c38e53 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
@@ -27,10 +27,7 @@ class PLATFORM_EXPORT FontMatchingMetrics {
public:
FontMatchingMetrics(bool top_level,
ukm::UkmRecorder* ukm_recorder,
- ukm::SourceId source_id)
- : top_level_(top_level),
- ukm_recorder_(ukm_recorder),
- source_id_(source_id) {}
+ ukm::SourceId source_id);
// Called when a page attempts to match a font family, and the font family is
// available.
@@ -46,6 +43,14 @@ class PLATFORM_EXPORT FontMatchingMetrics {
// Called when a page attempts to match a web font family.
void ReportWebFontFamily(const AtomicString& font_family_name);
+ // Reports a font listed in a @font-face src:local rule that successfully
+ // matched.
+ void ReportSuccessfulLocalFontMatch(const AtomicString& font_name);
+
+ // Reports a font listed in a @font-face src:local rule that didn't
+ // successfully match.
+ void ReportFailedLocalFontMatch(const AtomicString& font_name);
+
// Publishes the number of font family matches attempted (both successful and
// otherwise) to UKM. Called at page unload.
void PublishUkmMetrics();
@@ -63,6 +68,12 @@ class PLATFORM_EXPORT FontMatchingMetrics {
// Web font families the page attempted to match.
HashSet<AtomicString> web_font_families_;
+ // @font-face src:local fonts that successfully matched.
+ HashSet<AtomicString> local_fonts_succeeded_;
+
+ // @font-face src:local fonts that didn't successfully match.
+ HashSet<AtomicString> local_fonts_failed_;
+
// True if this FontMatchingMetrics instance is for a top-level frame, false
// otherwise.
const bool top_level_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selector.h b/chromium/third_party/blink/renderer/platform/fonts/font_selector.h
index 0eaaf9e94fb..0861e6e15c8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_selector.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_selector.h
@@ -71,6 +71,15 @@ class PLATFORM_EXPORT FontSelector : public FontCacheClient {
virtual void ReportFailedFontFamilyMatch(
const AtomicString& font_family_name) = 0;
+ // Called when a page attempts to match a font name via a @font-face src:local
+ // rule, and the font is available.
+ virtual void ReportSuccessfulLocalFontMatch(
+ const AtomicString& font_name) = 0;
+
+ // Called when a page attempts to match a font name via a @font-face src:local
+ // rule, and the font is not available.
+ virtual void ReportFailedLocalFontMatch(const AtomicString& font_name) = 0;
+
virtual void RegisterForInvalidationCallbacks(FontSelectorClient*) = 0;
virtual void UnregisterForInvalidationCallbacks(FontSelectorClient*) = 0;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selector_client.h b/chromium/third_party/blink/renderer/platform/fonts/font_selector_client.h
index 649b054fb68..b85832903ab 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_selector_client.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_selector_client.h
@@ -17,7 +17,7 @@ class FontSelectorClient : public GarbageCollectedMixin {
virtual void FontsNeedUpdate(FontSelector*) = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc b/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc
index 62d92b7f412..604a895c075 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc
@@ -19,7 +19,6 @@ sk_sp<SkTypeface> FontUniqueNameLookupLinux::MatchUniqueName(
if (!Platform::Current()->GetSandboxSupport()) {
LOG(ERROR) << "@font-face src: local() instantiation only available when "
"connected to browser process.";
- DCHECK(Platform::Current()->GetSandboxSupport());
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h b/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h
index 1816f6f49d7..b5f3ffe9738 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h
@@ -9,6 +9,7 @@ namespace blink {
bool CoreTextVersionSupportsVariations();
bool CoreTextVersionSupportsColrCpal();
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_MAC_CORE_TEXT_FONT_FORMAT_SUPPORT_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
index f50fc36281d..fedd1b91424 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
@@ -29,8 +29,11 @@
#import "third_party/blink/renderer/platform/fonts/font_cache.h"
-#import <AppKit/AppKit.h>
#include <memory>
+
+#import <AppKit/AppKit.h>
+#import <CoreText/CoreText.h>
+
#include "base/location.h"
#include "base/mac/foundation_util.h"
#include "third_party/blink/public/platform/platform.h"
@@ -59,6 +62,22 @@
inLanguage:(id)useNil;
@end
+namespace {
+
+NSString* GetLocalizedString(CTFontDescriptorRef fd, CFStringRef attribute) {
+ base::ScopedCFTypeRef<CFStringRef> cf_str(base::mac::CFCast<CFStringRef>(
+ CTFontDescriptorCopyLocalizedAttribute(fd, attribute, nullptr)));
+ return [base::mac::CFToNSCast(cf_str.release()) autorelease];
+}
+
+NSString* GetString(CTFontDescriptorRef fd, CFStringRef attribute) {
+ base::ScopedCFTypeRef<CFStringRef> cf_str(base::mac::CFCast<CFStringRef>(
+ CTFontDescriptorCopyAttribute(fd, attribute)));
+ return [base::mac::CFToNSCast(cf_str.release()) autorelease];
+}
+
+} // namespace
+
namespace blink {
const char kColorEmojiFontMac[] = "Apple Color Emoji";
@@ -221,9 +240,12 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
substitute_font, platform_data.size(), synthetic_bold,
(traits & NSFontItalicTrait) &&
!(substitute_font_traits & NSFontItalicTrait),
- platform_data.Orientation(),
+ platform_data.Orientation(), font_description.FontOpticalSizing(),
nullptr); // No variation paramaters in fallback.
+ if (!alternate_font)
+ return nullptr;
+
return FontDataFromFontPlatformData(alternate_font.get(), kDoNotRetain);
}
@@ -295,11 +317,43 @@ std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData(
// the returned FontPlatformData since it will not have a valid SkTypeface.
std::unique_ptr<FontPlatformData> platform_data = FontPlatformDataFromNSFont(
platform_font, size, synthetic_bold, synthetic_italic,
- font_description.Orientation(), font_description.VariationSettings());
- if (!platform_data->Typeface()) {
+ font_description.Orientation(), font_description.FontOpticalSizing(),
+ font_description.VariationSettings());
+ if (!platform_data || !platform_data->Typeface()) {
return nullptr;
}
return platform_data;
}
+std::vector<FontEnumerationEntry> FontCache::EnumeratePlatformAvailableFonts() {
+ DCHECK(RuntimeEnabledFeatures::FontAccessEnabled());
+ @autoreleasepool {
+ std::vector<FontEnumerationEntry> output;
+
+ CFTypeRef values[1] = {kCFBooleanTrue};
+ base::ScopedCFTypeRef<CFDictionaryRef> options(CFDictionaryCreate(
+ kCFAllocatorDefault,
+ (const void**)kCTFontCollectionRemoveDuplicatesOption,
+ (const void**)&values,
+ /*numValues=*/1, &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ base::ScopedCFTypeRef<CTFontCollectionRef> collection(
+ CTFontCollectionCreateFromAvailableFonts(options));
+
+ base::ScopedCFTypeRef<CFArrayRef> font_descs(
+ CTFontCollectionCreateMatchingFontDescriptors(collection));
+
+ for (CFIndex i = 0; i < CFArrayGetCount(font_descs); ++i) {
+ CTFontDescriptorRef fd = base::mac::CFCast<CTFontDescriptorRef>(
+ CFArrayGetValueAtIndex(font_descs, i));
+ NSString* postscript_name = GetString(fd, kCTFontNameAttribute);
+ NSString* full_name = GetLocalizedString(fd, kCTFontDisplayNameAttribute);
+ NSString* family = GetLocalizedString(fd, kCTFontFamilyNameAttribute);
+ output.push_back(FontEnumerationEntry{String(postscript_name),
+ String(full_name), String(family)});
+ }
+ return output;
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
index 8d01704041c..cf25ba022f2 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
@@ -46,7 +46,7 @@
namespace {
-static CGFloat toYosemiteFontWeight(blink::FontSelectionValue font_weight) {
+static CGFloat toFontWeight(blink::FontSelectionValue font_weight) {
static uint64_t ns_font_weights[] = {
0xbfe99999a0000000, // NSFontWeightUltraLight
0xbfe3333340000000, // NSFontWeightThin
@@ -181,8 +181,7 @@ NSFont* MatchNSFontFamily(const AtomicString& desired_family_string,
// On OSX 10.10+, the default system font has more weights.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
- font = [NSFont systemFontOfSize:size
- weight:toYosemiteFontWeight(desired_weight)];
+ font = [NSFont systemFontOfSize:size weight:toFontWeight(desired_weight)];
#pragma clang diagnostic pop
if (desired_traits & IMPORTANT_FONT_TRAITS)
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
index b1224beff2c..cd0e338cdb5 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
@@ -31,6 +31,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_MAC_FONT_PLATFORM_DATA_MAC_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_MAC_FONT_PLATFORM_DATA_MAC_H_
+#include "third_party/blink/renderer/platform/fonts/font_optical_sizing.h"
+
#include <memory>
@class NSFont;
@@ -47,6 +49,7 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
bool synthetic_bold,
bool synthetic_italic,
FontOrientation,
+ OpticalSizing,
FontVariationSettings*);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
index 16bcce4ba40..9bc59e46e5e 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
@@ -27,21 +27,26 @@
#import <AvailabilityMacros.h>
#include "base/mac/foundation_util.h"
-#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
#include "base/stl_util.h"
#import "third_party/blink/public/platform/mac/web_sandbox_support.h"
#import "third_party/blink/public/platform/platform.h"
#import "third_party/blink/renderer/platform/fonts/font.h"
#import "third_party/blink/renderer/platform/fonts/font_platform_data.h"
+#import "third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h"
#import "third_party/blink/renderer/platform/fonts/opentype/font_settings.h"
#import "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
#import "third_party/blink/renderer/platform/web_test_support.h"
#import "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#import "third_party/skia/include/core/SkFont.h"
#import "third_party/skia/include/core/SkStream.h"
+#import "third_party/skia/include/core/SkTypes.h"
#import "third_party/skia/include/ports/SkTypeface_mac.h"
+namespace {
+constexpr SkFourByteTag kOpszTag = SkSetFourByteTag('o', 'p', 's', 'z');
+}
+
namespace blink {
static bool CanLoadInProcess(NSFont* ns_font) {
@@ -53,10 +58,10 @@ static bool CanLoadInProcess(NSFont* ns_font) {
return ![font_name isEqualToString:@"LastResort"];
}
-static CTFontDescriptorRef CascadeToLastResortFontDescriptor() {
- static CTFontDescriptorRef descriptor;
- if (descriptor)
- return descriptor;
+static CFDictionaryRef CascadeToLastResortFontAttributes() {
+ static CFDictionaryRef attributes;
+ if (attributes)
+ return attributes;
base::ScopedCFTypeRef<CTFontDescriptorRef> last_resort(
CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0));
@@ -67,13 +72,10 @@ static CTFontDescriptorRef CascadeToLastResortFontDescriptor() {
const void* keys[] = {kCTFontCascadeListAttribute};
const void* values[] = {values_array};
- base::ScopedCFTypeRef<CFDictionaryRef> attributes(CFDictionaryCreate(
+ attributes = CFDictionaryCreate(
kCFAllocatorDefault, keys, values, base::size(keys),
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-
- descriptor = CTFontDescriptorCreateWithAttributes(attributes);
-
- return descriptor;
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ return attributes;
}
static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font,
@@ -88,20 +90,23 @@ static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font,
return nullptr;
}
- CGFontRef loaded_cg_font;
+ base::ScopedCFTypeRef<CTFontDescriptorRef> loaded_data_descriptor;
uint32_t font_id;
if (!sandbox_support->LoadFont(base::mac::NSToCFCast(ns_font),
- &loaded_cg_font, &font_id)) {
+ &loaded_data_descriptor, &font_id)) {
// TODO crbug.com/461279: Make this appear in the inspector console?
DLOG(ERROR)
<< "Loading user font \"" << [[ns_font familyName] UTF8String]
<< "\" from non system location failed. Corrupt or missing font file?";
return nullptr;
}
- base::ScopedCFTypeRef<CGFontRef> cg_font(loaded_cg_font);
- base::ScopedCFTypeRef<CTFontRef> ct_font(CTFontCreateWithGraphicsFont(
- cg_font, text_size, 0, CascadeToLastResortFontDescriptor()));
- sk_sp<SkTypeface> return_font(SkCreateTypefaceFromCTFont(ct_font, cg_font));
+
+ base::ScopedCFTypeRef<CTFontDescriptorRef> data_descriptor_with_cascade(
+ CTFontDescriptorCreateCopyWithAttributes(
+ loaded_data_descriptor, CascadeToLastResortFontAttributes()));
+ base::ScopedCFTypeRef<CTFontRef> ct_font(CTFontCreateWithFontDescriptor(
+ data_descriptor_with_cascade.get(), text_size, 0));
+ sk_sp<SkTypeface> return_font = SkMakeTypefaceFromCTFont(ct_font);
if (!return_font.get())
// TODO crbug.com/461279: Make this appear in the inspector console?
@@ -117,11 +122,12 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
bool synthetic_bold,
bool synthetic_italic,
FontOrientation orientation,
+ OpticalSizing optical_sizing,
FontVariationSettings* variation_settings) {
DCHECK(ns_font);
sk_sp<SkTypeface> typeface;
if (CanLoadInProcess(ns_font)) {
- typeface.reset(SkCreateTypefaceFromCTFont(base::mac::NSToCFCast(ns_font)));
+ typeface = SkMakeTypefaceFromCTFont(base::mac::NSToCFCast(ns_font));
} else {
// In process loading fails for cases where third party font manager
// software registers fonts in non system locations such as /Library/Fonts
@@ -129,26 +135,79 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont(
typeface = LoadFromBrowserProcess(ns_font, size);
}
- if (variation_settings && variation_settings->size() < UINT16_MAX) {
- SkFontArguments::Axis axes[variation_settings->size()];
- for (size_t i = 0; i < variation_settings->size(); ++i) {
- AtomicString feature_tag = variation_settings->at(i).Tag();
- axes[i] = {AtomicStringToFourByteTag(feature_tag),
- SkFloatToScalar(variation_settings->at(i).Value())};
+ auto make_typeface_fontplatformdata = [&typeface, &size, &synthetic_bold,
+ &synthetic_italic, &orientation]() {
+ return std::make_unique<FontPlatformData>(
+ std::move(typeface), std::string(), size, synthetic_bold,
+ synthetic_italic, orientation);
+ };
+
+ wtf_size_t valid_configured_axes =
+ variation_settings && variation_settings->size() < UINT16_MAX
+ ? variation_settings->size()
+ : 0;
+
+ // No variable font requested, return static font.
+ if (!valid_configured_axes && optical_sizing == kNoneOpticalSizing)
+ return make_typeface_fontplatformdata();
+
+ if (!typeface)
+ return nullptr;
+
+ int existing_axes = typeface->getVariationDesignPosition(nullptr, 0);
+ // Don't apply variation parameters if the font does not have axes or we
+ // fail to retrieve the existing ones.
+ if (existing_axes <= 0)
+ return make_typeface_fontplatformdata();
+
+ Vector<SkFontArguments::VariationPosition::Coordinate> coordinates_to_set;
+ coordinates_to_set.resize(existing_axes);
+
+ if (typeface->getVariationDesignPosition(coordinates_to_set.data(),
+ existing_axes) != existing_axes) {
+ return make_typeface_fontplatformdata();
+ }
+
+ // Iterate over the font's axes and find a missing tag from variation
+ // settings, special case opsz, track the number of axes reconfigured.
+ bool axes_reconfigured = false;
+ for (auto& coordinate : coordinates_to_set) {
+ // Set opsz to font size but allow having it overriden by
+ // font-variation-settings in case it has 'opsz'.
+ if (coordinate.axis == kOpszTag && optical_sizing == kAutoOpticalSizing) {
+ if (coordinate.value != SkFloatToScalar(size)) {
+ coordinate.value = SkFloatToScalar(size);
+ axes_reconfigured = true;
+ }
+ }
+ FontVariationAxis found_variation_setting(AtomicString(), 0);
+ if (variation_settings &&
+ variation_settings->FindPair(FourByteTagToAtomicString(coordinate.axis),
+ &found_variation_setting)) {
+ if (coordinate.value != found_variation_setting.Value()) {
+ coordinate.value = found_variation_setting.Value();
+ axes_reconfigured = true;
+ }
}
- sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- // TODO crbug.com/670246: Refactor this to a future Skia API that acccepts
- // axis parameters on system fonts directly.
- typeface = fm->makeFromStream(
- typeface->openStream(nullptr)->duplicate(),
- SkFontArguments().setAxes(axes, variation_settings->size()));
}
- return std::make_unique<FontPlatformData>(
- std::move(typeface),
- std::string(), // family_ doesn't exist on Mac, this avoids conversion
- // from NSString which requires including a //base header
- size, synthetic_bold, synthetic_italic, orientation);
+ if (!axes_reconfigured) {
+ // No variable axes touched, return the previous typeface.
+ return make_typeface_fontplatformdata();
+ }
+
+ SkFontArguments::VariationPosition variation_design_position{
+ coordinates_to_set.data(), coordinates_to_set.size()};
+
+ sk_sp<SkTypeface> cloned_typeface(typeface->makeClone(
+ SkFontArguments().setVariationDesignPosition(variation_design_position)));
+
+ if (!cloned_typeface) {
+ // Applying varition parameters failed, return original typeface.
+ return make_typeface_fontplatformdata();
+ }
+ typeface = cloned_typeface;
+ return make_typeface_fontplatformdata();
}
void FontPlatformData::SetupSkFont(SkFont* skfont,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc
index 964943fa0b2..2c11652ffcf 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc
@@ -4,32 +4,21 @@
#include "third_party/blink/renderer/platform/fonts/opentype/font_format_check.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/include/core/SkTypeface.h"
-
// Include HarfBuzz to have a cross-platform way to retrieve table tags without
// having to rely on the platform being able to instantiate this font format.
#include <hb.h>
-namespace blink {
-
-namespace {
-
-struct HarfbuzzBlobDestroyer {
- inline void operator()(hb_blob_t* blob) { hb_blob_destroy(blob); }
-};
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/harfbuzz-ng/utils/hb_scoped.h"
+#include "third_party/skia/include/core/SkTypeface.h"
-struct HarfbuzzFaceDestroyer {
- inline void operator()(hb_face_t* face) { hb_face_destroy(face); }
-};
-} // namespace
+namespace blink {
FontFormatCheck::FontFormatCheck(sk_sp<SkData> sk_data) {
- std::unique_ptr<hb_blob_t, HarfbuzzBlobDestroyer> font_blob(hb_blob_create(
+ HbScoped<hb_blob_t> font_blob(hb_blob_create(
reinterpret_cast<const char*>(sk_data->bytes()), sk_data->size(),
HB_MEMORY_MODE_READONLY, nullptr, nullptr));
- std::unique_ptr<hb_face_t, HarfbuzzFaceDestroyer> face(
- hb_face_create(font_blob.get(), 0));
+ HbScoped<hb_face_t> face(hb_face_create(font_blob.get(), 0));
unsigned table_count = 0;
table_count = hb_face_get_table_tags(face.get(), 0, nullptr, nullptr);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc
index 733d76d0db4..84c34be7a02 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/fonts/opentype/font_settings.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
@@ -16,6 +17,13 @@ uint32_t AtomicStringToFourByteTag(AtomicString tag) {
return (((tag[0]) << 24) | ((tag[1]) << 16) | ((tag[2]) << 8) | (tag[3]));
}
+AtomicString FourByteTagToAtomicString(uint32_t tag) {
+ constexpr size_t tag_size = 4;
+ LChar tag_string[tag_size] = {(tag >> 24) & 0xFF, (tag >> 16) & 0xFF,
+ (tag >> 8) & 0xFF, tag & 0xFF};
+ return AtomicString(tag_string, tag_size);
+}
+
unsigned FontVariationSettings::GetHash() const {
unsigned computed_hash = size() ? 5381 : 0;
unsigned num_features = size();
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h
index 10ab2aec21e..ea5b8c942f8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings.h
@@ -17,6 +17,7 @@
namespace blink {
uint32_t AtomicStringToFourByteTag(AtomicString tag);
+AtomicString FourByteTagToAtomicString(uint32_t tag);
template <typename T>
class FontTagValuePair {
@@ -34,7 +35,7 @@ class FontTagValuePair {
private:
AtomicString tag_;
- const T value_;
+ T value_;
};
template <typename T>
@@ -47,6 +48,7 @@ class FontSettings {
bool operator==(const FontSettings& other) const {
return list_ == other.list_;
}
+ bool operator!=(const FontSettings& other) const { return !(*this == other); }
String ToString() const {
StringBuilder builder;
wtf_size_t num_features = size();
@@ -60,6 +62,20 @@ class FontSettings {
}
return builder.ToString();
}
+
+ bool FindPair(AtomicString tag, T* found_pair) const {
+ if (!found_pair)
+ return false;
+
+ for (auto& pair : list_) {
+ if (pair.Tag() == tag) {
+ *found_pair = pair;
+ return true;
+ }
+ }
+ return false;
+ }
+
const T* begin() const { return list_.begin(); }
const T* end() const { return list_.end(); }
T* begin() { return list_.begin(); }
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings_test.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings_test.cc
index 5c2fa7d94e8..6a3e0457ac3 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/font_settings_test.cc
@@ -61,4 +61,30 @@ TEST(FontSettingsTest, ToString) {
}
}
+TEST(FontSettingsTest, FindTest) {
+ {
+ scoped_refptr<FontVariationSettings> settings =
+ MakeSettings<FontVariationSettings, FontVariationAxis>(
+ {FontVariationAxis{"a", 42}, FontVariationAxis{"b", 8118}});
+ FontVariationAxis found_axis(AtomicString(), 0);
+ ASSERT_FALSE(settings->FindPair("c", &found_axis));
+ ASSERT_FALSE(settings->FindPair("ddddd", &found_axis));
+ ASSERT_FALSE(settings->FindPair("", &found_axis));
+ ASSERT_EQ(found_axis.Value(), 0);
+ ASSERT_TRUE(settings->FindPair("a", &found_axis));
+ ASSERT_EQ(found_axis.Tag(), AtomicString("a"));
+ ASSERT_EQ(found_axis.Value(), 42);
+ ASSERT_TRUE(settings->FindPair("b", &found_axis));
+ ASSERT_EQ(found_axis.Tag(), AtomicString("b"));
+ ASSERT_EQ(found_axis.Value(), 8118);
+ }
+}
+
+TEST(FontSettingsTest, FindTestEmpty) {
+ scoped_refptr<FontVariationSettings> settings =
+ MakeSettings<FontVariationSettings, FontVariationAxis>({});
+ FontVariationAxis found_axis(AtomicString(), 0);
+ ASSERT_FALSE(settings->FindPair("a", &found_axis));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc
index 4c18c37138f..542975a52ba 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc
@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
-
-#include <hb-aat.h>
+// clang-format off
#include <hb.h>
+#include <hb-aat.h>
+// clang-format on
+
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
+#include "third_party/harfbuzz-ng/utils/hb_scoped.h"
namespace blink {
@@ -138,12 +141,10 @@ OpenTypeCapsSupport::FontFormat OpenTypeCapsSupport::GetFontFormat() const {
hb_face_t* hb_face = hb_font_get_face(
harfbuzz_face_->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout));
- std::unique_ptr<hb_blob_t, decltype(&hb_blob_destroy)> morx_blob(
- hb_face_reference_table(hb_face, HB_TAG('m', 'o', 'r', 'x')),
- hb_blob_destroy);
- std::unique_ptr<hb_blob_t, decltype(&hb_blob_destroy)> mort_blob(
- hb_face_reference_table(hb_face, HB_TAG('m', 'o', 'r', 't')),
- hb_blob_destroy);
+ HbScoped<hb_blob_t> morx_blob(
+ hb_face_reference_table(hb_face, HB_TAG('m', 'o', 'r', 'x')));
+ HbScoped<hb_blob_t> mort_blob(
+ hb_face_reference_table(hb_face, HB_TAG('m', 'o', 'r', 't')));
// TODO(crbug.com/911149): Use hb_aat_layout_has_substitution() for
// has_morx_or_mort and hb_ot_layout_has_substitution() for has_gsub once is
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h
new file mode 100644
index 00000000000..af3cc059903
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h
@@ -0,0 +1,45 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_STRETCH_DATA_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_STRETCH_DATA_H_
+
+#include "base/optional.h"
+#include "third_party/blink/renderer/platform/fonts/glyph.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT OpenTypeMathStretchData {
+ public:
+ enum StretchAxis : uint8_t { Horizontal = 0, Vertical = 1 };
+
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathGlyphVariantRecordFormat
+ // Note: Only variantGlyph is considered as using advanceMeasurement can lead
+ // to inconsistent values compared to what SimpleFontData returns.
+ using GlyphVariantRecord = Glyph;
+
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#glyphPartRecord
+ struct GlyphPartRecord {
+ Glyph glyph;
+ float start_connector_length;
+ float end_connector_length;
+ float full_advance;
+ bool is_extender;
+ };
+
+ // https://mathml-refresh.github.io/mathml-core/#the-glyphassembly-table
+ struct AssemblyParameters {
+ float connector_overlap{0};
+ unsigned repetition_count{0};
+ unsigned glyph_count{0};
+ float stretch_size{0};
+ Vector<GlyphPartRecord> parts;
+ };
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_STRETCH_DATA_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc
new file mode 100644
index 00000000000..80d94665ab7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.cc
@@ -0,0 +1,258 @@
+// 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 "third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h"
+
+// clang-format off
+#include <hb.h>
+#include <hb-ot.h>
+// clang-format on
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
+
+namespace {
+// HarfBuzz' hb_position_t is a 16.16 fixed-point value.
+float HarfBuzzUnitsToFloat(hb_position_t value) {
+ static const float kFloatToHbRatio = 1.0f / (1 << 16);
+ return kFloatToHbRatio * value;
+}
+
+// Latin Modern, STIX Two, XITS, Asana, Deja Vu, Libertinus and TeX Gyre fonts
+// provide at most 13 size variant and 5 assembly parts.
+// See https://chromium-review.googlesource.com/c/chromium/src/+/2074678
+unsigned kMaxHarfBuzzRecords = 20;
+
+hb_direction_t HarfBuzzDirection(
+ blink::OpenTypeMathStretchData::StretchAxis stretch_axis) {
+ return stretch_axis == blink::OpenTypeMathStretchData::StretchAxis::Horizontal
+ ? HB_DIRECTION_LTR
+ : HB_DIRECTION_BTT;
+}
+
+} // namespace
+
+namespace blink {
+
+bool OpenTypeMathSupport::HasMathData(const HarfBuzzFace* harfbuzz_face) {
+ if (!harfbuzz_face)
+ return false;
+
+ hb_font_t* font =
+ harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
+ DCHECK(font);
+ hb_face_t* face = hb_font_get_face(font);
+ DCHECK(face);
+
+ return hb_ot_math_has_data(face);
+}
+
+base::Optional<float> OpenTypeMathSupport::MathConstant(
+ const HarfBuzzFace* harfbuzz_face,
+ MathConstants constant) {
+ if (!HasMathData(harfbuzz_face))
+ return base::nullopt;
+
+ hb_font_t* font =
+ harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
+ DCHECK(font);
+
+ hb_position_t harfbuzz_value = hb_ot_math_get_constant(
+ font, static_cast<hb_ot_math_constant_t>(constant));
+
+ switch (constant) {
+ case kScriptPercentScaleDown:
+ case kScriptScriptPercentScaleDown:
+ case kRadicalDegreeBottomRaisePercent:
+ return base::Optional<float>(harfbuzz_value / 100.0);
+ case kDelimitedSubFormulaMinHeight:
+ case kDisplayOperatorMinHeight:
+ case kMathLeading:
+ case kAxisHeight:
+ case kAccentBaseHeight:
+ case kFlattenedAccentBaseHeight:
+ case kSubscriptShiftDown:
+ case kSubscriptTopMax:
+ case kSubscriptBaselineDropMin:
+ case kSuperscriptShiftUp:
+ case kSuperscriptShiftUpCramped:
+ case kSuperscriptBottomMin:
+ case kSuperscriptBaselineDropMax:
+ case kSubSuperscriptGapMin:
+ case kSuperscriptBottomMaxWithSubscript:
+ case kSpaceAfterScript:
+ case kUpperLimitGapMin:
+ case kUpperLimitBaselineRiseMin:
+ case kLowerLimitGapMin:
+ case kLowerLimitBaselineDropMin:
+ case kStackTopShiftUp:
+ case kStackTopDisplayStyleShiftUp:
+ case kStackBottomShiftDown:
+ case kStackBottomDisplayStyleShiftDown:
+ case kStackGapMin:
+ case kStackDisplayStyleGapMin:
+ case kStretchStackTopShiftUp:
+ case kStretchStackBottomShiftDown:
+ case kStretchStackGapAboveMin:
+ case kStretchStackGapBelowMin:
+ case kFractionNumeratorShiftUp:
+ case kFractionNumeratorDisplayStyleShiftUp:
+ case kFractionDenominatorShiftDown:
+ case kFractionDenominatorDisplayStyleShiftDown:
+ case kFractionNumeratorGapMin:
+ case kFractionNumDisplayStyleGapMin:
+ case kFractionRuleThickness:
+ case kFractionDenominatorGapMin:
+ case kFractionDenomDisplayStyleGapMin:
+ case kSkewedFractionHorizontalGap:
+ case kSkewedFractionVerticalGap:
+ case kOverbarVerticalGap:
+ case kOverbarRuleThickness:
+ case kOverbarExtraAscender:
+ case kUnderbarVerticalGap:
+ case kUnderbarRuleThickness:
+ case kUnderbarExtraDescender:
+ case kRadicalVerticalGap:
+ case kRadicalDisplayStyleVerticalGap:
+ case kRadicalRuleThickness:
+ case kRadicalExtraAscender:
+ case kRadicalKernBeforeDegree:
+ case kRadicalKernAfterDegree:
+ return base::Optional<float>(HarfBuzzUnitsToFloat(harfbuzz_value));
+ default:
+ NOTREACHED();
+ }
+ return base::nullopt;
+}
+
+base::Optional<float> OpenTypeMathSupport::MathItalicCorrection(
+ const HarfBuzzFace* harfbuzz_face,
+ Glyph glyph) {
+ if (!harfbuzz_face)
+ return base::nullopt;
+
+ hb_font_t* font =
+ harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
+
+ return base::Optional<float>(HarfBuzzUnitsToFloat(
+ hb_ot_math_get_glyph_italics_correction(font, glyph)));
+}
+
+template <typename HarfBuzzRecordType>
+using GetHarfBuzzMathRecordGetter =
+ base::OnceCallback<unsigned int(hb_font_t* font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ unsigned int start_offset,
+ unsigned int* record_count,
+ HarfBuzzRecordType* record_array)>;
+
+template <typename HarfBuzzRecordType, typename RecordType>
+using HarfBuzzMathRecordConverter =
+ base::RepeatingCallback<RecordType(HarfBuzzRecordType)>;
+
+template <typename HarfBuzzRecordType, typename RecordType>
+Vector<RecordType> GetHarfBuzzMathRecord(
+ const HarfBuzzFace* harfbuzz_face,
+ Glyph base_glyph,
+ OpenTypeMathStretchData::StretchAxis stretch_axis,
+ GetHarfBuzzMathRecordGetter<HarfBuzzRecordType> getter,
+ HarfBuzzMathRecordConverter<HarfBuzzRecordType, RecordType> converter,
+ base::Optional<RecordType> prepended_record) {
+ hb_font_t* hb_font =
+ harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
+ DCHECK(hb_font);
+
+ hb_direction_t hb_stretch_axis = HarfBuzzDirection(stretch_axis);
+
+ // In practice, math fonts have, for a given base glyph and stretch axis only
+ // provide a few GlyphVariantRecords (size variants of increasing sizes) and
+ // GlyphPartRecords (parts of a glyph assembly) so it is safe to truncate
+ // the result vector to a small size.
+ HarfBuzzRecordType chunk[kMaxHarfBuzzRecords];
+ unsigned int count = kMaxHarfBuzzRecords;
+ std::move(getter).Run(hb_font, base_glyph, hb_stretch_axis,
+ 0 /* start_offset */, &count, chunk);
+
+ // Create the vector to the determined size and initialize it with the results
+ // converted from HarfBuzz's ones, prepending any optional record.
+ Vector<RecordType> result;
+ result.ReserveInitialCapacity(prepended_record ? count + 1 : count);
+ if (prepended_record)
+ result.push_back(*prepended_record);
+ for (unsigned i = 0; i < count; i++) {
+ result.push_back(converter.Run(chunk[i]));
+ }
+ return result;
+}
+
+Vector<OpenTypeMathStretchData::GlyphVariantRecord>
+OpenTypeMathSupport::GetGlyphVariantRecords(
+ const HarfBuzzFace* harfbuzz_face,
+ Glyph base_glyph,
+ OpenTypeMathStretchData::StretchAxis stretch_axis) {
+ DCHECK(harfbuzz_face);
+ DCHECK(base_glyph);
+
+ auto getter = base::BindOnce(&hb_ot_math_get_glyph_variants);
+ auto converter =
+ base::BindRepeating([](hb_ot_math_glyph_variant_t record)
+ -> OpenTypeMathStretchData::GlyphVariantRecord {
+ return record.glyph;
+ });
+ return GetHarfBuzzMathRecord(
+ harfbuzz_face, base_glyph, stretch_axis, std::move(getter),
+ std::move(converter),
+ base::Optional<OpenTypeMathStretchData::GlyphVariantRecord>(base_glyph));
+}
+
+Vector<OpenTypeMathStretchData::GlyphPartRecord>
+OpenTypeMathSupport::GetGlyphPartRecords(
+ const HarfBuzzFace* harfbuzz_face,
+ Glyph base_glyph,
+ OpenTypeMathStretchData::StretchAxis stretch_axis,
+ float* italic_correction) {
+ DCHECK(harfbuzz_face);
+ DCHECK(base_glyph);
+
+ auto getter = base::BindOnce(
+ [](hb_font_t* font, hb_codepoint_t glyph, hb_direction_t direction,
+ unsigned int start_offset, unsigned int* parts_count,
+ hb_ot_math_glyph_part_t* parts) {
+ hb_position_t italic_correction;
+ return hb_ot_math_get_glyph_assembly(font, glyph, direction,
+ start_offset, parts_count, parts,
+ &italic_correction);
+ });
+ auto converter =
+ base::BindRepeating([](hb_ot_math_glyph_part_t record)
+ -> OpenTypeMathStretchData::GlyphPartRecord {
+ return {record.glyph,
+ HarfBuzzUnitsToFloat(record.start_connector_length),
+ HarfBuzzUnitsToFloat(record.end_connector_length),
+ HarfBuzzUnitsToFloat(record.full_advance),
+ record.flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER};
+ });
+ Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
+ GetHarfBuzzMathRecord(
+ harfbuzz_face, base_glyph, stretch_axis, std::move(getter),
+ std::move(converter),
+ base::Optional<OpenTypeMathStretchData::GlyphPartRecord>());
+ if (italic_correction && !parts.IsEmpty()) {
+ hb_font_t* hb_font =
+ harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
+ // A GlyphAssembly subtable exists for the specified font, glyph and stretch
+ // axis since it has been possible to retrieve the GlyphPartRecords. This
+ // means that the following call is guaranteed to get an italic correction.
+ hb_position_t harfbuzz_italic_correction;
+ hb_ot_math_get_glyph_assembly(hb_font, base_glyph,
+ HarfBuzzDirection(stretch_axis), 0, nullptr,
+ nullptr, &harfbuzz_italic_correction);
+ *italic_correction = HarfBuzzUnitsToFloat(harfbuzz_italic_correction);
+ }
+ return parts;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h
new file mode 100644
index 00000000000..633a4d11f2b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h
@@ -0,0 +1,120 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_SUPPORT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_SUPPORT_H_
+
+#include "base/optional.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class HarfBuzzFace;
+
+class PLATFORM_EXPORT OpenTypeMathSupport {
+ public:
+ static bool HasMathData(const HarfBuzzFace*);
+
+ // These constants are defined in the OpenType MATH table:
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table
+ // Their values match the indices in the MathConstants subtable.
+ enum MathConstants {
+ kScriptPercentScaleDown = 0,
+ kScriptScriptPercentScaleDown = 1,
+ kDelimitedSubFormulaMinHeight = 2,
+ kDisplayOperatorMinHeight = 3,
+ kMathLeading = 4,
+ kAxisHeight = 5,
+ kAccentBaseHeight = 6,
+ kFlattenedAccentBaseHeight = 7,
+ kSubscriptShiftDown = 8,
+ kSubscriptTopMax = 9,
+ kSubscriptBaselineDropMin = 10,
+ kSuperscriptShiftUp = 11,
+ kSuperscriptShiftUpCramped = 12,
+ kSuperscriptBottomMin = 13,
+ kSuperscriptBaselineDropMax = 14,
+ kSubSuperscriptGapMin = 15,
+ kSuperscriptBottomMaxWithSubscript = 16,
+ kSpaceAfterScript = 17,
+ kUpperLimitGapMin = 18,
+ kUpperLimitBaselineRiseMin = 19,
+ kLowerLimitGapMin = 20,
+ kLowerLimitBaselineDropMin = 21,
+ kStackTopShiftUp = 22,
+ kStackTopDisplayStyleShiftUp = 23,
+ kStackBottomShiftDown = 24,
+ kStackBottomDisplayStyleShiftDown = 25,
+ kStackGapMin = 26,
+ kStackDisplayStyleGapMin = 27,
+ kStretchStackTopShiftUp = 28,
+ kStretchStackBottomShiftDown = 29,
+ kStretchStackGapAboveMin = 30,
+ kStretchStackGapBelowMin = 31,
+ kFractionNumeratorShiftUp = 32,
+ kFractionNumeratorDisplayStyleShiftUp = 33,
+ kFractionDenominatorShiftDown = 34,
+ kFractionDenominatorDisplayStyleShiftDown = 35,
+ kFractionNumeratorGapMin = 36,
+ kFractionNumDisplayStyleGapMin = 37,
+ kFractionRuleThickness = 38,
+ kFractionDenominatorGapMin = 39,
+ kFractionDenomDisplayStyleGapMin = 40,
+ kSkewedFractionHorizontalGap = 41,
+ kSkewedFractionVerticalGap = 42,
+ kOverbarVerticalGap = 43,
+ kOverbarRuleThickness = 44,
+ kOverbarExtraAscender = 45,
+ kUnderbarVerticalGap = 46,
+ kUnderbarRuleThickness = 47,
+ kUnderbarExtraDescender = 48,
+ kRadicalVerticalGap = 49,
+ kRadicalDisplayStyleVerticalGap = 50,
+ kRadicalRuleThickness = 51,
+ kRadicalExtraAscender = 52,
+ kRadicalKernBeforeDegree = 53,
+ kRadicalKernAfterDegree = 54,
+ kRadicalDegreeBottomRaisePercent = 55
+ };
+
+ // Returns the value of the requested math constant or null if the font does
+ // not have any OpenType MATH table. All values are 16.16 fixed-point values
+ // converted to float except percentages (kScriptPercentScaleDown,
+ // kScriptScriptPercentScaleDown and kRadicalDegreeBottomRaisePercent) which
+ // are represented by a number between 0 and 1.
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table
+ static base::Optional<float> MathConstant(const HarfBuzzFace*, MathConstants);
+
+ // Returns the italic correction corresponding to the specified glyph or null
+ // if the font does not have any OpenType MATH table. This value provides an
+ // estimation of how much the glyph is slanted, which can be used e.g. when
+ // attaching scripts to the glyph.
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathitalicscorrectioninfo-table
+ static base::Optional<float> MathItalicCorrection(const HarfBuzzFace*, Glyph);
+
+ // Returns a vector of GlyphVariantRecords corresponding to the specified
+ // glyph and stretch axis. The base glyph is always added as the first item.
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table
+ static Vector<OpenTypeMathStretchData::GlyphVariantRecord>
+ GetGlyphVariantRecords(const HarfBuzzFace*,
+ Glyph base_glyph,
+ OpenTypeMathStretchData::StretchAxis);
+
+ // Returns a vector of GlyphPartRecords corresponding to the specified
+ // glyph and stretch axis or an empty vector if there is no such construction.
+ // If the italic_correction parameter is specified and a construction is
+ // available, then it is set to the italic correction of the glyph assembly.
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table
+ static Vector<OpenTypeMathStretchData::GlyphPartRecord> GetGlyphPartRecords(
+ const HarfBuzzFace*,
+ Glyph base_glyph,
+ OpenTypeMathStretchData::StretchAxis,
+ float* italic_correction = nullptr);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_MATH_SUPPORT_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support_test.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support_test.cc
new file mode 100644
index 00000000000..c6493f48399
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_math_support_test.cc
@@ -0,0 +1,466 @@
+// 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 "third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h"
+#include "base/memory/scoped_refptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_types.h"
+#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace {
+const UChar32 kLeftBraceCodePoint = '{';
+const UChar32 kOverBraceCodePoint = 0x23DE;
+const UChar32 kArabicMathOperatorHahWithDalCodePoint = 0x1EEF1;
+const UChar32 kNAryWhiteVerticalBarCodePoint = 0x2AFF;
+} // namespace
+
+namespace blink {
+
+class OpenTypeMathSupportTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ font_description.SetComputedSize(10.0);
+ font = Font(font_description);
+ }
+
+ void TearDown() override {}
+
+ Font CreateMathFont(const String& name, float size = 1000) {
+ FontDescription::VariantLigatures ligatures;
+ return blink::test::CreateTestFont(
+ "MathTestFont",
+ blink::test::BlinkWebTestsFontsTestDataPath(String("math/") + name),
+ size, &ligatures);
+ }
+
+ bool HasMathData(const String& name) {
+ return OpenTypeMathSupport::HasMathData(
+ CreateMathFont(name).PrimaryFont()->PlatformData().GetHarfBuzzFace());
+ }
+
+ base::Optional<float> MathConstant(
+ const String& name,
+ OpenTypeMathSupport::MathConstants constant) {
+ Font math = CreateMathFont(name);
+ return OpenTypeMathSupport::MathConstant(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), constant);
+ }
+
+ FontDescription font_description;
+ Font font;
+};
+
+TEST_F(OpenTypeMathSupportTest, HasMathData) {
+ // Null parameter.
+ EXPECT_FALSE(OpenTypeMathSupport::HasMathData(nullptr));
+
+ // Font without a MATH table.
+ EXPECT_FALSE(HasMathData("math-text.woff"));
+
+ // Font with a MATH table.
+ EXPECT_TRUE(HasMathData("axisheight5000-verticalarrow14000.woff"));
+}
+
+TEST_F(OpenTypeMathSupportTest, MathConstantNullOpt) {
+ Font math_text = CreateMathFont("math-text.woff");
+
+ for (int i = OpenTypeMathSupport::MathConstants::kScriptPercentScaleDown;
+ i <=
+ OpenTypeMathSupport::MathConstants::kRadicalDegreeBottomRaisePercent;
+ i++) {
+ auto math_constant = static_cast<OpenTypeMathSupport::MathConstants>(i);
+
+ // Null parameter.
+ EXPECT_FALSE(OpenTypeMathSupport::MathConstant(nullptr, math_constant));
+
+ // Font without a MATH table.
+ EXPECT_FALSE(OpenTypeMathSupport::MathConstant(
+ math_text.PrimaryFont()->PlatformData().GetHarfBuzzFace(),
+ math_constant));
+ }
+}
+
+// See third_party/blink/web_tests/external/wpt/mathml/tools/percentscaledown.py
+TEST_F(OpenTypeMathSupportTest, MathConstantPercentScaleDown) {
+ {
+ auto result = MathConstant(
+ "scriptpercentscaledown80-scriptscriptpercentscaledown0.woff",
+ OpenTypeMathSupport::MathConstants::kScriptPercentScaleDown);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, .8);
+ }
+
+ {
+ auto result = MathConstant(
+ "scriptpercentscaledown0-scriptscriptpercentscaledown40.woff",
+ OpenTypeMathSupport::MathConstants::kScriptScriptPercentScaleDown);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, .4);
+ }
+}
+
+// See third_party/blink/web_tests/external/wpt/mathml/tools/fractions.py
+TEST_F(OpenTypeMathSupportTest, MathConstantFractions) {
+ {
+ auto result = MathConstant(
+ "fraction-numeratorshiftup11000-axisheight1000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kFractionNumeratorShiftUp);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 11000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-numeratordisplaystyleshiftup2000-axisheight1000-"
+ "rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::
+ kFractionNumeratorDisplayStyleShiftUp);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 2000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-denominatorshiftdown3000-axisheight1000-rulethickness1000."
+ "woff",
+ OpenTypeMathSupport::MathConstants::kFractionDenominatorShiftDown);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 3000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-denominatordisplaystyleshiftdown6000-axisheight1000-"
+ "rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::
+ kFractionDenominatorDisplayStyleShiftDown);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 6000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-numeratorgapmin9000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kFractionNumeratorGapMin);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 9000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-numeratordisplaystylegapmin8000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kFractionNumDisplayStyleGapMin);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 8000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-rulethickness10000.woff",
+ OpenTypeMathSupport::MathConstants::kFractionRuleThickness);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 10000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-denominatorgapmin4000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kFractionDenominatorGapMin);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 4000);
+ }
+
+ {
+ auto result = MathConstant(
+ "fraction-denominatordisplaystylegapmin5000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kFractionDenomDisplayStyleGapMin);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 5000);
+ }
+}
+
+// See third_party/blink/web_tests/external/wpt/mathml/tools/radicals.py
+TEST_F(OpenTypeMathSupportTest, MathConstantRadicals) {
+ {
+ auto result = MathConstant(
+ "radical-degreebottomraisepercent25-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalDegreeBottomRaisePercent);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, .25);
+ }
+
+ {
+ auto result =
+ MathConstant("radical-verticalgap6000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalVerticalGap);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 6000);
+ }
+
+ {
+ auto result = MathConstant(
+ "radical-displaystyleverticalgap7000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalDisplayStyleVerticalGap);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 7000);
+ }
+
+ {
+ auto result =
+ MathConstant("radical-rulethickness8000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalRuleThickness);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 8000);
+ }
+
+ {
+ auto result =
+ MathConstant("radical-extraascender3000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalExtraAscender);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 3000);
+ }
+
+ {
+ auto result = MathConstant(
+ "radical-kernbeforedegree4000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalKernBeforeDegree);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, 4000);
+ }
+
+ {
+ auto result = MathConstant(
+ "radical-kernafterdegreeminus5000-rulethickness1000.woff",
+ OpenTypeMathSupport::MathConstants::kRadicalKernAfterDegree);
+ EXPECT_TRUE(result);
+ EXPECT_FLOAT_EQ(*result, -5000);
+ }
+}
+
+TEST_F(OpenTypeMathSupportTest, MathVariantsWithoutTable) {
+ Font math = CreateMathFont("math-text.woff");
+ auto glyph = math.PrimaryFont()->GlyphForCharacter('A');
+
+ // Horizontal variants.
+ {
+ auto variants = OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), glyph,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+ EXPECT_EQ(variants.size(), 1u);
+ EXPECT_EQ(variants[0], glyph);
+ }
+
+ // Vertical variants.
+ {
+ auto variants = OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), glyph,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_EQ(variants.size(), 1u);
+ EXPECT_EQ(variants[0], glyph);
+ }
+
+ // Horizontal parts.
+ {
+ auto parts = OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), glyph,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+ EXPECT_TRUE(parts.IsEmpty());
+ }
+
+ // // Vertical parts.
+ {
+ auto parts = OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), glyph,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_TRUE(parts.IsEmpty());
+ }
+}
+
+TEST_F(OpenTypeMathSupportTest, MathVariantsWithTable) {
+ // operators.woff contains stretchy operators from the MathML operator
+ // dictionary (including left and over braces) represented by squares.
+ // It also contains glyphs h0, h1, h2, h3 and v0, v1, v2, v3 that are
+ // respectively horizontal and vertical rectangles of increasing size.
+ // The MathVariants table contains the following data for horizontal
+ // (respectively vertical) operators:
+ // - Glyph variants: h0, h1, h2, h3 (respectively v0, v1, v2, v3).
+ // - Glyph parts: non-extender h2 and extender h1 (respectively v2 and v1).
+ // For details, see createSizeVariants() and createStretchy() from
+ // third_party/blink/web_tests/external/wpt/mathml/tools/operator-dictionary.py
+
+ Font math = CreateMathFont("operators.woff");
+ auto left_brace = math.PrimaryFont()->GlyphForCharacter(kLeftBraceCodePoint);
+ auto over_brace = math.PrimaryFont()->GlyphForCharacter(kOverBraceCodePoint);
+
+ // Calculate glyph indices from the last unicode character in the font.
+ // TODO(https://crbug.com/1057596): Find a better way to access these glyph
+ // indices.
+ auto v0 = math.PrimaryFont()->GlyphForCharacter(
+ kArabicMathOperatorHahWithDalCodePoint) +
+ 1;
+ auto h0 = v0 + 1;
+ auto v1 = h0 + 1;
+ auto h1 = v1 + 1;
+ auto v2 = h1 + 1;
+ auto h2 = v2 + 1;
+ auto v3 = h2 + 1;
+ auto h3 = v3 + 1;
+
+ // Vertical variants for vertical operator.
+ {
+ auto variants = OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), left_brace,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_EQ(variants.size(), 5u);
+ EXPECT_EQ(variants[0], left_brace);
+ EXPECT_EQ(variants[1], v0);
+ EXPECT_EQ(variants[2], v1);
+ EXPECT_EQ(variants[3], v2);
+ EXPECT_EQ(variants[4], v3);
+ }
+
+ // Horizontal variants for vertical operator.
+ {
+ auto variants = OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), left_brace,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+ EXPECT_EQ(variants.size(), 1u);
+ EXPECT_EQ(variants[0], left_brace);
+ }
+
+ // Horizontal variants for horizontal operator.
+ {
+ auto variants = OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), over_brace,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+ EXPECT_EQ(variants.size(), 5u);
+ EXPECT_EQ(variants[0], over_brace);
+ EXPECT_EQ(variants[1], h0);
+ EXPECT_EQ(variants[2], h1);
+ EXPECT_EQ(variants[3], h2);
+ EXPECT_EQ(variants[4], h3);
+ }
+
+ // Vertical variants for horizontal operator.
+ {
+ auto variants = OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), over_brace,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_EQ(variants.size(), 1u);
+ EXPECT_EQ(variants[0], over_brace);
+ }
+
+ // Vertical parts for vertical operator.
+ {
+ auto parts = OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), left_brace,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_EQ(parts.size(), 2u);
+ EXPECT_EQ(parts[0].glyph, v2);
+ EXPECT_FLOAT_EQ(parts[0].start_connector_length, 0);
+ EXPECT_FLOAT_EQ(parts[0].end_connector_length, 1000);
+ EXPECT_FLOAT_EQ(parts[0].full_advance, 3000);
+ EXPECT_EQ(parts[0].is_extender, false);
+ EXPECT_EQ(parts[1].glyph, v1);
+ EXPECT_FLOAT_EQ(parts[1].start_connector_length, 1000);
+ EXPECT_FLOAT_EQ(parts[1].end_connector_length, 1000);
+ EXPECT_FLOAT_EQ(parts[1].full_advance, 2000);
+ EXPECT_EQ(parts[1].is_extender, true);
+ }
+
+ // Horizontal parts for vertical operator.
+ {
+ auto parts = OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), left_brace,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+ EXPECT_TRUE(parts.IsEmpty());
+ }
+
+ // Horizontal parts for horizontal operator.
+ {
+ auto parts = OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), over_brace,
+ OpenTypeMathStretchData::StretchAxis::Horizontal);
+
+ EXPECT_EQ(parts.size(), 2u);
+ EXPECT_EQ(parts[0].glyph, h2);
+ EXPECT_FLOAT_EQ(parts[0].start_connector_length, 0);
+ EXPECT_FLOAT_EQ(parts[0].end_connector_length, 1000);
+ EXPECT_FLOAT_EQ(parts[0].full_advance, 3000);
+ EXPECT_EQ(parts[0].is_extender, false);
+
+ EXPECT_EQ(parts[1].glyph, h1);
+ EXPECT_FLOAT_EQ(parts[1].start_connector_length, 1000);
+ EXPECT_FLOAT_EQ(parts[1].end_connector_length, 1000);
+ EXPECT_FLOAT_EQ(parts[1].full_advance, 2000);
+ EXPECT_EQ(parts[1].is_extender, true);
+ }
+
+ // Vertical parts for horizontal operator.
+ {
+ auto parts = OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), over_brace,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_TRUE(parts.IsEmpty());
+ }
+}
+
+// See third_party/blink/web_tests/external/wpt/mathml/tools/largeop.py
+TEST_F(OpenTypeMathSupportTest, MathItalicCorrection) {
+ {
+ Font math = CreateMathFont(
+ "largeop-displayoperatorminheight2000-2AFF-italiccorrection3000.woff");
+ Glyph base_glyph =
+ math.PrimaryFont()->GlyphForCharacter(kNAryWhiteVerticalBarCodePoint);
+
+ // Retrieve the glyph with italic correction.
+ Vector<OpenTypeMathStretchData::GlyphVariantRecord> variants =
+ OpenTypeMathSupport::GetGlyphVariantRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), base_glyph,
+ OpenTypeMathStretchData::StretchAxis::Vertical);
+ EXPECT_EQ(variants.size(), 3u);
+ EXPECT_EQ(variants[0], base_glyph);
+ EXPECT_EQ(variants[1], base_glyph);
+ Glyph glyph_with_italic_correction = variants[2];
+
+ // MathItalicCorrection with a value.
+ base::Optional<float> glyph_with_italic_correction_value =
+ OpenTypeMathSupport::MathItalicCorrection(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(),
+ glyph_with_italic_correction);
+ EXPECT_TRUE(glyph_with_italic_correction_value);
+ EXPECT_FLOAT_EQ(*glyph_with_italic_correction_value, 3000);
+
+ // GetGlyphPartRecords does not set italic correction when there is no
+ // construction available.
+ float italic_correction = -1000;
+ Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
+ OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), base_glyph,
+ OpenTypeMathStretchData::StretchAxis::Vertical, &italic_correction);
+ EXPECT_TRUE(parts.IsEmpty());
+ EXPECT_FLOAT_EQ(italic_correction, -1000);
+ }
+
+ {
+ Font math = CreateMathFont(
+ "largeop-displayoperatorminheight7000-2AFF-italiccorrection5000.woff");
+ Glyph base_glyph =
+ math.PrimaryFont()->GlyphForCharacter(kNAryWhiteVerticalBarCodePoint);
+
+ // OpenTypeMathSupport::GetGlyphPartRecords sets italic correction.
+ float italic_correction = -1000;
+ Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
+ OpenTypeMathSupport::GetGlyphPartRecords(
+ math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), base_glyph,
+ OpenTypeMathStretchData::StretchAxis::Vertical, &italic_correction);
+ EXPECT_EQ(parts.size(), 3u);
+ EXPECT_FLOAT_EQ(italic_correction, 5000);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h
index 61b2872c97b..17cc3ed89ec 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/segmented_font_data.h
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/platform/fonts/font_data.h"
#include "third_party/blink/renderer/platform/fonts/font_data_for_range_set.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
class SimpleFontData;
@@ -61,7 +62,12 @@ class PLATFORM_EXPORT SegmentedFontData : public FontData {
Vector<scoped_refptr<FontDataForRangeSet>, 1> faces_;
};
-DEFINE_FONT_DATA_TYPE_CASTS(SegmentedFontData, true);
+template <>
+struct DowncastTraits<SegmentedFontData> {
+ static bool AllowFrom(const FontData& fontData) {
+ return fontData.IsSegmented();
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc
index 5b020364b1a..a9886bcd928 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc
@@ -13,8 +13,8 @@ scoped_refptr<const ShapeResult>
CachingWordShapeIterator::ShapeWordWithoutSpacing(const TextRun& word_run,
const Font* font) {
ShapeCacheEntry* cache_entry = shape_cache_->Add(word_run, ShapeCacheEntry());
- if (cache_entry && cache_entry->shape_result_)
- return cache_entry->shape_result_;
+ if (cache_entry && *cache_entry)
+ return *cache_entry;
const String word_text = word_run.NormalizedUTF16();
HarfBuzzShaper shaper(word_text);
@@ -25,7 +25,7 @@ CachingWordShapeIterator::ShapeWordWithoutSpacing(const TextRun& word_run,
shape_result->SetDeprecatedInkBounds(shape_result->ComputeInkBounds());
if (cache_entry)
- cache_entry->shape_result_ = shape_result;
+ *cache_entry = shape_result;
return shape_result;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
index 7e4e2bc6398..68972169da9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
@@ -37,7 +37,7 @@
namespace blink {
ShapeCache* CachingWordShaper::GetShapeCache() const {
- return font_.font_fallback_list_->GetShapeCache(font_.font_description_);
+ return font_.GetShapeCache();
}
// Returns the total advance width of the TextRun run. If glyph_bounds
@@ -157,7 +157,7 @@ GlyphData CachingWordShaper::EmphasisMarkGlyphData(
ShapeResultBuffer buffer;
ShapeResultsForRun(GetShapeCache(), &font_, emphasis_mark_run, &buffer);
- return buffer.EmphasisMarkGlyphData(font_.font_description_);
+ return buffer.EmphasisMarkGlyphData(font_.GetFontDescription());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc
index 89fea7e10c3..46137b2efdd 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc
@@ -24,7 +24,6 @@ class CachingWordShaperTest : public testing::Test {
font_description.SetGenericFamily(FontDescription::kStandardFamily);
font = Font(font_description);
- font.Update(nullptr);
ASSERT_TRUE(font.CanShapeWordByWord());
fallback_fonts = nullptr;
cache = std::make_unique<ShapeCache>();
@@ -390,7 +389,6 @@ TEST_F(CachingWordShaperTest, TextOrientationFallbackShouldNotInFallbackList) {
font_description.SetOrientation(FontOrientation::kVerticalMixed);
Font vertical_mixed_font = Font(font_description);
- vertical_mixed_font.Update(nullptr);
ASSERT_TRUE(vertical_mixed_font.CanShapeWordByWord());
CachingWordShaper shaper(vertical_mixed_font);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
index 4d4a8227312..97fa173bb8b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -30,8 +30,10 @@
#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
-#include <hb-ot.h>
+// clang-format off
#include <hb.h>
+#include <hb-ot.h>
+// clang-format on
#include <memory>
@@ -50,6 +52,7 @@
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/harfbuzz-ng/utils/hb_scoped.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPoint.h"
@@ -59,34 +62,40 @@
namespace blink {
-void HbFontDeleter::operator()(hb_font_t* font) {
- if (font)
- hb_font_destroy(font);
-}
+namespace {
-void HbFaceDeleter::operator()(hb_face_t* face) {
- if (face)
- hb_face_destroy(face);
-}
+#if defined(OS_MACOSX)
+void DetermineTrakSbix(SkTypeface* typeface, bool* has_trak, bool* has_sbix) {
+ int num_tags = typeface->countTables();
+
+ SkFontTableTag tags[num_tags];
+
+ int returned_tags = typeface->getTableTags(tags);
+ DCHECK_EQ(num_tags, returned_tags);
-struct HbSetDeleter {
- void operator()(hb_set_t* set) {
- if (set)
- hb_set_destroy(set);
+ for (auto& tag : tags) {
+ if (tag == SkSetFourByteTag('t', 'r', 'a', 'k'))
+ *has_trak = true;
+ if (tag == SkSetFourByteTag('s', 'b', 'i', 'x'))
+ *has_sbix = true;
}
-};
+}
+#endif
-using HbSetUniquePtr = std::unique_ptr<hb_set_t, HbSetDeleter>;
+} // namespace
-static scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t*);
+static scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(
+ hb_face_t*,
+ SkTypeface* typefaces);
HarfBuzzFace::HarfBuzzFace(FontPlatformData* platform_data, uint64_t unique_id)
: platform_data_(platform_data), unique_id_(unique_id) {
HarfBuzzFontCache::AddResult result =
- FontGlobalContext::GetHarfBuzzFontCache().insert(unique_id_, nullptr);
+ FontGlobalContext::GetHarfBuzzFontCache()->insert(unique_id_, nullptr);
if (result.is_new_entry) {
- HbFaceUniquePtr face(CreateFace());
- result.stored_value->value = CreateHbFontCacheEntry(face.get());
+ HbScoped<hb_face_t> face(CreateFace());
+ result.stored_value->value =
+ CreateHbFontCacheEntry(face.get(), platform_data->Typeface());
}
result.stored_value->value->AddRef();
unscaled_font_ = result.stored_value->value->HbFont();
@@ -94,13 +103,14 @@ HarfBuzzFace::HarfBuzzFace(FontPlatformData* platform_data, uint64_t unique_id)
}
HarfBuzzFace::~HarfBuzzFace() {
- HarfBuzzFontCache::iterator result =
- FontGlobalContext::GetHarfBuzzFontCache().find(unique_id_);
- SECURITY_DCHECK(result != FontGlobalContext::GetHarfBuzzFontCache().end());
+ HarfBuzzFontCache* harfbuzz_font_cache =
+ FontGlobalContext::GetHarfBuzzFontCache();
+ HarfBuzzFontCache::iterator result = harfbuzz_font_cache->find(unique_id_);
+ SECURITY_DCHECK(result != harfbuzz_font_cache->end());
DCHECK(!result.Get()->value->HasOneRef());
result.Get()->value->Release();
if (result.Get()->value->HasOneRef())
- FontGlobalContext::GetHarfBuzzFontCache().erase(unique_id_);
+ harfbuzz_font_cache->erase(unique_id_);
}
static hb_bool_t HarfBuzzGetGlyph(hb_font_t* hb_font,
@@ -228,7 +238,7 @@ bool HarfBuzzFace::HasSpaceInLigaturesOrKerning(TypesettingFeatures features) {
const hb_codepoint_t kInvalidCodepoint = static_cast<hb_codepoint_t>(-1);
hb_codepoint_t space = kInvalidCodepoint;
- HbSetUniquePtr glyphs(hb_set_create());
+ HbScoped<hb_set_t> glyphs(hb_set_create());
// Check whether computing is needed and compute for gpos/gsub.
if (features & kKerning &&
@@ -280,31 +290,43 @@ bool HarfBuzzFace::ShouldSubpixelPosition() {
return harfbuzz_font_data_->font_.isSubpixel();
}
-static hb_font_funcs_t* HarfBuzzSkiaGetFontFuncs() {
- hb_font_funcs_t* funcs = FontGlobalContext::GetHarfBuzzFontFuncs();
+static hb_font_funcs_t* create_populated_hb_font_funcs(
+ FontGlobalContext::HorizontalAdvanceSource horizontal_advance_source) {
+ hb_font_funcs_t* funcs = hb_font_funcs_create();
- // We don't set callback functions which we can't support.
- // HarfBuzz will use the fallback implementation if they aren't set.
- if (!funcs) {
- funcs = hb_font_funcs_create();
- hb_font_funcs_set_variation_glyph_func(funcs, HarfBuzzGetGlyph, nullptr,
- nullptr);
- hb_font_funcs_set_nominal_glyph_func(funcs, HarfBuzzGetNominalGlyph,
- nullptr, nullptr);
+ if (horizontal_advance_source == FontGlobalContext::kSkiaHorizontalAdvances) {
hb_font_funcs_set_glyph_h_advance_func(
funcs, HarfBuzzGetGlyphHorizontalAdvance, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func(
funcs, HarfBuzzGetGlyphHorizontalAdvances, nullptr, nullptr);
- // TODO(https://crbug.com/899718): Replace vertical metrics callbacks with
- // HarfBuzz VORG/VMTX internal implementation by deregistering those.
- hb_font_funcs_set_glyph_v_advance_func(
- funcs, HarfBuzzGetGlyphVerticalAdvance, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_origin_func(funcs, HarfBuzzGetGlyphVerticalOrigin,
- nullptr, nullptr);
- hb_font_funcs_set_glyph_extents_func(funcs, HarfBuzzGetGlyphExtents,
+ }
+ hb_font_funcs_set_variation_glyph_func(funcs, HarfBuzzGetGlyph, nullptr,
+ nullptr);
+ hb_font_funcs_set_nominal_glyph_func(funcs, HarfBuzzGetNominalGlyph, nullptr,
+ nullptr);
+ // TODO(https://crbug.com/899718): Replace vertical metrics callbacks with
+ // HarfBuzz VORG/VMTX internal implementation by deregistering those.
+ hb_font_funcs_set_glyph_v_advance_func(funcs, HarfBuzzGetGlyphVerticalAdvance,
nullptr, nullptr);
- hb_font_funcs_make_immutable(funcs);
- FontGlobalContext::SetHarfBuzzFontFuncs(funcs);
+ hb_font_funcs_set_glyph_v_origin_func(funcs, HarfBuzzGetGlyphVerticalOrigin,
+ nullptr, nullptr);
+ hb_font_funcs_set_glyph_extents_func(funcs, HarfBuzzGetGlyphExtents, nullptr,
+ nullptr);
+
+ hb_font_funcs_make_immutable(funcs);
+ return funcs;
+}
+
+static hb_font_funcs_t* HarfBuzzSkiaGetFontFuncs(
+ FontGlobalContext::HorizontalAdvanceSource advance_source) {
+ hb_font_funcs_t* funcs =
+ FontGlobalContext::GetHarfBuzzFontFuncs(advance_source);
+
+ // We don't set callback functions which we can't support.
+ // HarfBuzz will use the fallback implementation if they aren't set.
+ if (!funcs) {
+ funcs = create_populated_hb_font_funcs(advance_source);
+ FontGlobalContext::SetHarfBuzzFontFuncs(advance_source, funcs);
}
DCHECK(funcs);
return funcs;
@@ -360,11 +382,10 @@ hb_face_t* HarfBuzzFace::CreateFace() {
if (tf_stream && tf_stream->getMemoryBase()) {
const void* tf_memory = tf_stream->getMemoryBase();
size_t tf_size = tf_stream->getLength();
- std::unique_ptr<hb_blob_t, void (*)(hb_blob_t*)> face_blob(
+ HbScoped<hb_blob_t> face_blob(
hb_blob_create(reinterpret_cast<const char*>(tf_memory),
SafeCast<unsigned int>(tf_size), HB_MEMORY_MODE_READONLY,
- tf_stream.release(), DeleteTypefaceStream),
- hb_blob_destroy);
+ tf_stream.release(), DeleteTypefaceStream));
face = hb_face_create(face_blob.get(), ttc_index);
}
#endif
@@ -382,15 +403,39 @@ hb_face_t* HarfBuzzFace::CreateFace() {
return face;
}
-scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t* face) {
- HbFontUniquePtr ot_font(hb_font_create(face));
+scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t* face,
+ SkTypeface* typeface) {
+ HbScoped<hb_font_t> ot_font(hb_font_create(face));
hb_ot_font_set_funcs(ot_font.get());
+
+ int axis_count = typeface->getVariationDesignPosition(nullptr, 0);
+ if (axis_count > 0) {
+ Vector<SkFontArguments::VariationPosition::Coordinate> axis_values;
+ axis_values.resize(axis_count);
+ if (typeface->getVariationDesignPosition(axis_values.data(),
+ axis_values.size()) > 0) {
+ hb_font_set_variations(
+ ot_font.get(), reinterpret_cast<hb_variation_t*>(axis_values.data()),
+ axis_values.size());
+ }
+ }
+
// Creating a sub font means that non-available functions
// are found from the parent.
hb_font_t* unscaled_font = hb_font_create_sub_font(ot_font.get());
scoped_refptr<HbFontCacheEntry> cache_entry =
HbFontCacheEntry::Create(unscaled_font);
- hb_font_set_funcs(unscaled_font, HarfBuzzSkiaGetFontFuncs(),
+
+ FontGlobalContext::HorizontalAdvanceSource advance_source =
+ FontGlobalContext::kSkiaHorizontalAdvances;
+#if defined(OS_MACOSX)
+ bool has_trak = false;
+ bool has_sbix = false;
+ DetermineTrakSbix(typeface, &has_trak, &has_sbix);
+ if (has_trak && !has_sbix)
+ advance_source = FontGlobalContext::kHarfBuzzHorizontalAdvances;
+#endif
+ hb_font_set_funcs(unscaled_font, HarfBuzzSkiaGetFontFuncs(advance_source),
cache_entry->HbFontData(), nullptr);
return cache_entry;
}
@@ -423,19 +468,6 @@ hb_font_t* HarfBuzzFace::GetScaledFont(
// equivalent of CSS pixels here.
hb_font_set_ptem(unscaled_font_, platform_data_->size());
- SkTypeface* typeface = harfbuzz_font_data_->font_.getTypeface();
- int axis_count = typeface->getVariationDesignPosition(nullptr, 0);
- if (axis_count > 0) {
- Vector<SkFontArguments::VariationPosition::Coordinate> axis_values;
- axis_values.resize(axis_count);
- if (typeface->getVariationDesignPosition(axis_values.data(),
- axis_values.size()) > 0) {
- hb_font_set_variations(
- unscaled_font_, reinterpret_cast<hb_variation_t*>(axis_values.data()),
- axis_values.size());
- }
- }
-
return unscaled_font_;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.cc
index 02690dd9854..40ad779aaed 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.cc
@@ -8,7 +8,7 @@
namespace blink {
HbFontCacheEntry::HbFontCacheEntry(hb_font_t* font)
- : hb_font_(HbFontUniquePtr(font)),
+ : hb_font_(HbScoped<hb_font_t>(font)),
hb_font_data_(std::make_unique<HarfBuzzFontData>()) {}
HbFontCacheEntry::~HbFontCacheEntry() = default;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
index 5826f0a6bba..d8526a9352a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
@@ -5,30 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FONT_CACHE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FONT_CACHE_H_
+#include <hb.h>
+
#include <memory>
#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
-
-struct hb_font_t;
-struct hb_face_t;
+#include "third_party/harfbuzz-ng/utils/hb_scoped.h"
namespace blink {
struct HarfBuzzFontData;
-struct HbFontDeleter {
- void operator()(hb_font_t* font);
-};
-
-using HbFontUniquePtr = std::unique_ptr<hb_font_t, HbFontDeleter>;
-
-struct HbFaceDeleter {
- void operator()(hb_face_t* face);
-};
-
-using HbFaceUniquePtr = std::unique_ptr<hb_face_t, HbFaceDeleter>;
-
// Though we have FontCache class, which provides the cache mechanism for
// WebKit's font objects, we also need additional caching layer for HarfBuzz to
// reduce the number of hb_font_t objects created. Without it, we would create
@@ -50,15 +38,17 @@ class HbFontCacheEntry : public RefCounted<HbFontCacheEntry> {
private:
explicit HbFontCacheEntry(hb_font_t* font);
- HbFontUniquePtr hb_font_;
+ HbScoped<hb_font_t> hb_font_;
std::unique_ptr<HarfBuzzFontData> hb_font_data_;
};
-typedef HashMap<uint64_t,
- scoped_refptr<HbFontCacheEntry>,
- WTF::IntHash<uint64_t>,
- WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>
- HarfBuzzFontCache;
+// Declare as derived class in order to be able to forward-declare it as class
+// in FontGlobalContext.
+class HarfBuzzFontCache
+ : public HashMap<uint64_t,
+ scoped_refptr<HbFontCacheEntry>,
+ WTF::IntHash<uint64_t>,
+ WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> {};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc
index 186cb357c9c..b63c48d9513 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc
@@ -36,9 +36,8 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
Font font(font_description);
// Set font size to something other than the default 0 size in
// FontDescription, 16 matches the default text size in HTML.
+ // We don't use a FontSelector here. Only look for system fonts for now.
font_description.SetComputedSize(16.0f);
- // Only look for system fonts for now.
- font.Update(nullptr);
HarfBuzzShaper shaper(String(converted_input_buffer, converted_length));
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
index 9cca0e58d2b..6c03756d4c4 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
@@ -83,7 +83,6 @@ class HarfBuzzShaperTest : public testing::Test {
void SetUp() override {
font_description.SetComputedSize(12.0);
font = Font(font_description);
- font.Update(nullptr);
}
void TearDown() override {}
@@ -101,7 +100,6 @@ class HarfBuzzShaperTest : public testing::Test {
font_description.SetFamily(devanagari_family);
font = Font(font_description);
- font.Update(nullptr);
}
Font CreateAhem(float size) {
@@ -472,7 +470,6 @@ TEST_F(HarfBuzzShaperTest, ShapeTabulationCharacters) {
TEST_F(HarfBuzzShaperTest, ShapeVerticalUpright) {
font_description.SetOrientation(FontOrientation::kVerticalUpright);
font = Font(font_description);
- font.Update(nullptr);
// This string should create 2 runs, ideographic and Latin, both in upright.
String string(u"\u65E5\u65E5\u65E5lllll");
@@ -496,7 +493,6 @@ TEST_F(HarfBuzzShaperTest, ShapeVerticalUpright) {
TEST_F(HarfBuzzShaperTest, ShapeVerticalUprightIdeograph) {
font_description.SetOrientation(FontOrientation::kVerticalUpright);
font = Font(font_description);
- font.Update(nullptr);
// This string should create one ideograph run.
String string(u"\u65E5\u65E6\u65E0\u65D3\u65D0");
@@ -527,7 +523,6 @@ TEST_F(HarfBuzzShaperTest, RangeShapeSmallCaps) {
font_description.SetVariantCaps(FontDescription::kSmallCaps);
font_description.SetComputedSize(12.0);
Font font(font_description);
- font.Update(nullptr);
// Shaping index 2 to 3 means that case splitting for small caps splits before
// character index 2 since the initial 'a' needs to be uppercased, but the
@@ -563,7 +558,6 @@ TEST_F(HarfBuzzShaperTest, RangeShapeSmallCaps) {
TEST_F(HarfBuzzShaperTest, ShapeVerticalMixed) {
font_description.SetOrientation(FontOrientation::kVerticalMixed);
font = Font(font_description);
- font.Update(nullptr);
// This string should create 2 runs, ideographic in upright and Latin in
// rotated horizontal.
@@ -1634,10 +1628,7 @@ static bool KerningIsHappening(const FontDescription& font_description,
kern.SetKerning(FontDescription::kAutoKerning);
Font font_no_kern(no_kern);
- font_no_kern.Update(nullptr);
-
Font font_kern(kern);
- font_kern.Update(nullptr);
HarfBuzzShaper shaper(str);
@@ -1749,7 +1740,6 @@ TEST_F(HarfBuzzShaperTest, ShapeVerticalWithoutSubpixelPositionIsRounded) {
font_description.SetOrientation(FontOrientation::kVerticalUpright);
font = Font(font_description);
- font.Update(nullptr);
String string(u"\u65E5\u65E5\u65E5");
TextDirection direction = TextDirection::kLtr;
@@ -1769,7 +1759,6 @@ TEST_F(HarfBuzzShaperTest, ShapeVerticalWithSubpixelPositionIsRounded) {
font_description.SetOrientation(FontOrientation::kVerticalUpright);
font = Font(font_description);
- font.Update(nullptr);
String string(u"\u65E5\u65E5\u65E5");
TextDirection direction = TextDirection::kLtr;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
index b6a3ff992b0..9dfd507dd0b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
@@ -39,11 +39,7 @@
namespace blink {
-struct ShapeCacheEntry {
- DISALLOW_NEW();
- ShapeCacheEntry() { shape_result_ = nullptr; }
- scoped_refptr<const ShapeResult> shape_result_;
-};
+using ShapeCacheEntry = scoped_refptr<const ShapeResult>;
class ShapeCache {
USING_FAST_MALLOC(ShapeCache);
@@ -118,7 +114,7 @@ class ShapeCache {
if (run.length() > SmallStringKey::Capacity())
return nullptr;
- return AddSlowCase(run, entry);
+ return AddSlowCase(run, std::move(entry));
}
void ClearIfVersionChanged(unsigned version) {
@@ -140,10 +136,10 @@ class ShapeCache {
size_t ByteSize() const {
size_t self_byte_size = 0;
for (auto cache_entry : single_char_map_) {
- self_byte_size += cache_entry.value.shape_result_->ByteSize();
+ self_byte_size += cache_entry.value->ByteSize();
}
for (auto cache_entry : short_string_map_) {
- self_byte_size += cache_entry.value.shape_result_->ByteSize();
+ self_byte_size += cache_entry.value->ByteSize();
}
return self_byte_size;
}
@@ -160,7 +156,8 @@ class ShapeCache {
// as such use bit 31 (zero-based) to indicate direction.
if (run.Direction() == TextDirection::kRtl)
key |= (1u << 31);
- SingleCharMap::AddResult add_result = single_char_map_.insert(key, entry);
+ SingleCharMap::AddResult add_result =
+ single_char_map_.insert(key, std::move(entry));
is_new_entry = add_result.is_new_entry;
value = &add_result.stored_value->value;
} else {
@@ -170,9 +167,8 @@ class ShapeCache {
} else {
small_string_key = SmallStringKey(run.Span16(), run.Direction());
}
-
SmallStringMap::AddResult add_result =
- short_string_map_.insert(small_string_key, entry);
+ short_string_map_.insert(small_string_key, std::move(entry));
is_new_entry = add_result.is_new_entry;
value = &add_result.stored_value->value;
}
@@ -202,6 +198,7 @@ class ShapeCache {
struct SmallStringKeyHashTraits : WTF::SimpleClassHashTraits<SmallStringKey> {
STATIC_ONLY(SmallStringKeyHashTraits);
static const bool kHasIsEmptyValueFunction = true;
+ static const bool kEmptyValueIsZero = false;
static bool IsEmptyValue(const SmallStringKey& key) {
return key.IsHashTableEmptyValue();
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
index 3a73c9a9d8e..81864362264 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -565,7 +565,7 @@ unsigned ShapeResult::OffsetToFit(float x, TextDirection line_direction) const {
if (IsLtr(line_direction))
return result.left_character_index;
- if (x == result.origin_x && IsRtl(Direction()))
+ if (x == result.origin_x)
return result.left_character_index;
return result.right_character_index;
}
@@ -1450,6 +1450,96 @@ scoped_refptr<ShapeResult> ShapeResult::CreateForSpaces(const Font* font,
return result;
}
+scoped_refptr<ShapeResult> ShapeResult::CreateForStretchyMathOperator(
+ const Font* font,
+ TextDirection direction,
+ OpenTypeMathStretchData::StretchAxis stretch_axis,
+ Glyph glyph_variant,
+ float stretch_size) {
+ bool is_horizontal_assembly =
+ stretch_axis == OpenTypeMathStretchData::StretchAxis::Horizontal;
+ unsigned start_index = 0;
+ unsigned num_characters = 1;
+ scoped_refptr<ShapeResult> result =
+ ShapeResult::Create(font, start_index, num_characters, direction);
+
+ hb_direction_t hb_direction =
+ is_horizontal_assembly ? HB_DIRECTION_LTR : HB_DIRECTION_TTB;
+ unsigned glyph_index = 0;
+ scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create(
+ font->PrimaryFont(), hb_direction, CanvasRotationInVertical::kRegular,
+ HB_SCRIPT_COMMON, start_index, 1 /* num_glyph */, num_characters);
+ run->glyph_data_[glyph_index] = {glyph_variant, 0 /* character index */,
+ true /* IsSafeToBreakBefore */,
+ stretch_size};
+ run->width_ = std::max(0.0f, stretch_size);
+
+ result->width_ = run->width_;
+ result->num_glyphs_ = run->NumGlyphs();
+ result->runs_.push_back(std::move(run));
+
+ return result;
+}
+
+scoped_refptr<ShapeResult> ShapeResult::CreateForStretchyMathOperator(
+ const Font* font,
+ TextDirection direction,
+ OpenTypeMathStretchData::StretchAxis stretch_axis,
+ const OpenTypeMathStretchData::AssemblyParameters& assembly_parameters) {
+ DCHECK(!assembly_parameters.parts.IsEmpty());
+ DCHECK_LE(assembly_parameters.glyph_count, HarfBuzzRunGlyphData::kMaxGlyphs);
+
+ bool is_horizontal_assembly =
+ stretch_axis == OpenTypeMathStretchData::StretchAxis::Horizontal;
+ unsigned start_index = 0;
+ unsigned num_characters = 1;
+ scoped_refptr<ShapeResult> result =
+ ShapeResult::Create(font, start_index, num_characters, direction);
+
+ hb_direction_t hb_direction =
+ is_horizontal_assembly ? HB_DIRECTION_LTR : HB_DIRECTION_TTB;
+ scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create(
+ font->PrimaryFont(), hb_direction, CanvasRotationInVertical::kRegular,
+ HB_SCRIPT_COMMON, start_index, assembly_parameters.glyph_count,
+ num_characters);
+
+ float overlap = assembly_parameters.connector_overlap;
+ unsigned part_index = 0;
+ for (const auto& part : assembly_parameters.parts) {
+ unsigned repetition_count =
+ part.is_extender ? assembly_parameters.repetition_count : 1;
+ if (!repetition_count)
+ continue;
+ DCHECK(part_index < assembly_parameters.glyph_count);
+ for (unsigned repetition_index = 0; repetition_index < repetition_count;
+ repetition_index++) {
+ unsigned glyph_index =
+ is_horizontal_assembly
+ ? part_index
+ : assembly_parameters.glyph_count - 1 - part_index;
+ float full_advance = glyph_index == assembly_parameters.glyph_count - 1
+ ? part.full_advance
+ : part.full_advance - overlap;
+ run->glyph_data_[glyph_index] = {part.glyph, 0 /* character index */,
+ !glyph_index /* IsSafeToBreakBefore */,
+ full_advance};
+ if (!is_horizontal_assembly) {
+ GlyphOffset glyph_offset(
+ 0, -assembly_parameters.stretch_size + part.full_advance);
+ run->glyph_data_.SetOffsetAt(glyph_index, glyph_offset);
+ result->has_vertical_offsets_ |= (glyph_offset.Height() != 0);
+ }
+ part_index++;
+ }
+ }
+ run->width_ = std::max(0.0f, assembly_parameters.stretch_size);
+
+ result->width_ = run->width_;
+ result->num_glyphs_ = run->NumGlyphs();
+ result->runs_.push_back(std::move(run));
+ return result;
+}
+
void ShapeResult::ToString(StringBuilder* output) const {
output->Append("#chars=");
output->AppendNumber(num_characters_);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
index eeb7e99b05f..d63fdd62f44 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -35,6 +35,7 @@
#include "base/containers/span.h"
#include "third_party/blink/renderer/platform/fonts/canvas_rotation_in_vertical.h"
#include "third_party/blink/renderer/platform/fonts/glyph.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_math_stretch_data.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
@@ -142,6 +143,17 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
unsigned start_index,
unsigned length,
float width);
+ static scoped_refptr<ShapeResult> CreateForStretchyMathOperator(
+ const Font*,
+ TextDirection,
+ OpenTypeMathStretchData::StretchAxis,
+ Glyph,
+ float stretch_size);
+ static scoped_refptr<ShapeResult> CreateForStretchyMathOperator(
+ const Font*,
+ TextDirection,
+ OpenTypeMathStretchData::StretchAxis,
+ const OpenTypeMathStretchData::AssemblyParameters&);
~ShapeResult();
// Returns a mutable unique instance. If |this| has more than 1 ref count,
@@ -495,6 +507,7 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
friend class ShapeResultBloberizer;
friend class ShapeResultView;
friend class ShapeResultTest;
+ friend class StretchyOperatorShaper;
template <bool has_non_zero_glyph_offsets>
float ForEachGlyphImpl(float initial_advance,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
index 17be9dacea0..91a4ccffadc 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
@@ -39,7 +39,6 @@ class ShapeResultBloberizerTest : public testing::Test {
font_description.SetGenericFamily(FontDescription::kStandardFamily);
font = Font(font_description);
- font.Update(nullptr);
ASSERT_TRUE(font.CanShapeWordByWord());
fallback_fonts = nullptr;
cache = std::make_unique<ShapeCache>();
@@ -267,7 +266,6 @@ TEST_F(ShapeResultBloberizerTest, CommonAccentLeftToRightFillGlyphBuffer) {
bloberizer.FillGlyphs(run_info, buffer);
Font reference_font(font_description);
- reference_font.Update(nullptr);
reference_font.SetCanShapeWordByWordForTesting(false);
ShapeResultBloberizer reference_bloberizer(reference_font, 1);
@@ -305,7 +303,6 @@ TEST_F(ShapeResultBloberizerTest, CommonAccentRightToLeftFillGlyphBuffer) {
bloberizer.FillGlyphs(run_info, buffer);
Font reference_font(font_description);
- reference_font.Update(nullptr);
reference_font.SetCanShapeWordByWordForTesting(false);
ShapeResultBloberizer reference_bloberizer(reference_font, 1);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
index 73f8a4c0fe3..758065226be 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
@@ -130,7 +130,7 @@ Vector<CharacterRange> ShapeResultBuffer::IndividualCharacterRanges(
float total_width) const {
Vector<CharacterRange> ranges;
float current_x = direction == TextDirection::kRtl ? total_width : 0;
- for (const scoped_refptr<const ShapeResult> result : results_)
+ for (const scoped_refptr<const ShapeResult>& result : results_)
current_x = result->IndividualCharacterRanges(&ranges, current_x);
return ranges;
}
@@ -192,7 +192,7 @@ Vector<double> ShapeResultBuffer::IndividualCharacterAdvances(
Vector<double> advances;
double current_x = direction == TextDirection::kRtl ? total_width : 0;
- for (const scoped_refptr<const ShapeResult> result : results_) {
+ for (const scoped_refptr<const ShapeResult>& result : results_) {
unsigned run_count = result->runs_.size();
result->EnsureGraphemes(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
index a1a6708907c..32fa8f2ab73 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -211,7 +211,7 @@ struct ShapeResult::RunInfo : public RefCounted<ShapeResult::RunInfo> {
}
if (!Rtl())
- end = num_characters_;
+ end = offset + num_characters_;
else
end = start;
start = index;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc
index 3738a170f1d..8dac0939e7b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc
@@ -21,7 +21,6 @@ class ShapeResultTest : public testing::Test {
void SetUp() override {
font_description.SetComputedSize(12.0);
font = Font(font_description);
- font.Update(nullptr);
FontDescription::VariantLigatures ligatures;
arabic_font = blink::test::CreateTestFont(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
index 9e558346965..dd4998fb3c0 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -83,6 +83,15 @@ struct ShapeResultView::RunInfoPart {
// |base::span<RunInfoPart>|.
const RunInfoPart* get() const { return this; }
+ void ExpandRangeToIncludePartialGlyphs(unsigned offset,
+ unsigned* from,
+ unsigned* to) const {
+ DCHECK_GE(offset + start_index_, offset_);
+ unsigned part_offset = offset + start_index_ - offset_;
+ run_->ExpandRangeToIncludePartialGlyphs(
+ part_offset, reinterpret_cast<int*>(from), reinterpret_cast<int*>(to));
+ }
+
scoped_refptr<const ShapeResult::RunInfo> run_;
ShapeResult::RunInfo::GlyphDataRange range_;
@@ -633,4 +642,13 @@ FloatRect ShapeResultView::ComputeInkBounds() const {
return ink_bounds;
}
+void ShapeResultView::ExpandRangeToIncludePartialGlyphs(unsigned* from,
+ unsigned* to) const {
+ unsigned accumulated_offset = char_index_offset_;
+ for (const auto& part : Parts()) {
+ part.ExpandRangeToIncludePartialGlyphs(accumulated_offset, from, to);
+ accumulated_offset += part.NumCharacters();
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
index 591dff49962..05c7fa1563d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
@@ -145,9 +145,11 @@ class PLATFORM_EXPORT ShapeResultView final
}
void GetRunFontData(Vector<ShapeResult::RunFontData>*) const;
+ void ExpandRangeToIncludePartialGlyphs(unsigned* from, unsigned* to) const;
+
private:
template <class ShapeResultType>
- ShapeResultView(const ShapeResultType*);
+ explicit ShapeResultView(const ShapeResultType*);
struct RunInfoPart;
template <class ShapeResultType>
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
index ce0f6ccb82b..85c46054789 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
@@ -21,7 +21,6 @@ class ShapeResultViewTest : public testing::Test {
void SetUp() override {
font_description.SetComputedSize(12.0);
font = Font(font_description);
- font.Update(nullptr);
}
void TearDown() override {}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
index 82eeefad31b..b0296b7f786 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
@@ -52,7 +52,6 @@ class ShapingLineBreakerTest : public testing::Test {
void SetUp() override {
font_description.SetComputedSize(12.0);
font = Font(font_description);
- font.Update(nullptr);
}
void TearDown() override {}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc
new file mode 100644
index 00000000000..99c80b364f4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.cc
@@ -0,0 +1,223 @@
+// 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 "third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h"
+
+#include <hb-ot.h>
+#include <hb.h>
+#include <unicode/uchar.h>
+
+#include "third_party/blink/renderer/platform/fonts/canvas_rotation_in_vertical.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
+#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "ui/gfx/skia_util.h"
+
+namespace blink {
+
+namespace {
+
+// HarfBuzz' hb_position_t is a 16.16 fixed-point value.
+inline float HarfBuzzUnitsToFloat(hb_position_t value) {
+ static const float kFloatToHbRatio = 1.0f / (1 << 16);
+ return kFloatToHbRatio * value;
+}
+
+inline float GetGlyphStretchSize(
+ FloatRect bounds,
+ OpenTypeMathStretchData::StretchAxis stretch_axis) {
+ return stretch_axis == OpenTypeMathStretchData::StretchAxis::Horizontal
+ ? bounds.Width()
+ : bounds.Height();
+}
+
+inline StretchyOperatorShaper::Metrics ToMetrics(FloatRect bounds) {
+ return {bounds.Width(), -bounds.Y(), bounds.MaxY()};
+}
+
+base::Optional<OpenTypeMathStretchData::AssemblyParameters>
+GetAssemblyParameters(const HarfBuzzFace* harfbuzz_face,
+ Glyph base_glyph,
+ OpenTypeMathStretchData::StretchAxis stretch_axis,
+ float target_size) {
+ Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
+ OpenTypeMathSupport::GetGlyphPartRecords(harfbuzz_face, base_glyph,
+ stretch_axis);
+ if (parts.IsEmpty())
+ return base::nullopt;
+
+ hb_font_t* hb_font =
+ harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
+
+ auto hb_stretch_axis =
+ stretch_axis == OpenTypeMathStretchData::StretchAxis::Horizontal
+ ? HB_DIRECTION_LTR
+ : HB_DIRECTION_BTT;
+
+ // Go over the assembly parts and determine parameters used below.
+ // https://mathml-refresh.github.io/mathml-core/#the-glyphassembly-table
+ float min_connector_overlap = HarfBuzzUnitsToFloat(
+ hb_ot_math_get_min_connector_overlap(hb_font, hb_stretch_axis));
+ float max_connector_overlap = std::numeric_limits<float>::max();
+ float non_extender_advance_sum = 0, extender_advance_sum = 0;
+ unsigned non_extender_count = 0, extender_count = 0;
+
+ for (auto& part : parts) {
+ // Calculate the count and advance sums of extender and non-extender glyphs.
+ if (part.is_extender) {
+ extender_count++;
+ extender_advance_sum += part.full_advance;
+ } else {
+ non_extender_count++;
+ non_extender_advance_sum += part.full_advance;
+ }
+
+ // Take into account start connector length for all but the first glyph.
+ if (part.is_extender || &part != &parts.front()) {
+ max_connector_overlap =
+ std::min(max_connector_overlap, part.start_connector_length);
+ }
+
+ // Take into account end connector length for all but the last glyph.
+ if (part.is_extender || &part != &parts.back()) {
+ max_connector_overlap =
+ std::min(max_connector_overlap, part.end_connector_length);
+ }
+ }
+
+ // Check validity conditions indicated in MathML core.
+ float extender_non_overlapping_advance_sum =
+ extender_advance_sum - min_connector_overlap * extender_count;
+ if (extender_count == 0 || max_connector_overlap < min_connector_overlap ||
+ extender_non_overlapping_advance_sum <= 0)
+ return base::nullopt;
+
+ // Calculate the minimal number of repetitions needed to obtain an assembly
+ // size of size at least target size (r_min in MathML Core).
+ unsigned repetition_count = std::max<float>(
+ std::ceil((target_size - non_extender_advance_sum +
+ min_connector_overlap * (non_extender_count - 1)) /
+ extender_non_overlapping_advance_sum),
+ 0);
+
+ // Calculate the number of glyphs, limiting repetition_count to ensure the
+ // assembly does not have more than HarfBuzzRunGlyphData::kMaxGlyphs.
+ DCHECK_LE(non_extender_count, HarfBuzzRunGlyphData::kMaxGlyphs);
+ repetition_count = std::min<unsigned>(
+ repetition_count,
+ (HarfBuzzRunGlyphData::kMaxGlyphs - non_extender_count) / extender_count);
+ unsigned glyph_count = non_extender_count + repetition_count * extender_count;
+ DCHECK_LE(glyph_count, HarfBuzzRunGlyphData::kMaxGlyphs);
+
+ // Calculate the maximum overlap (called o_max in MathML Core) and the number
+ // of glyph in such an assembly (called N in MathML Core).
+ float connector_overlap = max_connector_overlap;
+ if (glyph_count > 1) {
+ float max_connector_overlap_theorical =
+ (non_extender_advance_sum + repetition_count * extender_advance_sum -
+ target_size) /
+ (glyph_count - 1);
+ connector_overlap =
+ std::max(min_connector_overlap,
+ std::min(connector_overlap, max_connector_overlap_theorical));
+ }
+
+ // Calculate the assembly size (called AssemblySize(o, r) in MathML Core).
+ float stretch_size = non_extender_advance_sum +
+ repetition_count * extender_advance_sum -
+ connector_overlap * (glyph_count - 1);
+
+ return base::Optional<OpenTypeMathStretchData::AssemblyParameters>(
+ {connector_overlap, repetition_count, glyph_count, stretch_size,
+ std::move(parts)});
+}
+
+} // namespace
+
+StretchyOperatorShaper::Metrics StretchyOperatorShaper::GetMetrics(
+ const Font* font,
+ float target_size) const {
+ const SimpleFontData* primary_font = font->PrimaryFont();
+ const HarfBuzzFace* harfbuzz_face =
+ primary_font->PlatformData().GetHarfBuzzFace();
+ Glyph base_glyph = primary_font->GlyphForCharacter(stretchy_character_);
+
+ FloatRect bounds;
+
+ // Try different glyph variants.
+ for (auto& variant : OpenTypeMathSupport::GetGlyphVariantRecords(
+ harfbuzz_face, base_glyph, stretch_axis_)) {
+ bounds = primary_font->BoundsForGlyph(variant);
+ if (GetGlyphStretchSize(bounds, stretch_axis_) >= target_size)
+ return ToMetrics(bounds);
+ }
+
+ // Try a glyph assembly.
+ auto params = GetAssemblyParameters(harfbuzz_face, base_glyph, stretch_axis_,
+ target_size);
+ if (!params)
+ return ToMetrics(bounds);
+
+ bounds = stretch_axis_ == OpenTypeMathStretchData::StretchAxis::Horizontal
+ ? FloatRect(0, 0, params->stretch_size, 0)
+ : FloatRect(0, -params->stretch_size, 0, params->stretch_size);
+
+ for (auto& part : params->parts) {
+ // Include dimension of the part, orthogonal to the stretch axis.
+ auto glyph_bounds = primary_font->BoundsForGlyph(part.glyph);
+ if (stretch_axis_ == OpenTypeMathStretchData::StretchAxis::Horizontal) {
+ glyph_bounds.SetX(0);
+ glyph_bounds.SetWidth(0);
+ } else {
+ glyph_bounds.SetY(0);
+ glyph_bounds.SetHeight(0);
+ }
+ bounds.UniteEvenIfEmpty(glyph_bounds);
+ }
+
+ return ToMetrics(bounds);
+}
+
+scoped_refptr<ShapeResult> StretchyOperatorShaper::Shape(
+ const Font* font,
+ float target_size) const {
+ const SimpleFontData* primary_font = font->PrimaryFont();
+ const HarfBuzzFace* harfbuzz_face =
+ primary_font->PlatformData().GetHarfBuzzFace();
+ Glyph base_glyph = primary_font->GlyphForCharacter(stretchy_character_);
+
+ Glyph glyph_variant;
+ float glyph_variant_stretch_size;
+ TextDirection direction = TextDirection::kLtr;
+
+ // Try different glyph variants.
+ for (auto& variant : OpenTypeMathSupport::GetGlyphVariantRecords(
+ harfbuzz_face, base_glyph, stretch_axis_)) {
+ glyph_variant = variant;
+ auto bounds = primary_font->BoundsForGlyph(glyph_variant);
+ glyph_variant_stretch_size = GetGlyphStretchSize(bounds, stretch_axis_);
+ if (glyph_variant_stretch_size >= target_size) {
+ return ShapeResult::CreateForStretchyMathOperator(
+ font, direction, stretch_axis_, glyph_variant,
+ glyph_variant_stretch_size);
+ }
+ }
+
+ // Try a glyph assembly.
+ auto params = GetAssemblyParameters(harfbuzz_face, base_glyph, stretch_axis_,
+ target_size);
+ if (!params) {
+ return ShapeResult::CreateForStretchyMathOperator(
+ font, direction, stretch_axis_, glyph_variant,
+ glyph_variant_stretch_size);
+ }
+
+ return ShapeResult::CreateForStretchyMathOperator(
+ font, direction, stretch_axis_, std::move(*params));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h
new file mode 100644
index 00000000000..4df0edaed15
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h
@@ -0,0 +1,59 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_STRETCHY_OPERATOR_SHAPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_STRETCHY_OPERATOR_SHAPER_H_
+
+#include <base/memory/scoped_refptr.h>
+#include <unicode/uchar.h>
+#include "third_party/blink/renderer/platform/fonts/glyph.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_math_support.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class Font;
+class ShapeResult;
+class StretchyOperatorShaper;
+
+// TODO(https://crbug.com/1057589): Add a TextDirection parameter, so that it's
+// possible to perform glyph-level (rtlm feature) or character-level mirroring
+// before stretching.
+// https://mathml-refresh.github.io/mathml-core/#algorithms-for-glyph-stretching
+class PLATFORM_EXPORT StretchyOperatorShaper final {
+ DISALLOW_NEW();
+
+ public:
+ StretchyOperatorShaper(UChar stretchy_character,
+ OpenTypeMathStretchData::StretchAxis stretch_axis)
+ : stretchy_character_(stretchy_character), stretch_axis_(stretch_axis) {}
+
+ // Returns the metrics of the stretched operator for layout purpose.
+ // May be called multiple times; font and direction may vary between calls.
+ // https://mathml-refresh.github.io/mathml-core/#dfn-box-metrics-of-a-stretchy-glyph
+ struct Metrics {
+ float advance;
+ float ascent;
+ float descent;
+ // TODO(https://crbug.com/1057592): Add italic correction.
+ };
+ Metrics GetMetrics(const Font*, float target_size) const;
+
+ // Shape the stretched operator. The coordinates of the glyph(s) use the same
+ // origin as the rectangle returned by GetMetrics.
+ // May be called multiple times; font and direction may vary between calls.
+ // https://mathml-refresh.github.io/mathml-core/#dfn-shape-a-stretchy-glyph
+ scoped_refptr<ShapeResult> Shape(const Font*, float target_size) const;
+
+ ~StretchyOperatorShaper() = default;
+
+ private:
+ const UChar stretchy_character_;
+ const OpenTypeMathStretchData::StretchAxis stretch_axis_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_STRETCHY_OPERATOR_SHAPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc
new file mode 100644
index 00000000000..1fd1aeaf8bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper_test.cc
@@ -0,0 +1,264 @@
+// 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 "third_party/blink/renderer/platform/fonts/shaping/stretchy_operator_shaper.h"
+#include "base/memory/scoped_refptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_types.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
+#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+namespace {
+
+const UChar32 kLeftBraceCodePoint = '{';
+const UChar32 kOverBraceCodePoint = 0x23DE;
+const UChar32 kArabicMathOperatorHahWithDalCodePoint = 0x1EEF1;
+float kSizeError = .1;
+
+ShapeResultTestInfo* TestInfo(const scoped_refptr<ShapeResult>& result) {
+ return static_cast<ShapeResultTestInfo*>(result.get());
+}
+
+} // namespace
+
+class StretchyOperatorShaperTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ font_description.SetComputedSize(10.0);
+ font = Font(font_description);
+ }
+
+ void TearDown() override {}
+
+ Font CreateMathFont(const String& name, float size = 1000) {
+ FontDescription::VariantLigatures ligatures;
+ return blink::test::CreateTestFont(
+ "MathTestFont",
+ blink::test::BlinkWebTestsFontsTestDataPath(String("math/") + name),
+ size, &ligatures);
+ }
+
+ FontDescription font_description;
+ Font font;
+};
+
+// See createStretchy() in
+// third_party/blink/web_tests/external/wpt/mathml/tools/operator-dictionary.py
+TEST_F(StretchyOperatorShaperTest, GlyphVariants) {
+ Font math = CreateMathFont("operators.woff");
+
+ StretchyOperatorShaper vertical_shaper(
+ kLeftBraceCodePoint, OpenTypeMathStretchData::StretchAxis::Vertical);
+ StretchyOperatorShaper horizontal_shaper(
+ kOverBraceCodePoint, OpenTypeMathStretchData::StretchAxis::Horizontal);
+
+ auto left_brace = math.PrimaryFont()->GlyphForCharacter(kLeftBraceCodePoint);
+ auto over_brace = math.PrimaryFont()->GlyphForCharacter(kOverBraceCodePoint);
+
+ // Calculate glyph indices from the last unicode character in the font.
+ // TODO(https://crbug.com/1057596): Find a better way to access these glyph
+ // indices.
+ auto v0 = math.PrimaryFont()->GlyphForCharacter(
+ kArabicMathOperatorHahWithDalCodePoint) +
+ 1;
+ auto h0 = v0 + 1;
+ auto v1 = h0 + 1;
+ auto h1 = v1 + 1;
+ auto v2 = h1 + 1;
+ auto h2 = v2 + 1;
+
+ // Stretch operators to target sizes (in font units) 125, 250, 375, 500, 625,
+ // 750, 875, 1000, 1125, ..., 3750, 3875, 4000.
+ //
+ // Shaper tries glyphs over_brace/left_brace, h0/v0, h1/v1, h2/v2, h3/v3 of
+ // respective sizes 1000, 1000, 2000, 3000 and 4000. It returns the smallest
+ // glyph larger than the target size.
+ const unsigned size_count = 4;
+ const unsigned subdivision = 8;
+ for (unsigned i = 0; i < size_count; i++) {
+ for (unsigned j = 1; j <= subdivision; j++) {
+ // Due to floating-point errors, the actual metrics of the size variants
+ // might actually be slightly smaller than expected. Reduce the
+ // target_size by kSizeError to ensure that the shaper picks the desired
+ // size variant.
+ float target_size = i * 1000 + (j * 1000 / subdivision) - kSizeError;
+
+ // Metrics of horizontal size variants.
+ {
+ auto metrics = horizontal_shaper.GetMetrics(&math, target_size);
+ EXPECT_NEAR(metrics.advance, (i + 1) * 1000, kSizeError);
+ EXPECT_NEAR(metrics.ascent, 1000, kSizeError);
+ EXPECT_FLOAT_EQ(metrics.descent, 0);
+ }
+
+ // Metrics of vertical size variants.
+
+ {
+ auto metrics = vertical_shaper.GetMetrics(&math, target_size);
+ EXPECT_NEAR(metrics.advance, 1000, kSizeError);
+ EXPECT_NEAR(metrics.ascent, (i + 1) * 1000, kSizeError);
+ EXPECT_FLOAT_EQ(metrics.descent, 0);
+ }
+
+ // Shaping of horizontal size variants.
+ {
+ scoped_refptr<ShapeResult> result =
+ horizontal_shaper.Shape(&math, target_size);
+ EXPECT_EQ(TestInfo(result)->NumberOfRunsForTesting(), 1u);
+ EXPECT_EQ(TestInfo(result)->RunInfoForTesting(0).NumGlyphs(), 1u);
+ Glyph expected_variant = i ? h0 + 2 * i : over_brace;
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, 0), expected_variant);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, 0), (i + 1) * 1000,
+ kSizeError);
+ }
+
+ // Shaping of vertical size variants.
+ {
+ scoped_refptr<ShapeResult> result =
+ vertical_shaper.Shape(&math, target_size);
+ EXPECT_EQ(TestInfo(result)->NumberOfRunsForTesting(), 1u);
+ EXPECT_EQ(TestInfo(result)->RunInfoForTesting(0).NumGlyphs(), 1u);
+ Glyph expected_variant = i ? v0 + 2 * i : left_brace;
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, 0), expected_variant);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, 0), (i + 1) * 1000,
+ kSizeError);
+ }
+ }
+ }
+
+ // Stretch an operator to target sizes (in font units) much larger than 4000.
+ //
+ // This will force an assembly with the following parts:
+ // _____________________________________________________________
+ // Part | MaxStartOverlap | MaxEndOverlap | Advance | Extender |
+ // h2/v2 | 0 | 1000 | 3000 | false |
+ // h1/v1 | 1000 | 1000 | 2000 | true |
+ //
+ // For an assembly made of one non-extender glyph h2/v2 and repetition_count
+ // copies of extenders h1/v1, the size is
+ // advance(h2/v2) + repetition_count * (advance(h1/v1) - overlap).
+ //
+ // For repetition_count = k and overlap = 750, the size is X = 1250k + 3000.
+ //
+ // Since the font min overlap is 500, for repetition_count = k - 1 the size
+ // is at most Y = 1500k + 1500.
+ //
+ // Since the max overlap of parts is 1000, for repetition_count = k + 1 the
+ // size is at least Z = 1000k + 4000.
+ //
+ // { X - 4000 = 1250k - 1000 >= 250 >> kSizeError for k >= 1.
+ // { X - Y = 1500 - 250k >= 250 >> kSizeError for k <= 5.
+ // Hence setting the target size to 1250k + 3000 will ensure an assembly of
+ // k + 1 glyphs and overlap close to 750 for 1 <= k <= 5.
+ //
+ // Additionally, X - Z = 250k - 1000 = 250 >> kSizeError for k = 5 so this
+ // case also verifies that the minimal number of repetitions is actually used.
+ //
+ for (unsigned repetition_count = 1; repetition_count <= 5;
+ repetition_count++) {
+ // It is not necessary to decrease the target_size by kSizeError here. The
+ // shaper can just increase overlap by kSizeError / repetition_count to
+ // reduce the actual size of the assembly.
+ float overlap = 750;
+ float target_size = 3000 + repetition_count * (2000 - overlap);
+
+ // Metrics of horizontal assembly.
+ {
+ auto metrics = horizontal_shaper.GetMetrics(&math, target_size);
+ EXPECT_NEAR(metrics.advance, target_size, kSizeError);
+ EXPECT_NEAR(metrics.ascent, 1000, kSizeError);
+ EXPECT_FLOAT_EQ(metrics.descent, 0);
+ }
+
+ // Metrics of vertical assembly.
+ {
+ auto metrics = vertical_shaper.GetMetrics(&math, target_size);
+ EXPECT_NEAR(metrics.advance, 1000, kSizeError);
+ EXPECT_NEAR(metrics.ascent, target_size, kSizeError);
+ EXPECT_FLOAT_EQ(metrics.descent, 0);
+ }
+
+ // Shaping of horizontal assembly.
+ // From left to right: h2, h1, h1, h1, ...
+ {
+ scoped_refptr<ShapeResult> result =
+ horizontal_shaper.Shape(&math, target_size);
+
+ EXPECT_EQ(TestInfo(result)->NumberOfRunsForTesting(), 1u);
+ EXPECT_EQ(TestInfo(result)->RunInfoForTesting(0).NumGlyphs(),
+ repetition_count + 1);
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, 0), h2);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, 0), 3000 - overlap,
+ kSizeError);
+ for (unsigned i = 0; i < repetition_count - 1; i++) {
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, i + 1), h1);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, i + 1),
+ 2000 - overlap, kSizeError);
+ }
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, repetition_count), h1);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, repetition_count),
+ 2000, kSizeError);
+ }
+
+ // Shaping of vertical assembly.
+ // From bottom to top: v2, v1, v1, v1, ...
+ {
+ scoped_refptr<ShapeResult> result =
+ vertical_shaper.Shape(&math, target_size);
+
+ EXPECT_EQ(TestInfo(result)->NumberOfRunsForTesting(), 1u);
+ EXPECT_EQ(TestInfo(result)->RunInfoForTesting(0).NumGlyphs(),
+ repetition_count + 1);
+ for (unsigned i = 0; i < repetition_count; i++) {
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, i), v1);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, i), 2000 - overlap,
+ kSizeError);
+ }
+ EXPECT_EQ(TestInfo(result)->GlyphForTesting(0, repetition_count), v2);
+ EXPECT_NEAR(TestInfo(result)->AdvanceForTesting(0, repetition_count),
+ 3000, kSizeError);
+ }
+ }
+
+ // Stretch an operator to edge target size values.
+ //
+ // These tests verify that it does not cause any assertion or crashes.
+ {
+ // Zero.
+ float target_size = 0;
+ horizontal_shaper.Shape(&math, target_size);
+ vertical_shaper.Shape(&math, target_size);
+
+ // Negative.
+ target_size = -5500;
+ horizontal_shaper.Shape(&math, target_size);
+ vertical_shaper.Shape(&math, target_size);
+
+ // Max limit.
+ target_size = std::numeric_limits<float>::max();
+ horizontal_shaper.Shape(&math, target_size);
+ vertical_shaper.Shape(&math, target_size);
+
+ // Min limit.
+ target_size = std::numeric_limits<float>::min();
+ horizontal_shaper.Shape(&math, target_size);
+ vertical_shaper.Shape(&math, target_size);
+
+ // More than the max number of glyphs.
+ // The size of an assembly with one non-extender v2/h2 and k - 1 extenders
+ // h1/v1 and minimal overlap 500 is Y = 1500k + 1500.
+ // So target_size - Y >= 250 >> kSizeError if the assembly does not have
+ // more than the max number of glyphs.
+ target_size = 1500 * HarfBuzzRunGlyphData::kMaxGlyphs + 1750;
+ horizontal_shaper.Shape(&math, target_size);
+ vertical_shaper.Shape(&math, target_size);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
index 7c5e9561c83..070cde2e8ba 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/skia/include/core/SkFont.h"
@@ -245,7 +246,12 @@ ALWAYS_INLINE float SimpleFontData::WidthForGlyph(Glyph glyph) const {
#endif
}
-DEFINE_FONT_DATA_TYPE_CASTS(SimpleFontData, false);
+template <>
+struct DowncastTraits<SimpleFontData> {
+ static bool AllowFrom(const FontData& fontData) {
+ return !fontData.IsSegmented();
+ }
+};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SIMPLE_FONT_DATA_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
index 51bdbb7510c..7537fb4d036 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
@@ -33,6 +33,7 @@
#include <memory>
#include <utility>
+#include "base/logging.h"
#include "build/build_config.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#include "third_party/blink/public/platform/platform.h"
@@ -245,6 +246,13 @@ sk_sp<SkTypeface> FontCache::CreateTypeface(
name.c_str(), font_description.SkiaFontStyle());
}
+#if !defined(OS_MACOSX)
+std::vector<FontEnumerationEntry> FontCache::EnumeratePlatformAvailableFonts() {
+ NOTIMPLEMENTED();
+ return std::vector<FontEnumerationEntry>();
+}
+#endif // !defined(OS_MACOSX)
+
#if !defined(OS_WIN)
std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData(
const FontDescription& font_description,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
index 6a72122ee22..f638f1c8393 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
@@ -15,6 +15,10 @@ class SkFont;
namespace blink {
+// TODO: Width functions are affected by issue
+// https://bugs.chromium.org/p/skia/issues/detail?id=10123 in Skia, which
+// currently does not return trak-free advances on Mac OS 10.15.
+
void SkFontGetGlyphWidthForHarfBuzz(const SkFont&,
hb_codepoint_t,
hb_position_t* width);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc b/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
index 9b5a8ed881f..e72f801016a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
@@ -30,15 +30,12 @@
#include "third_party/blink/renderer/platform/fonts/web_font_decoder.h"
-#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/ots/include/ots-memory-stream.h"
#include "third_party/skia/include/core/SkStream.h"
@@ -145,38 +142,6 @@ ots::TableAction BlinkOTSContext::GetTableAction(uint32_t tag) {
}
}
-void RecordDecodeSpeedHistogram(const char* data,
- size_t length,
- double decode_time,
- size_t decoded_size) {
- if (decode_time <= 0)
- return;
-
- double kb_per_second = decoded_size / (1000 * decode_time);
- if (length >= 4) {
- if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, woff_histogram,
- ("WebFont.DecodeSpeed.WOFF", 1000, 300000, 50));
- woff_histogram.Count(kb_per_second);
- return;
- }
-
- if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == '2') {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, woff2_histogram,
- ("WebFont.DecodeSpeed.WOFF2", 1000, 300000, 50));
- woff2_histogram.Count(kb_per_second);
- return;
- }
- }
-
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, sfnt_histogram,
- ("WebFont.DecodeSpeed.SFNT", 1000, 300000, 50));
- sfnt_histogram.Count(kb_per_second);
-}
-
} // namespace
sk_sp<SkTypeface> WebFontDecoder::Decode(SharedBuffer* buffer) {
@@ -196,14 +161,13 @@ sk_sp<SkTypeface> WebFontDecoder::Decode(SharedBuffer* buffer) {
// Most web fonts are compressed, so the result can be much larger than
// the original.
ots::ExpandingMemoryStream output(buffer->size(), kMaxWebFontSize);
- base::ElapsedTimer timer;
BlinkOTSContext ots_context;
SharedBuffer::DeprecatedFlatData flattened_buffer(buffer);
- const char* data = flattened_buffer.Data();
TRACE_EVENT_BEGIN0("blink", "DecodeFont");
- bool ok = ots_context.Process(&output, reinterpret_cast<const uint8_t*>(data),
- buffer->size());
+ bool ok = ots_context.Process(
+ &output, reinterpret_cast<const uint8_t*>(flattened_buffer.Data()),
+ buffer->size());
TRACE_EVENT_END0("blink", "DecodeFont");
if (!ok) {
@@ -212,9 +176,6 @@ sk_sp<SkTypeface> WebFontDecoder::Decode(SharedBuffer* buffer) {
}
const size_t decoded_length = SafeCast<size_t>(output.Tell());
- RecordDecodeSpeedHistogram(data, buffer->size(), timer.Elapsed().InSecondsF(),
- decoded_length);
-
sk_sp<SkData> sk_data = SkData::MakeWithCopy(output.get(), decoded_length);
sk_sp<SkTypeface> new_typeface;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc
index a563a80074d..9544a0ed0ab 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc
@@ -49,12 +49,11 @@ void FallbackFamilyStyleCache::Put(
String cache_key =
makeCacheKey(generic_family, bcp47_language_tag, fallback_priority);
- FallbackLruCache::TypefaceVector* existing_typefaces =
- recent_fallback_fonts_.Get(cache_key);
+ TypefaceVector* existing_typefaces = recent_fallback_fonts_.Get(cache_key);
if (existing_typefaces) {
existing_typefaces->insert(0, sk_ref_sp(typeface));
} else {
- FallbackLruCache::TypefaceVector typefaces;
+ TypefaceVector typefaces;
typefaces.push_back(sk_ref_sp(typeface));
recent_fallback_fonts_.Put(std::move(cache_key), std::move(typefaces));
}
@@ -67,7 +66,7 @@ void FallbackFamilyStyleCache::Get(
UChar32 character,
String* fallback_family,
SkFontStyle* fallback_style) {
- FallbackLruCache::TypefaceVector* typefaces = recent_fallback_fonts_.Get(
+ TypefaceVector* typefaces = recent_fallback_fonts_.Get(
makeCacheKey(generic_family, bcp47_language_tag, fallback_priority));
if (!typefaces)
return;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
index 5e8f86ebcf9..770702feb39 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
@@ -7,12 +7,15 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
-#include "third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h"
+#include "third_party/blink/renderer/platform/wtf/lru_cache.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkTypeface.h"
namespace blink {
+using TypefaceVector = Vector<sk_sp<SkTypeface>>;
+using FallbackLruCache = WTF::LruCache<String, TypefaceVector>;
+
class FallbackFamilyStyleCache {
USING_FAST_MALLOC(FallbackFamilyStyleCache);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc
deleted file mode 100644
index 37b6a152785..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h"
-
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-FallbackLruCache::FallbackLruCache(size_t max_size) : max_size_(max_size) {
- DCHECK_GT(max_size_, 0u);
-}
-
-FallbackLruCache::TypefaceVector* FallbackLruCache::Get(const String& key) {
- HashMapType::iterator find_result = map_.find(key);
- if (find_result == map_.end())
- return nullptr;
-
- // Move result to beginning of list.
- KeyListNode* node = find_result->value.ListNode();
- ordering_.Remove(node);
- ordering_.Push(node);
- return find_result->value.value();
-}
-
-void FallbackLruCache::Put(String&& key, TypefaceVector&& arg) {
- HashMapType::iterator find_result = map_.find(key);
- if (find_result != map_.end()) {
- ordering_.Remove(find_result->value.ListNode());
- map_.erase(find_result);
- }
-
- if (map_.size() >= max_size_) {
- RemoveLeastRecentlyUsed();
- }
-
- std::unique_ptr<KeyListNode> list_node = std::make_unique<KeyListNode>(key);
- HashMapType::AddResult add_result = map_.insert(
- std::move(key), MappedWithListNode(std::move(arg), std::move(list_node)));
- DCHECK(add_result.is_new_entry);
- ordering_.Push(add_result.stored_value->value.ListNode());
-}
-
-void FallbackLruCache::Clear() {
- map_.clear();
- ordering_.Clear();
-}
-
-void FallbackLruCache::RemoveLeastRecentlyUsed() {
- KeyListNode* tail = ordering_.Tail();
- ordering_.Remove(tail);
- map_.erase(tail->key());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h
deleted file mode 100644
index 90048e3319a..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/doubly_linked_list.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-#include "third_party/skia/include/core/SkTypeface.h"
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_LRU_CACHE_WIN_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_LRU_CACHE_WIN_H_
-
-namespace blink {
-
-/* A LRU cache for storing a a vector of typefaces for a particular key string,
- * which would usually be a locale plus potential additional parameters. Uses a
- * HashMap for storage and access and a DoublyLinkedList for managing age of
- * entries. TODO(https://crbug.com/1010925): Potentially move this to a generic
- * LRU Cache implementation once we have such in WTF. */
-class PLATFORM_EXPORT FallbackLruCache {
- USING_FAST_MALLOC(FallbackLruCache);
-
- public:
- FallbackLruCache(size_t max_size);
-
- using TypefaceVector = Vector<sk_sp<SkTypeface>>;
-
- TypefaceVector* Get(const String& key);
- void Put(String&& key, TypefaceVector&& arg);
-
- void Clear();
-
- size_t size() const { return map_.size(); }
-
- private:
- class KeyListNode final : public DoublyLinkedListNode<KeyListNode> {
- USING_FAST_MALLOC(KeyListNode);
-
- public:
- friend class DoublyLinkedListNode<KeyListNode>;
- KeyListNode(const String& key) : key_(key) {}
-
- const String& key() const { return key_; }
-
- private:
- String key_;
- KeyListNode* prev_{nullptr};
- KeyListNode* next_{nullptr};
- };
-
- class MappedWithListNode {
- USING_FAST_MALLOC(MappedWithListNode);
-
- public:
- MappedWithListNode(TypefaceVector&& mapped_arg,
- std::unique_ptr<KeyListNode>&& list_node)
- : mapped_value_(std::move(mapped_arg)),
- list_node_(std::move(list_node)) {}
-
- MappedWithListNode(WTF::HashTableDeletedValueType) {
- list_node_.reset(reinterpret_cast<KeyListNode*>(-1));
- }
-
- TypefaceVector* value() { return &mapped_value_; }
- KeyListNode* ListNode() { return list_node_.get(); }
-
- private:
- TypefaceVector mapped_value_;
- std::unique_ptr<KeyListNode> list_node_;
- };
-
- void RemoveLeastRecentlyUsed();
-
- using HashMapType = HashMap<String,
- MappedWithListNode,
- DefaultHash<String>::Hash,
- HashTraits<String>,
- SimpleClassHashTraits<MappedWithListNode>>;
-
- HashMapType map_;
- DoublyLinkedList<KeyListNode> ordering_;
- size_t max_size_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_LRU_CACHE_WIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc
index 92f78aa9e38..917f0111235 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h"
+#include "third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkTypeface.h"
@@ -29,7 +32,7 @@ void fillCacheWithDummies(blink::FallbackLruCache& lru_cache,
const char* format_string,
size_t count) {
for (size_t i = 0; i < count; ++i) {
- blink::FallbackLruCache::TypefaceVector dummy_typefaces;
+ blink::TypefaceVector dummy_typefaces;
dummy_typefaces.push_back(
SkTypeface::MakeFromName(kFontFamilyNameArial, SkFontStyle()));
lru_cache.Put(String::Format(format_string, i), std::move(dummy_typefaces));
@@ -48,7 +51,7 @@ TEST(FallbackLruCacheTest, KeepChineseWhenFetched) {
// the Chinese font and ensure it's gone.
FallbackLruCache lru_cache(kLruCacheTestSize);
EXPECT_EQ(lru_cache.size(), 0u);
- FallbackLruCache::TypefaceVector fallback_typefaces_zh;
+ TypefaceVector fallback_typefaces_zh;
fallback_typefaces_zh.push_back(
fallbackForLocale(kHanSimplifiedLocale, kFirstCJKIdeograph));
lru_cache.Put(kHanSimplifiedLocale, std::move(fallback_typefaces_zh));
@@ -56,8 +59,7 @@ TEST(FallbackLruCacheTest, KeepChineseWhenFetched) {
EXPECT_EQ(lru_cache.size(), 1u);
fillCacheWithDummies(lru_cache, "dummy_locale_%zu", kLruCacheTestSize - 1);
- FallbackLruCache::TypefaceVector* chinese_typefaces =
- lru_cache.Get(kHanSimplifiedLocale);
+ TypefaceVector* chinese_typefaces = lru_cache.Get(kHanSimplifiedLocale);
EXPECT_TRUE(chinese_typefaces);
EXPECT_TRUE(chinese_typefaces->at(0)->unicharToGlyph(0x4E01));
EXPECT_EQ(lru_cache.size(), kLruCacheTestSize);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
index 821a6a7afc3..52427643b20 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
@@ -42,7 +42,7 @@
#include "base/debug/alias.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
-#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/fonts/bitmap_glyphs_block_list.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
@@ -229,7 +229,7 @@ void FontCache::SetStatusFontMetrics(const wchar_t* family_name,
void FontCache::EnsureServiceConnected() {
if (service_)
return;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
service_.BindNewPipeAndPassReceiver());
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
index 52555021f7b..13162712b2e 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
@@ -9,8 +9,8 @@
#include "base/files/file_path.h"
#include "mojo/public/mojom/base/shared_memory.mojom-blink.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -165,7 +165,7 @@ bool FontUniqueNameLookupWin::IsFontUniqueNameLookupReadyForSyncLookup() {
void FontUniqueNameLookupWin::EnsureServiceConnected() {
if (service_)
return;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
service_.BindNewPipeAndPassReceiver());
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_point.h b/chromium/third_party/blink/renderer/platform/geometry/float_point.h
index cd1ddb8bf56..91b2d129008 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_point.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_point.h
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_f.h"
@@ -71,6 +72,11 @@ class PLATFORM_EXPORT FloatPoint {
static FloatPoint NarrowPrecision(double x, double y);
+ bool IsValid() const {
+ return x_ != -std::numeric_limits<float>::infinity() &&
+ y_ != -std::numeric_limits<float>::infinity();
+ }
+
constexpr float X() const { return x_; }
constexpr float Y() const { return y_; }
@@ -139,6 +145,9 @@ class PLATFORM_EXPORT FloatPoint {
private:
float x_, y_;
+
+ friend struct ::WTF::DefaultHash<blink::FloatSize>;
+ friend struct ::WTF::HashTraits<blink::FloatSize>;
};
inline FloatPoint& operator+=(FloatPoint& a, const FloatSize& b) {
@@ -217,6 +226,10 @@ inline IntPoint FlooredIntPoint(const FloatPoint& p) {
return IntPoint(clampTo<int>(floorf(p.X())), clampTo<int>(floorf(p.Y())));
}
+inline IntPoint FlooredIntPoint(const gfx::PointF& p) {
+ return IntPoint(clampTo<int>(floorf(p.x())), clampTo<int>(floorf(p.y())));
+}
+
inline IntPoint CeiledIntPoint(const FloatPoint& p) {
return IntPoint(clampTo<int>(ceilf(p.X())), clampTo<int>(ceilf(p.Y())));
}
@@ -243,4 +256,42 @@ PLATFORM_EXPORT WTF::TextStream& operator<<(WTF::TextStream&,
} // namespace blink
-#endif
+namespace WTF {
+
+template <>
+struct DefaultHash<blink::FloatPoint> {
+ STATIC_ONLY(DefaultHash);
+ struct Hash {
+ STATIC_ONLY(Hash);
+ typedef typename IntTypes<sizeof(float)>::UnsignedType Bits;
+ static unsigned GetHash(const blink::FloatPoint& key) {
+ return HashInts(bit_cast<Bits>(key.X()), bit_cast<Bits>(key.Y()));
+ }
+ static bool Equal(const blink::FloatPoint& a, const blink::FloatPoint& b) {
+ return bit_cast<Bits>(a.X()) == bit_cast<Bits>(b.X()) &&
+ bit_cast<Bits>(a.Y()) == bit_cast<Bits>(b.Y());
+ }
+ static const bool safe_to_compare_to_empty_or_deleted = true;
+ };
+};
+
+template <>
+struct HashTraits<blink::FloatPoint> : GenericHashTraits<blink::FloatPoint> {
+ STATIC_ONLY(HashTraits);
+ static const bool kEmptyValueIsZero = false;
+ static blink::FloatPoint EmptyValue() {
+ return blink::FloatPoint(std::numeric_limits<float>::infinity(),
+ std::numeric_limits<float>::infinity());
+ }
+ static void ConstructDeletedValue(blink::FloatPoint& slot, bool) {
+ slot = blink::FloatPoint(-std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity());
+ }
+ static bool IsDeletedValue(const blink::FloatPoint& value) {
+ return !value.IsValid();
+ }
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_FLOAT_POINT_H_
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc b/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
index 3b0b298bf7b..f9c90559557 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
@@ -63,6 +63,10 @@ bool FloatRect::EqualWithinEpsilon(const FloatRect& other,
#endif
+bool FloatRect::IsFinite() const {
+ return static_cast<SkRect>(*this).isFinite();
+}
+
bool FloatRect::IsExpressibleAsIntRect() const {
return isWithinIntRange(X()) && isWithinIntRange(Y()) &&
isWithinIntRange(Width()) && isWithinIntRange(Height()) &&
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rect.h b/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
index 1e3c7b0787a..4271528c4b0 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
@@ -29,6 +29,7 @@
#include <iosfwd>
+#include "base/compiler_specific.h"
#include "base/numerics/clamped_math.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
@@ -92,6 +93,8 @@ class PLATFORM_EXPORT FloatRect {
constexpr bool IsEmpty() const { return size_.IsEmpty(); }
constexpr bool IsZero() const { return size_.IsZero(); }
+ // True if no member is infinite or NaN.
+ bool IsFinite() const;
bool IsExpressibleAsIntRect() const;
FloatPoint Center() const {
@@ -130,8 +133,8 @@ class PLATFORM_EXPORT FloatRect {
location_.Y() + size_.Height());
} // typically bottomRight
- bool Intersects(const IntRect&) const;
- bool Intersects(const FloatRect&) const;
+ WARN_UNUSED_RESULT bool Intersects(const IntRect&) const;
+ WARN_UNUSED_RESULT bool Intersects(const FloatRect&) const;
bool Contains(const IntRect&) const;
bool Contains(const FloatRect&) const;
bool Contains(const FloatPoint&, ContainsMode = kInsideOrOnStroke) const;
diff --git a/chromium/third_party/blink/renderer/platform/geometry/int_rect.h b/chromium/third_party/blink/renderer/platform/geometry/int_rect.h
index 28a594d574e..9f891218aa4 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_rect.h
@@ -28,6 +28,7 @@
#include <iosfwd>
+#include "base/compiler_specific.h"
#include "base/numerics/clamped_math.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
@@ -133,7 +134,7 @@ class PLATFORM_EXPORT IntRect {
location_.Y() + size_.Height());
} // typically bottomRight
- bool Intersects(const IntRect&) const;
+ WARN_UNUSED_RESULT bool Intersects(const IntRect&) const;
bool Contains(const IntRect&) const;
// This checks to see if the rect contains x,y in the traditional sense.
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_rect.h b/chromium/third_party/blink/renderer/platform/geometry/layout_rect.h
index f1b6f9b0798..6434c5d32f5 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_rect.h
@@ -32,6 +32,8 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_RECT_H_
#include <iosfwd>
+
+#include "base/compiler_specific.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
@@ -196,7 +198,7 @@ class PLATFORM_EXPORT LayoutRect {
location_.Y() + size_.Height());
}
- bool Intersects(const LayoutRect&) const;
+ WARN_UNUSED_RESULT bool Intersects(const LayoutRect&) const;
bool Contains(const LayoutRect&) const;
// This checks to see if the rect contains x,y in the traditional sense.
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_size.h b/chromium/third_party/blink/renderer/platform/geometry/layout_size.h
index 472784b000d..32a0c93f776 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_size.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_size.h
@@ -65,6 +65,8 @@ class PLATFORM_EXPORT LayoutSize {
: width_(size.Width()), height_(size.Height()) {}
constexpr explicit LayoutSize(const gfx::Size& size)
: width_(size.width()), height_(size.height()) {}
+ constexpr explicit LayoutSize(const gfx::SizeF& size)
+ : width_(size.width()), height_(size.height()) {}
constexpr explicit operator FloatSize() const {
return FloatSize(width_.ToFloat(), height_.ToFloat());
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_unit.h b/chromium/third_party/blink/renderer/platform/geometry/layout_unit.h
index eaaff017795..8ffe3e11501 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_unit.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_unit.h
@@ -723,7 +723,12 @@ inline float& operator/=(float& a, const LayoutUnit& b) {
inline int SnapSizeToPixel(LayoutUnit size, LayoutUnit location) {
LayoutUnit fraction = location.Fraction();
- return (fraction + size).Round() - fraction.Round();
+ int result = (fraction + size).Round() - fraction.Round();
+ if (UNLIKELY(result == 0 &&
+ std::abs(size.ToFloat()) > LayoutUnit::Epsilon() * 4)) {
+ return size > 0 ? 1 : -1;
+ }
+ return result;
}
inline int RoundToInt(LayoutUnit value) {
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_unit_test.cc b/chromium/third_party/blink/renderer/platform/geometry/layout_unit_test.cc
index db1fa1f610f..05d4a2f762e 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_unit_test.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_unit_test.cc
@@ -155,8 +155,20 @@ TEST(LayoutUnitTest, LayoutUnitSnapSizeToPixel) {
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.99)));
EXPECT_EQ(2, SnapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1)));
- EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)));
- EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)));
+ // 0.046875 is 3/64, lower than 4 * LayoutUnit::Epsilon()
+ EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(0.046875), LayoutUnit(0)));
+ // 0.078125 is 5/64, higher than 4 * LayoutUnit::Epsilon()
+ EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(0.078125), LayoutUnit(0)));
+
+ // Negative versions
+ EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(-0.046875), LayoutUnit(0)));
+ EXPECT_EQ(-1, SnapSizeToPixel(LayoutUnit(-0.078125), LayoutUnit(0)));
+
+ // The next 2 would snap to zero but for the requirement that we not snap
+ // sizes greater than 4 * LayoutUnit::Epsilon() to 0.
+ EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)));
+ EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)));
+
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.0), LayoutUnit(1.5)));
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.49), LayoutUnit(1.5)));
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1.5)));
diff --git a/chromium/third_party/blink/renderer/platform/geometry/length.h b/chromium/third_party/blink/renderer/platform/geometry/length.h
index 72d3979fb1a..a77de90a46a 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/length.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/length.h
@@ -60,7 +60,7 @@ class PLATFORM_EXPORT Length {
kExtendToZoom,
kDeviceWidth,
kDeviceHeight,
- kMaxSizeNone
+ kNone
};
Length() : int_value_(0), quirk_(false), type_(kAuto), is_float_(false) {}
@@ -114,7 +114,7 @@ class PLATFORM_EXPORT Length {
bool operator==(const Length& o) const {
return (type_ == o.type_) && (quirk_ == o.quirk_) &&
- (IsMaxSizeNone() || (GetFloatValue() == o.GetFloatValue()) ||
+ (IsNone() || (GetFloatValue() == o.GetFloatValue()) ||
IsCalculatedEqual(o));
}
bool operator!=(const Length& o) const { return !(*this == o); }
@@ -145,7 +145,7 @@ class PLATFORM_EXPORT Length {
static Length ExtendToZoom() { return Length(kExtendToZoom); }
static Length DeviceWidth() { return Length(kDeviceWidth); }
static Length DeviceHeight() { return Length(kDeviceHeight); }
- static Length MaxSizeNone() { return Length(kMaxSizeNone); }
+ static Length None() { return Length(kNone); }
static Length FitContent() { return Length(kFitContent); }
template <typename NUMBER_TYPE>
static Length Percent(NUMBER_TYPE number) {
@@ -191,21 +191,21 @@ class PLATFORM_EXPORT Length {
void SetQuirk(bool quirk) { quirk_ = quirk; }
- bool IsMaxSizeNone() const { return GetType() == kMaxSizeNone; }
+ bool IsNone() const { return GetType() == kNone; }
// FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated
// Length always contains a percentage, and without a maxValue passed to these
// functions it's impossible to determine the sign or zero-ness. We assume all
// calc values are positive and non-zero for now.
bool IsZero() const {
- DCHECK(!IsMaxSizeNone());
+ DCHECK(!IsNone());
if (IsCalculated())
return false;
return is_float_ ? !float_value_ : !int_value_;
}
bool IsPositive() const {
- if (IsMaxSizeNone())
+ if (IsNone())
return false;
if (IsCalculated())
return true;
@@ -213,7 +213,7 @@ class PLATFORM_EXPORT Length {
return GetFloatValue() > 0;
}
bool IsNegative() const {
- if (IsMaxSizeNone() || IsCalculated())
+ if (IsNone() || IsCalculated())
return false;
return GetFloatValue() < 0;
@@ -272,7 +272,7 @@ class PLATFORM_EXPORT Length {
}
float GetFloatValue() const {
- DCHECK(!IsMaxSizeNone());
+ DCHECK(!IsNone());
return is_float_ ? float_value_ : int_value_;
}
float NonNanCalculatedValue(LayoutUnit max_value) const;
@@ -283,7 +283,7 @@ class PLATFORM_EXPORT Length {
private:
int GetIntValue() const {
- DCHECK(!IsMaxSizeNone());
+ DCHECK(!IsNone());
return is_float_ ? static_cast<int>(float_value_) : int_value_;
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc b/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc
index 6aef97e527d..dd5a6fed930 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/length_functions.cc
@@ -52,7 +52,7 @@ float FloatValueForLength(const Length& length, float maximum_value) {
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
- case Length::kMaxSizeNone:
+ case Length::kNone:
NOTREACHED();
return 0;
}
@@ -80,7 +80,7 @@ LayoutUnit MinimumValueForLengthInternal(const Length& length,
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
- case Length::kMaxSizeNone:
+ case Length::kNone:
NOTREACHED();
return LayoutUnit();
}
@@ -103,7 +103,7 @@ LayoutUnit ValueForLength(const Length& length, LayoutUnit maximum_value) {
case Length::kExtendToZoom:
case Length::kDeviceWidth:
case Length::kDeviceHeight:
- case Length::kMaxSizeNone:
+ case Length::kNone:
NOTREACHED();
return LayoutUnit();
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/length_size.h b/chromium/third_party/blink/renderer/platform/geometry/length_size.h
index 8da2e50bbe9..a03152f6e2b 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/length_size.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/length_size.h
@@ -38,6 +38,7 @@ class LengthSize {
bool operator==(const LengthSize& o) const {
return width_ == o.width_ && height_ == o.height_;
}
+ bool operator!=(const LengthSize& o) const { return !(*this == o); }
void SetWidth(const Length& width) { width_ = width; }
const Length& Width() const { return width_; }
diff --git a/chromium/third_party/blink/renderer/platform/geometry/region.cc b/chromium/third_party/blink/renderer/platform/geometry/region.cc
index a90abdc2378..54a4ce33a34 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/region.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/region.cc
@@ -327,7 +327,7 @@ Region::Shape::SegmentIterator Region::Shape::SegmentsEnd(
return segments_.data() + segment_index;
}
-#ifndef NDEBUG
+#if DCHECK_IS_ON()
void Region::Shape::Dump() const {
for (Shape::SpanIterator span = SpansBegin(), end = SpansEnd(); span != end;
++span) {
@@ -570,7 +570,7 @@ Region::Shape Region::Shape::SubtractShapes(const Shape& shape1,
return ShapeOperation<SubtractOperation>(shape1, shape2);
}
-#ifndef NDEBUG
+#if DCHECK_IS_ON()
void Region::Dump() const {
printf("Bounds: (%d, %d, %d, %d)\n", bounds_.X(), bounds_.Y(),
bounds_.Width(), bounds_.Height());
diff --git a/chromium/third_party/blink/renderer/platform/geometry/region.h b/chromium/third_party/blink/renderer/platform/geometry/region.h
index d34815c7ca1..581d4df4574 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/region.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/region.h
@@ -73,7 +73,11 @@ class PLATFORM_EXPORT Region {
uint64_t Area() const;
-#ifndef NDEBUG
+ wtf_size_t Complexity() const {
+ return shape_.SpansSize() + shape_.SegmentsSize();
+ }
+
+#if DCHECK_IS_ON()
void Dump() const;
#endif
@@ -130,7 +134,7 @@ class PLATFORM_EXPORT Region {
static bool CompareShapes(const Shape& shape1, const Shape& shape2);
void TrimCapacities();
-#ifndef NDEBUG
+#if DCHECK_IS_ON()
void Dump() const;
#endif
diff --git a/chromium/third_party/blink/renderer/platform/graphics/DEPS b/chromium/third_party/blink/renderer/platform/graphics/DEPS
index 69ebb831274..9af9d13ba01 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/DEPS
+++ b/chromium/third_party/blink/renderer/platform/graphics/DEPS
@@ -19,9 +19,11 @@ include_rules = [
"+gpu/command_buffer/client/gpu_memory_buffer_manager.h",
"+gpu/command_buffer/client/raster_interface.h",
"+gpu/command_buffer/client/shared_image_interface.h",
+ "+gpu/command_buffer/common/gles2_cmd_copy_texture_chromium_utils.h",
"+gpu/command_buffer/common/gpu_memory_buffer_support.h",
"+gpu/command_buffer/common/capabilities.h",
"+gpu/command_buffer/common/mailbox.h",
+ "+gpu/command_buffer/common/mailbox_holder.h",
"+gpu/command_buffer/common/shared_image_usage.h",
"+gpu/command_buffer/common/sync_token.h",
"+gpu/ipc/common/mailbox.mojom-blink.h",
@@ -62,4 +64,5 @@ specific_include_rules = {
".*_test.cc": [
"+components/viz/test",
],
+ "(graphics_context|skia_utils)\.cc" : [ "+ui/base/ui_base_features.h" ]
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/OWNERS b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
index 73a65352c7d..0bb32866bbe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
@@ -13,6 +13,7 @@ vollick@chromium.org
# For surface ID propagation and synchronization
samans@chromium.org
+jonross@chromium.org
# lowLatency canvas
mcasas@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
index 22135712d5d..08d74cb21d7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -4,51 +4,88 @@
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
+#include <memory>
+#include <utility>
+
#include "components/viz/common/resources/single_release_callback.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
-#include "third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
-#include "third_party/blink/renderer/platform/graphics/skia_texture_holder.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/gpu/GrTexture.h"
-
-#include <memory>
-#include <utility>
namespace blink {
+namespace {
-scoped_refptr<AcceleratedStaticBitmapImage>
-AcceleratedStaticBitmapImage::CreateFromSkImage(
- sk_sp<SkImage> image,
+void ReleaseCallbackOnContextThread(
+ std::unique_ptr<viz::SingleReleaseCallback> callback,
+ const gpu::SyncToken sync_token) {
+ callback->Run(sync_token, /* is_lost = */ false);
+}
+
+} // namespace
+
+AcceleratedStaticBitmapImage::MailboxRef::MailboxRef(
+ const gpu::SyncToken& sync_token,
+ base::PlatformThreadRef context_thread_ref,
+ scoped_refptr<base::SingleThreadTaskRunner> context_task_runner,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback)
+ : sync_token_(sync_token),
+ context_thread_ref_(context_thread_ref),
+ context_task_runner_(std::move(context_task_runner)),
+ release_callback_(std::move(release_callback)) {
+ DCHECK(!is_cross_thread() || sync_token_.verified_flush());
+}
+
+AcceleratedStaticBitmapImage::MailboxRef::~MailboxRef() {
+ if (context_thread_ref_ == base::PlatformThread::CurrentRef()) {
+ ReleaseCallbackOnContextThread(std::move(release_callback_), sync_token_);
+ } else {
+ context_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ReleaseCallbackOnContextThread,
+ std::move(release_callback_), sync_token_));
+ }
+}
+
+const gpu::SyncToken&
+AcceleratedStaticBitmapImage::MailboxRef::GetOrCreateSyncToken(
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
context_provider_wrapper) {
- CHECK(image && image->isTextureBacked());
- return base::AdoptRef(new AcceleratedStaticBitmapImage(
- std::move(image), std::move(context_provider_wrapper)));
+ if (!sync_token_.HasData()) {
+ DCHECK(!is_cross_thread());
+ DCHECK(context_provider_wrapper);
+ context_provider_wrapper->ContextProvider()
+ ->InterfaceBase()
+ ->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData());
+ }
+ return sync_token_;
}
-scoped_refptr<AcceleratedStaticBitmapImage>
-AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
- const gpu::Mailbox& mailbox,
- const gpu::SyncToken& sync_token,
- unsigned texture_id,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper,
- IntSize mailbox_size,
- bool is_origin_top_left) {
- return base::AdoptRef(new AcceleratedStaticBitmapImage(
- mailbox, sync_token, texture_id, std::move(context_provider_wrapper),
- mailbox_size, is_origin_top_left));
+// static
+void AcceleratedStaticBitmapImage::ReleaseTexture(void* ctx) {
+ auto* release_ctx = static_cast<ReleaseContext*>(ctx);
+ if (release_ctx->context_provider_wrapper) {
+ if (release_ctx->texture_id) {
+ auto* ri = release_ctx->context_provider_wrapper->ContextProvider()
+ ->RasterInterface();
+ ri->EndSharedImageAccessDirectCHROMIUM(release_ctx->texture_id);
+ ri->DeleteGpuRasterTexture(release_ctx->texture_id);
+ }
+ }
+
+ delete release_ctx;
}
+// static
scoped_refptr<AcceleratedStaticBitmapImage>
AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
const gpu::Mailbox& mailbox,
@@ -56,38 +93,16 @@ AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
GLuint shared_image_texture_id,
const SkImageInfo& sk_image_info,
GLenum texture_target,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
- PlatformThreadId context_thread_id,
bool is_origin_top_left,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
+ base::PlatformThreadRef context_thread_ref,
+ scoped_refptr<base::SingleThreadTaskRunner> context_task_runner,
std::unique_ptr<viz::SingleReleaseCallback> release_callback) {
return base::AdoptRef(new AcceleratedStaticBitmapImage(
mailbox, sync_token, shared_image_texture_id, sk_image_info,
- texture_target, std::move(context_provider_wrapper), context_thread_id,
- is_origin_top_left, std::move(release_callback)));
-}
-
-AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
- sk_sp<SkImage> image,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper)
- : paint_image_content_id_(cc::PaintImage::GetNextContentId()) {
- CHECK(image && image->isTextureBacked());
- skia_texture_holder_ = std::make_unique<SkiaTextureHolder>(
- std::move(image), std::move(context_provider_wrapper));
-}
-
-AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
- const gpu::Mailbox& mailbox,
- const gpu::SyncToken& sync_token,
- unsigned texture_id,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper,
- IntSize mailbox_size,
- bool is_origin_top_left)
- : paint_image_content_id_(cc::PaintImage::GetNextContentId()) {
- mailbox_texture_holder_ = std::make_unique<MailboxTextureHolder>(
- mailbox, sync_token, texture_id, std::move(context_provider_wrapper),
- mailbox_size, is_origin_top_left);
+ texture_target, is_origin_top_left, kDefaultImageOrientation,
+ std::move(context_provider_wrapper), context_thread_ref,
+ std::move(context_task_runner), std::move(release_callback)));
}
AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
@@ -96,92 +111,44 @@ AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
GLuint shared_image_texture_id,
const SkImageInfo& sk_image_info,
GLenum texture_target,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper,
- PlatformThreadId context_thread_id,
bool is_origin_top_left,
+ const ImageOrientation& orientation,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
+ base::PlatformThreadRef context_thread_ref,
+ scoped_refptr<base::SingleThreadTaskRunner> context_task_runner,
std::unique_ptr<viz::SingleReleaseCallback> release_callback)
- : mailbox_ref_(base::MakeRefCounted<TextureHolder::MailboxRef>(
- std::move(release_callback))),
+ : StaticBitmapImage(orientation),
+ mailbox_(mailbox),
+ sk_image_info_(sk_image_info),
+ texture_target_(texture_target),
+ is_origin_top_left_(is_origin_top_left),
+ context_provider_wrapper_(std::move(context_provider_wrapper)),
+ mailbox_ref_(
+ base::MakeRefCounted<MailboxRef>(sync_token,
+ context_thread_ref,
+ std::move(context_task_runner),
+ std::move(release_callback))),
paint_image_content_id_(cc::PaintImage::GetNextContentId()) {
- mailbox_texture_holder_ = std::make_unique<MailboxTextureHolder>(
- mailbox, sync_token, std::move(context_provider_wrapper), mailbox_ref_,
- context_thread_id, sk_image_info, texture_target, is_origin_top_left);
- if (shared_image_texture_id) {
- skia_texture_holder_ = std::make_unique<SkiaTextureHolder>(
- mailbox_texture_holder_.get(), shared_image_texture_id);
- }
-}
-
-namespace {
-
-void DestroySkImageOnOriginalThread(
- sk_sp<SkImage> image,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
- std::unique_ptr<gpu::SyncToken> sync_token) {
- if (context_provider_wrapper &&
- image->isValid(
- context_provider_wrapper->ContextProvider()->GetGrContext())) {
- if (sync_token->HasData()) {
- // To make sure skia does not recycle the texture while it is still in use
- // by another context.
- context_provider_wrapper->ContextProvider()
- ->ContextGL()
- ->WaitSyncTokenCHROMIUM(sync_token->GetData());
- }
- // In case texture was used by compositor, which may have changed params.
- image->getTexture()->textureParamsModified();
- }
- image.reset();
-}
-
-} // namespace
-
-AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(mailbox_.IsSharedImage());
- // If the original SkImage was retained, it must be destroyed on the thread
- // where it came from. In the same thread case, there is nothing to do because
- // the regular destruction flow is fine.
- if (original_skia_image_) {
- std::unique_ptr<gpu::SyncToken> sync_token =
- base::WrapUnique(new gpu::SyncToken(GetSyncToken()));
- if (!original_skia_image_task_runner_->BelongsToCurrentThread()) {
- PostCrossThreadTask(
- *original_skia_image_task_runner_, FROM_HERE,
- CrossThreadBindOnce(
- &DestroySkImageOnOriginalThread, std::move(original_skia_image_),
- std::move(original_skia_image_context_provider_wrapper_),
- WTF::Passed(std::move(sync_token))));
- } else {
- DestroySkImageOnOriginalThread(
- std::move(original_skia_image_),
- std::move(original_skia_image_context_provider_wrapper_),
- std::move(sync_token));
- }
- }
+ if (shared_image_texture_id)
+ InitializeSkImage(shared_image_texture_id);
}
-void AcceleratedStaticBitmapImage::RetainOriginalSkImage() {
+AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- DCHECK(skia_texture_holder_);
- original_skia_image_ = skia_texture_holder_->GetSkImage();
- original_skia_image_context_provider_wrapper_ = ContextProviderWrapper();
- DCHECK(original_skia_image_);
-
- original_skia_image_task_runner_ = Thread::Current()->GetTaskRunner();
}
IntSize AcceleratedStaticBitmapImage::Size() const {
- return texture_holder()->Size();
+ return IntSize(sk_image_info_.width(), sk_image_info_.height());
}
scoped_refptr<StaticBitmapImage>
AcceleratedStaticBitmapImage::MakeUnaccelerated() {
CreateImageFromMailboxIfNeeded();
return UnacceleratedStaticBitmapImage::Create(
- skia_texture_holder_->GetSkImage()->makeNonTextureImage());
+ sk_image_->makeNonTextureImage(), orientation_);
}
bool AcceleratedStaticBitmapImage::CopyToTexture(
@@ -197,49 +164,34 @@ bool AcceleratedStaticBitmapImage::CopyToTexture(
if (!IsValid())
return false;
- // TODO(junov) : could reduce overhead by using kOrderingBarrier when we know
- // that the source and destination context or on the same stream.
- EnsureMailbox(kUnverifiedSyncToken, GL_NEAREST);
-
// This method should only be used for cross-context copying, otherwise it's
// wasting overhead.
- DCHECK(mailbox_texture_holder_->IsCrossThread() ||
- dest_gl != ContextProviderWrapper()->ContextProvider()->ContextGL());
-
- bool is_shared_image = mailbox_texture_holder_->GetMailbox().IsSharedImage();
+ DCHECK(mailbox_ref_->is_cross_thread() ||
+ dest_gl != ContextProvider()->ContextGL());
+ DCHECK(mailbox_.IsSharedImage());
// Get a texture id that |destProvider| knows about and copy from it.
dest_gl->WaitSyncTokenCHROMIUM(
- mailbox_texture_holder_->GetSyncToken().GetConstData());
- GLuint source_texture_id;
- if (is_shared_image) {
- source_texture_id = dest_gl->CreateAndTexStorage2DSharedImageCHROMIUM(
- mailbox_texture_holder_->GetMailbox().name);
- dest_gl->BeginSharedImageAccessDirectCHROMIUM(
- source_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
- } else {
- source_texture_id = dest_gl->CreateAndConsumeTextureCHROMIUM(
- mailbox_texture_holder_->GetMailbox().name);
- }
+ mailbox_ref_->GetOrCreateSyncToken(ContextProviderWrapper())
+ .GetConstData());
+ GLuint source_texture_id =
+ dest_gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox_.name);
+ dest_gl->BeginSharedImageAccessDirectCHROMIUM(
+ source_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
dest_gl->CopySubTextureCHROMIUM(
source_texture_id, 0, dest_target, dest_texture_id, dest_level,
dest_point.X(), dest_point.Y(), source_sub_rectangle.X(),
source_sub_rectangle.Y(), source_sub_rectangle.Width(),
source_sub_rectangle.Height(), unpack_flip_y ? GL_FALSE : GL_TRUE,
GL_FALSE, unpack_premultiply_alpha ? GL_FALSE : GL_TRUE);
- if (is_shared_image) {
- dest_gl->EndSharedImageAccessDirectCHROMIUM(source_texture_id);
- }
- // This drops the |destGL| context's reference on our |m_mailbox|, but it's
- // still held alive by our SkImage.
+ dest_gl->EndSharedImageAccessDirectCHROMIUM(source_texture_id);
dest_gl->DeleteTextures(1, &source_texture_id);
// We need to update the texture holder's sync token to ensure that when this
- // image is deleted, the texture resource will not be recycled by skia before
- // the above texture copy has completed.
+ // mailbox is recycled or deleted, it is done after the copy operation above.
gpu::SyncToken sync_token;
dest_gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
- mailbox_texture_holder_->UpdateSyncToken(sync_token);
+ mailbox_ref_->set_sync_token(sync_token);
return true;
}
@@ -251,31 +203,22 @@ PaintImage AcceleratedStaticBitmapImage::PaintImageForCurrentFrame() {
if (!IsValid())
return PaintImage();
- sk_sp<SkImage> image;
- if (original_skia_image_ &&
- original_skia_image_task_runner_->BelongsToCurrentThread()) {
- // We need to avoid consuming the mailbox in the context where it
- // originated. This avoids swapping back and forth between TextureHolder
- // types.
- image = original_skia_image_;
- } else {
- CreateImageFromMailboxIfNeeded();
- image = skia_texture_holder_->GetSkImage();
- }
+ CreateImageFromMailboxIfNeeded();
return CreatePaintImageBuilder()
- .set_image(image, paint_image_content_id_)
+ .set_image(sk_image_, paint_image_content_id_)
.set_completion_state(PaintImage::CompletionState::DONE)
.TakePaintImage();
}
-void AcceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
- const cc::PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- RespectImageOrientationEnum,
- ImageClampingMode image_clamping_mode,
- ImageDecodingMode decode_mode) {
+void AcceleratedStaticBitmapImage::Draw(
+ cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum should_respect_image_orientation,
+ ImageClampingMode image_clamping_mode,
+ ImageDecodingMode decode_mode) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto paint_image = PaintImageForCurrentFrame();
if (!paint_image)
@@ -287,68 +230,185 @@ void AcceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
.TakePaintImage();
}
StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect,
- image_clamping_mode, paint_image);
+ image_clamping_mode,
+ should_respect_image_orientation, paint_image);
}
bool AcceleratedStaticBitmapImage::IsValid() const {
- return texture_holder()->IsValid();
+ if (sk_image_ && (!skia_context_provider_wrapper_ ||
+ !sk_image_->isValid(ContextProvider()->GetGrContext()))) {
+ return false;
+ }
+
+ if (mailbox_ref_->is_cross_thread()) {
+ // If context is is from another thread, validity cannot be verified. Just
+ // assume valid. Potential problem will be detected later.
+ return true;
+ }
+
+ return !!context_provider_wrapper_;
}
WebGraphicsContext3DProvider* AcceleratedStaticBitmapImage::ContextProvider()
const {
- return texture_holder()->ContextProvider();
+ auto context = ContextProviderWrapper();
+ return context ? context->ContextProvider() : nullptr;
}
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
AcceleratedStaticBitmapImage::ContextProviderWrapper() const {
- if (!IsValid())
- return nullptr;
-
- return texture_holder()->ContextProviderWrapper();
+ return sk_image_ ? skia_context_provider_wrapper_ : context_provider_wrapper_;
}
void AcceleratedStaticBitmapImage::CreateImageFromMailboxIfNeeded() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (skia_texture_holder_)
+ if (sk_image_)
+ return;
+ InitializeSkImage(0u);
+}
+
+void AcceleratedStaticBitmapImage::InitializeSkImage(
+ GLuint shared_image_texture_id) {
+ DCHECK(!shared_image_texture_id || !mailbox_ref_->is_cross_thread());
+
+ auto context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
+ if (!context_provider_wrapper)
return;
- DCHECK(mailbox_texture_holder_);
- skia_texture_holder_ =
- std::make_unique<SkiaTextureHolder>(mailbox_texture_holder_.get(), 0u);
+ gpu::raster::RasterInterface* shared_ri =
+ context_provider_wrapper->ContextProvider()->RasterInterface();
+ GrContext* shared_gr_context =
+ context_provider_wrapper->ContextProvider()->GetGrContext();
+ DCHECK(shared_ri &&
+ shared_gr_context); // context isValid already checked in callers
+
+ GLuint shared_context_texture_id = 0u;
+ bool should_delete_texture_on_release = true;
+
+ if (shared_image_texture_id) {
+ shared_context_texture_id = shared_image_texture_id;
+ should_delete_texture_on_release = false;
+ } else {
+ shared_ri->WaitSyncTokenCHROMIUM(
+ mailbox_ref_->GetOrCreateSyncToken(context_provider_wrapper)
+ .GetConstData());
+ shared_context_texture_id =
+ shared_ri->CreateAndConsumeForGpuRaster(mailbox_);
+ shared_ri->BeginSharedImageAccessDirectCHROMIUM(
+ shared_context_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
+ }
+
+ GrGLTextureInfo texture_info;
+ texture_info.fTarget = texture_target_;
+ texture_info.fID = shared_context_texture_id;
+ texture_info.fFormat =
+ CanvasColorParams(sk_image_info_).GLSizedInternalFormat();
+ GrBackendTexture backend_texture(sk_image_info_.width(),
+ sk_image_info_.height(), GrMipMapped::kNo,
+ texture_info);
+
+ GrSurfaceOrigin origin = IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin
+ : kBottomLeft_GrSurfaceOrigin;
+
+ auto* release_ctx = new ReleaseContext;
+ release_ctx->mailbox_ref = mailbox_ref_;
+ if (should_delete_texture_on_release)
+ release_ctx->texture_id = shared_context_texture_id;
+ release_ctx->context_provider_wrapper = context_provider_wrapper;
+
+ sk_image_ = SkImage::MakeFromTexture(
+ shared_gr_context, backend_texture, origin, sk_image_info_.colorType(),
+ sk_image_info_.alphaType(), sk_image_info_.refColorSpace(),
+ &ReleaseTexture, release_ctx);
+ if (!sk_image_)
+ ReleaseTexture(release_ctx);
+ else
+ skia_context_provider_wrapper_ = std::move(context_provider_wrapper);
}
-void AcceleratedStaticBitmapImage::EnsureMailbox(MailboxSyncMode mode,
- GLenum filter) {
+void AcceleratedStaticBitmapImage::EnsureSyncTokenVerified() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (!mailbox_texture_holder_) {
- TRACE_EVENT0("blink", "AcceleratedStaticBitmapImage::EnsureMailbox");
-
- if (!original_skia_image_) {
- // To ensure that the texture resource stays alive we only really need
- // to retain the source SkImage until the mailbox is consumed, but this
- // works too.
- RetainOriginalSkImage();
- }
- mailbox_texture_holder_ = std::make_unique<MailboxTextureHolder>(
- skia_texture_holder_.get(), filter);
+ if (mailbox_ref_->verified_flush())
+ return;
+
+ if (mailbox_ref_->is_cross_thread()) {
+ // Was originally created on another thread. Should already have a sync
+ // token from the original source context, already verified if needed.
+ NOTREACHED() << "Cross-thread SyncToken should already be verified.";
+ return;
}
- mailbox_texture_holder_->Sync(mode);
+
+ if (!ContextProviderWrapper())
+ return;
+
+ auto sync_token =
+ mailbox_ref_->GetOrCreateSyncToken(ContextProviderWrapper());
+ int8_t* token_data = sync_token.GetData();
+ ContextProvider()->InterfaceBase()->VerifySyncTokensCHROMIUM(&token_data, 1);
+ sync_token.SetVerifyFlush();
+ mailbox_ref_->set_sync_token(sync_token);
+}
+
+gpu::MailboxHolder AcceleratedStaticBitmapImage::GetMailboxHolder() const {
+ if (!IsValid())
+ return gpu::MailboxHolder();
+
+ return gpu::MailboxHolder(
+ mailbox_, mailbox_ref_->GetOrCreateSyncToken(ContextProviderWrapper()),
+ texture_target_);
}
void AcceleratedStaticBitmapImage::Transfer() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- EnsureMailbox(kVerifiedSyncToken, GL_NEAREST);
+ EnsureSyncTokenVerified();
- // Release the SkiaTextureHolder, this SkImage is no longer valid to use
+ // SkImage is bound to the current thread so is no longer valid to use
// cross-thread.
- skia_texture_holder_.reset();
+ sk_image_.reset();
DETACH_FROM_THREAD(thread_checker_);
}
bool AcceleratedStaticBitmapImage::CurrentFrameKnownToBeOpaque() {
- return texture_holder()->CurrentFrameKnownToBeOpaque();
+ return sk_image_info_.isOpaque();
+}
+
+scoped_refptr<StaticBitmapImage>
+AcceleratedStaticBitmapImage::ConvertToColorSpace(
+ sk_sp<SkColorSpace> color_space,
+ SkColorType color_type) {
+ DCHECK(color_space);
+ DCHECK(color_type == kRGBA_F16_SkColorType ||
+ color_type == kRGBA_8888_SkColorType);
+
+ if (!ContextProviderWrapper())
+ return nullptr;
+
+ sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
+ if (SkColorSpace::Equals(color_space.get(), skia_image->colorSpace()) &&
+ color_type == skia_image->colorType()) {
+ return this;
+ }
+
+ auto image_info = skia_image->imageInfo()
+ .makeColorSpace(color_space)
+ .makeColorType(color_type);
+
+ auto usage_flags = ContextProviderWrapper()
+ ->ContextProvider()
+ ->SharedImageInterface()
+ ->UsageForMailbox(mailbox_);
+ auto provider = CanvasResourceProvider::CreateSharedImageProvider(
+ Size(), ContextProviderWrapper(), kLow_SkFilterQuality,
+ CanvasColorParams(image_info), IsOriginTopLeft(),
+ CanvasResourceProvider::RasterMode::kGPU, usage_flags);
+ if (!provider) {
+ return nullptr;
+ }
+
+ provider->Canvas()->drawImage(PaintImageForCurrentFrame(), 0, 0, nullptr);
+ return provider->Snapshot(orientation_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
index f89408d112d..2b04e048281 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
@@ -10,12 +10,9 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
-#include "third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h"
-#include "third_party/blink/renderer/platform/graphics/skia_texture_holder.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-class GrContext;
struct SkImageInfo;
namespace viz {
@@ -30,29 +27,10 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
public:
~AcceleratedStaticBitmapImage() override;
- // SkImage with a texture backing.
- // DO NOT USE. This is in the process of being removed. See crbug.com/962630.
- static scoped_refptr<AcceleratedStaticBitmapImage> CreateFromSkImage(
- sk_sp<SkImage>,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>);
-
- // Can specify the GrContext that created the texture backing. Ideally all
- // callers would use this option.
- // The |mailbox| is a name for the texture backing, allowing other contexts to
- // use the same backing.
- static scoped_refptr<AcceleratedStaticBitmapImage>
- CreateFromWebGLContextImage(
- const gpu::Mailbox&,
- const gpu::SyncToken&,
- unsigned texture_id,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
- IntSize mailbox_size,
- bool is_origin_top_left);
-
- // Creates an image wrapping a shared image mailbox. |release_callback| is a
- // callback to be invoked when this mailbox/texture can be safely destroyed.
- // It can be invoked on any thread. Note that it is assumed that the mailbox
- // can only be used for read operations, no writes are allowed.
+ // Creates an image wrapping a shared image mailbox.
+ //
+ // |sync_token| is the token that must be waited on before reading the
+ // contents of this mailbox.
//
// |shared_image_texture_id| is an optional texture bound to the shared image
// mailbox imported into the provided context. If provided the caller must
@@ -60,28 +38,42 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
// and has a read lock on the shared image until the |release_callback| is
// invoked.
//
- // If the image is created on a different thread than |context_thread_id| then
- // the provided sync_token must be verified and no |shared_image_texture_id|
- // should be provided.
+ // |sk_image_info| provides the metadata associated with the backing.
+ //
+ // |texture_target| is the target that the texture should be bound to if the
+ // backing is used with GL.
+ //
+ // |is_origin_top_left| indicates whether the origin in texture space
+ // corresponds to the top-left content pixel.
+ //
+ // |context_provider| is the context that the mailbox was created with.
+ // |context_thread_ref| and |context_task_runner| refer to the thread the
+ // context is bound to. If the image is created on a different thread than
+ // |context_thread_ref| then the provided sync_token must be verified and no
+ // |shared_image_texture_id| should be provided.
+ //
+ // |release_callback| is a callback to be invoked when this mailbox can be
+ // safely destroyed. It is guaranteed to be invoked on the context thread.
+ //
+ // Note that it is assumed that the mailbox can only be used for read
+ // operations, no writes are allowed.
static scoped_refptr<AcceleratedStaticBitmapImage> CreateFromCanvasMailbox(
const gpu::Mailbox&,
const gpu::SyncToken&,
GLuint shared_image_texture_id,
const SkImageInfo& sk_image_info,
GLenum texture_target,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
- PlatformThreadId context_thread_id,
bool is_origin_top_left,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
+ base::PlatformThreadRef context_thread_ref,
+ scoped_refptr<base::SingleThreadTaskRunner> context_task_runner,
std::unique_ptr<viz::SingleReleaseCallback> release_callback);
bool CurrentFrameKnownToBeOpaque() override;
IntSize Size() const override;
bool IsTextureBacked() const override { return true; }
- scoped_refptr<StaticBitmapImage> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_wrapper)
- override {
- return this;
- }
+ scoped_refptr<StaticBitmapImage> ConvertToColorSpace(sk_sp<SkColorSpace>,
+ SkColorType) override;
void Draw(cc::PaintCanvas*,
const cc::PaintFlags&,
@@ -105,82 +97,90 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
bool unpack_flip_y,
const IntPoint& dest_point,
const IntRect& source_sub_rectangle) override;
-
- bool HasMailbox() const final { return !!mailbox_texture_holder_; }
- // To be called on sender thread before performing a transfer
+ // To be called on sender thread before performing a transfer to a different
+ // thread.
void Transfer() final;
- void EnsureMailbox(MailboxSyncMode, GLenum filter) final;
+ // Makes sure that the sync token associated with this mailbox is verified.
+ void EnsureSyncTokenVerified() final;
- const gpu::Mailbox& GetMailbox() const final {
- static const gpu::Mailbox mailbox;
- return mailbox_texture_holder_ ? mailbox_texture_holder_->GetMailbox()
- : mailbox;
- }
- const gpu::SyncToken& GetSyncToken() const final {
- static const gpu::SyncToken sync_token;
- return mailbox_texture_holder_ ? mailbox_texture_holder_->GetSyncToken()
- : sync_token;
+ // Updates the sync token that must be waited on before recycling or deleting
+ // the mailbox for this image. This must be set by callers using the mailbox
+ // externally to this class.
+ void UpdateSyncToken(const gpu::SyncToken& sync_token) final {
+ mailbox_ref_->set_sync_token(sync_token);
}
+ // Provides the mailbox backing for this image. The caller must wait on the
+ // sync token before accessing this mailbox.
+ gpu::MailboxHolder GetMailboxHolder() const final;
+ bool IsOriginTopLeft() const final { return is_origin_top_left_; }
+
PaintImage PaintImageForCurrentFrame() override;
private:
- AcceleratedStaticBitmapImage(
- sk_sp<SkImage>,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&);
- AcceleratedStaticBitmapImage(
- const gpu::Mailbox&,
- const gpu::SyncToken&,
- unsigned texture_id,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
- IntSize mailbox_size,
- bool is_origin_top_left);
+ class MailboxRef : public ThreadSafeRefCounted<MailboxRef> {
+ public:
+ MailboxRef(const gpu::SyncToken& sync_token,
+ base::PlatformThreadRef context_thread_ref,
+ scoped_refptr<base::SingleThreadTaskRunner> context_task_runner,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback);
+ ~MailboxRef();
+
+ bool is_cross_thread() const {
+ return base::PlatformThread::CurrentRef() != context_thread_ref_;
+ }
+ void set_sync_token(gpu::SyncToken token) { sync_token_ = token; }
+ const gpu::SyncToken& GetOrCreateSyncToken(
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>);
+ bool verified_flush() { return sync_token_.verified_flush(); }
+
+ private:
+ gpu::SyncToken sync_token_;
+ const base::PlatformThreadRef context_thread_ref_;
+ const scoped_refptr<base::SingleThreadTaskRunner> context_task_runner_;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback_;
+ };
+
+ struct ReleaseContext {
+ scoped_refptr<MailboxRef> mailbox_ref;
+ GLuint texture_id = 0u;
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper;
+ };
+
+ static void ReleaseTexture(void* ctx);
+
AcceleratedStaticBitmapImage(
const gpu::Mailbox&,
const gpu::SyncToken&,
GLuint shared_image_texture_id,
const SkImageInfo& sk_image_info,
GLenum texture_target,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
- PlatformThreadId context_thread_id,
bool is_origin_top_left,
+ const ImageOrientation& orientation,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
+ base::PlatformThreadRef context_thread_ref,
+ scoped_refptr<base::SingleThreadTaskRunner> context_task_runner,
std::unique_ptr<viz::SingleReleaseCallback> release_callback);
void CreateImageFromMailboxIfNeeded();
- void WaitSyncTokenIfNeeded();
- void RetainOriginalSkImage();
-
- // TODO(khushalsagar): Its unclear what to use here for calls checking IsValid
- // or querying the ContextProvider for the image. This can differ in the 2,
- // for instance if the image was transferred between threads.
- const TextureHolder* texture_holder() const {
- if (skia_texture_holder_)
- return skia_texture_holder_.get();
- return mailbox_texture_holder_.get();
- }
+ void InitializeSkImage(GLuint shared_image_texture_id);
- scoped_refptr<TextureHolder::MailboxRef> mailbox_ref_;
+ const gpu::Mailbox mailbox_;
+ const SkImageInfo sk_image_info_;
+ const GLenum texture_target_;
+ const bool is_origin_top_left_;
- // The image is created with one of the texture holders below while the other
- // one is created lazily if needed and then persisted for the lifetime of the
- // image on a particular thread.
- // When Transfer is called, the image is detached from its current thread to
- // allow it to be used on a different thread. We create(if needed) and cache
- // the mailbox in this case, so the texture can be used with a different
- // context. The skia texture holder is released since the mailbox needs to be
- // imported into the GrContext on the new thread.
- std::unique_ptr<SkiaTextureHolder> skia_texture_holder_;
- std::unique_ptr<MailboxTextureHolder> mailbox_texture_holder_;
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
+ scoped_refptr<MailboxRef> mailbox_ref_;
- THREAD_CHECKER(thread_checker_);
- PaintImage::ContentId paint_image_content_id_;
-
- // For RetainOriginalSkImageForCopyOnWrite()
- sk_sp<SkImage> original_skia_image_;
- scoped_refptr<base::SingleThreadTaskRunner> original_skia_image_task_runner_;
+ // The context this SkImage is bound to.
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- original_skia_image_context_provider_wrapper_;
+ skia_context_provider_wrapper_;
+ sk_sp<SkImage> sk_image_;
+
+ PaintImage::ContentId paint_image_content_id_;
+ THREAD_CHECKER(thread_checker_);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
index 8f2ff90fddf..5fbfd9887e2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
@@ -4,12 +4,17 @@
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
+#include "base/test/null_task_runner.h"
#include "base/test/task_environment.h"
+#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/test/test_gles2_interface.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -25,12 +30,16 @@ using testing::SetArgPointee;
using testing::SetArrayArgument;
using testing::Test;
-class MockGLES2InterfaceWithSyncTokenSupport : public FakeGLES2Interface {
+class MockGLES2InterfaceWithSyncTokenSupport : public viz::TestGLES2Interface {
public:
MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*));
MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte*));
};
+GLbyte SyncTokenMatcher(const gpu::SyncToken& token) {
+ return reinterpret_cast<const GLbyte*>(&token)[0];
+}
+
gpu::SyncToken GenTestSyncToken(GLbyte id) {
gpu::SyncToken token;
// Store id in the first byte
@@ -38,89 +47,63 @@ gpu::SyncToken GenTestSyncToken(GLbyte id) {
return token;
}
-GLbyte SyncTokenMatcher(const gpu::SyncToken& token) {
- return reinterpret_cast<const GLbyte*>(&token)[0];
+scoped_refptr<StaticBitmapImage> CreateBitmap() {
+ auto mailbox = gpu::Mailbox::GenerateForSharedImage();
+ auto release_callback = viz::SingleReleaseCallback::Create(
+ base::BindOnce([](const gpu::SyncToken&, bool) {}));
+ return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
+ mailbox, GenTestSyncToken(100), 0, SkImageInfo::MakeN32Premul(100, 100),
+ GL_TEXTURE_2D, true, SharedGpuContext::ContextProviderWrapper(),
+ base::PlatformThread::CurrentRef(),
+ base::MakeRefCounted<base::NullTaskRunner>(),
+ std::move(release_callback));
}
class AcceleratedStaticBitmapImageTest : public Test {
public:
void SetUp() override {
- auto factory = [](MockGLES2InterfaceWithSyncTokenSupport* gl,
- bool* gpu_compositing_disabled)
- -> std::unique_ptr<WebGraphicsContext3DProvider> {
- *gpu_compositing_disabled = false;
- return std::make_unique<FakeWebGraphicsContext3DProvider>(gl, nullptr);
- };
- SharedGpuContext::SetContextProviderFactoryForTesting(
- WTF::BindRepeating(factory, WTF::Unretained(&gl_)));
+ auto gl = std::make_unique<MockGLES2InterfaceWithSyncTokenSupport>();
+ gl_ = gl.get();
+ context_provider_ = viz::TestContextProvider::Create(std::move(gl));
+ InitializeSharedGpuContext(context_provider_.get());
+ }
+ void TearDown() override {
+ gl_ = nullptr;
+ SharedGpuContext::ResetForTesting();
}
- void TearDown() override { SharedGpuContext::ResetForTesting(); }
protected:
base::test::TaskEnvironment task_environment_;
- MockGLES2InterfaceWithSyncTokenSupport gl_;
+ MockGLES2InterfaceWithSyncTokenSupport* gl_;
+ scoped_refptr<viz::TestContextProvider> context_provider_;
};
-TEST_F(AcceleratedStaticBitmapImageTest, NoTextureHolderThrashing) {
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper =
- SharedGpuContext::ContextProviderWrapper();
- GrContext* gr = context_provider_wrapper->ContextProvider()->GetGrContext();
- SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(100, 100);
-
- sk_sp<SkSurface> surface =
- SkSurface::MakeRenderTarget(gr, SkBudgeted::kNo, imageInfo);
-
- SkPaint paint;
- surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), paint);
-
- sk_sp<SkImage> image = surface->makeImageSnapshot();
- scoped_refptr<AcceleratedStaticBitmapImage> bitmap =
- AcceleratedStaticBitmapImage::CreateFromSkImage(image,
- context_provider_wrapper);
+TEST_F(AcceleratedStaticBitmapImageTest, SkImageCached) {
+ auto bitmap = CreateBitmap();
sk_sp<SkImage> stored_image =
bitmap->PaintImageForCurrentFrame().GetSkImage();
- EXPECT_EQ(stored_image.get(), image.get());
-
- bitmap->EnsureMailbox(kUnverifiedSyncToken, GL_LINEAR);
-
- // Verify that calling PaintImageForCurrentFrame does not swap out of mailbox
- // mode. It should use the cached original image instead.
- stored_image = bitmap->PaintImageForCurrentFrame().GetSkImage();
-
- EXPECT_EQ(stored_image.get(), image.get());
+ auto stored_image2 = bitmap->PaintImageForCurrentFrame().GetSkImage();
+ EXPECT_EQ(stored_image.get(), stored_image2.get());
}
TEST_F(AcceleratedStaticBitmapImageTest, CopyToTextureSynchronization) {
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper =
- SharedGpuContext::ContextProviderWrapper();
- GrContext* gr = context_provider_wrapper->ContextProvider()->GetGrContext();
- SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(100, 100);
- sk_sp<SkSurface> surface =
- SkSurface::MakeRenderTarget(gr, SkBudgeted::kNo, imageInfo);
-
- sk_sp<SkImage> image = surface->makeImageSnapshot();
- scoped_refptr<AcceleratedStaticBitmapImage> bitmap =
- AcceleratedStaticBitmapImage::CreateFromSkImage(image,
- context_provider_wrapper);
+ auto bitmap = CreateBitmap();
MockGLES2InterfaceWithSyncTokenSupport destination_gl;
- testing::Mock::VerifyAndClearExpectations(&gl_);
+ testing::Mock::VerifyAndClearExpectations(gl_);
testing::Mock::VerifyAndClearExpectations(&destination_gl);
InSequence s; // Indicate to gmock that order of EXPECT_CALLs is important
- // Anterior synchronization
- const gpu::SyncToken sync_token1 = GenTestSyncToken(1);
- EXPECT_CALL(gl_, GenUnverifiedSyncTokenCHROMIUM(_))
- .WillOnce(SetArrayArgument<0>(
- sync_token1.GetConstData(),
- sync_token1.GetConstData() + sizeof(gpu::SyncToken)));
- EXPECT_CALL(destination_gl,
- WaitSyncTokenCHROMIUM(Pointee(SyncTokenMatcher(sync_token1))));
+ // Anterior synchronization. Wait on the sync token for the mailbox on the
+ // dest context.
+ EXPECT_CALL(destination_gl, WaitSyncTokenCHROMIUM(Pointee(SyncTokenMatcher(
+ bitmap->GetMailboxHolder().sync_token))));
- // Posterior synchronization
+ // Posterior synchronization. Generate a sync token on the destination context
+ // to ensure mailbox is destroyed after the copy.
const gpu::SyncToken sync_token2 = GenTestSyncToken(2);
EXPECT_CALL(destination_gl, GenUnverifiedSyncTokenCHROMIUM(_))
.WillOnce(SetArrayArgument<0>(
@@ -129,25 +112,16 @@ TEST_F(AcceleratedStaticBitmapImageTest, CopyToTextureSynchronization) {
IntPoint dest_point(0, 0);
IntRect source_sub_rectangle(0, 0, 10, 10);
- bitmap->CopyToTexture(
+ ASSERT_TRUE(bitmap->CopyToTexture(
&destination_gl, GL_TEXTURE_2D, 1 /*dest_texture_id*/,
0 /*dest_texture_level*/, false /*unpack_premultiply_alpha*/,
- false /*unpack_flip_y*/, dest_point, source_sub_rectangle);
+ false /*unpack_flip_y*/, dest_point, source_sub_rectangle));
testing::Mock::VerifyAndClearExpectations(&gl_);
testing::Mock::VerifyAndClearExpectations(&destination_gl);
- // Note the following expectation is commented-out because the
- // MailboxTextureHolder destructor skips it when the texture ID is 0.
- // The ID is zero because skia detected that it is being used with a fake
- // context, so this problem can't be solved by just mocking GenTextures to
- // make it produce non-zero IDs.
- // TODO(junov): fix this!
-
// Final wait is postponed until destruction.
- // EXPECT_CALL(gl_,
- // WaitSyncTokenCHROMIUM(Pointee(SyncTokenMatcher(sync_token2)))); bitmap =
- // nullptr;
+ EXPECT_EQ(bitmap->GetMailboxHolder().sync_token, sync_token2);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h
index a35b7834192..deaa02ab7c3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h
@@ -19,7 +19,7 @@ class PLATFORM_EXPORT AnimationWorkletMutator : public GarbageCollectedMixin {
// Runs the animation frame callback.
virtual std::unique_ptr<AnimationWorkletOutput> Mutate(
std::unique_ptr<AnimationWorkletInput>) = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
index 64144689835..e34a9cccf59 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
@@ -199,9 +199,9 @@ void AnimationWorkletMutatorDispatcherImpl::MutateAsynchronouslyInternal(
DCHECK(host_queue_->BelongsToCurrentThread());
on_async_mutation_complete_ = std::move(done_callback);
int next_async_mutation_id = GetNextAsyncMutationId();
- TRACE_EVENT_ASYNC_BEGIN0("cc",
- "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
- next_async_mutation_id);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+ "cc", "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
+ TRACE_ID_LOCAL(next_async_mutation_id));
CrossThreadOnceClosure on_done = CrossThreadBindOnce(
[](scoped_refptr<base::SingleThreadTaskRunner> host_queue,
@@ -239,9 +239,9 @@ void AnimationWorkletMutatorDispatcherImpl::AsyncMutationsDone(
}
// The trace event deos not include queuing time. It covers the interval
// between dispatching the request and retrieving the results.
- TRACE_EVENT_ASYNC_END0("cc",
- "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
- async_mutation_id);
+ TRACE_EVENT_NESTABLE_ASYNC_END0(
+ "cc", "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
+ TRACE_ID_LOCAL(async_mutation_id));
// The Async mutation duration is the total time between request and
// completion, and thus includes queuing time.
UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
index 9524ea33884..624f216a509 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/single_thread_task_runner.h"
#include "services/viz/public/mojom/compositing/frame_timing_details.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "ui/gfx/mojom/presentation_feedback.mojom-blink.h"
@@ -64,7 +64,7 @@ void BeginFrameProvider::CreateCompositorFrameSinkIfNeeded() {
base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
provider.BindNewPipeAndPassReceiver());
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
index effb974b2a2..e7faefdc617 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -115,8 +115,7 @@ PaintImage BitmapImage::PaintImageForTesting() {
PaintImage BitmapImage::CreatePaintImage() {
sk_sp<PaintImageGenerator> generator =
- decoder_ ? decoder_->CreateGenerator(PaintImage::kDefaultFrameIndex)
- : nullptr;
+ decoder_ ? decoder_->CreateGenerator() : nullptr;
if (!generator)
return PaintImage();
@@ -157,6 +156,11 @@ IntSize BitmapImage::SizeRespectingOrientation() const {
return size_respecting_orientation_;
}
+bool BitmapImage::HasDefaultOrientation() const {
+ ImageOrientation orientation = CurrentFrameOrientation();
+ return orientation == kDefaultImageOrientation;
+}
+
bool BitmapImage::GetHotSpot(IntPoint& hot_spot) const {
return decoder_ && decoder_->HotSpot(hot_spot);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
index b73b4caf454..b36599efbd7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
@@ -36,9 +36,9 @@
#include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/image_animation_policy.h"
-#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
#include "third_party/blink/renderer/platform/image-decoders/image_animation.h"
#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -65,7 +65,8 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
bool CurrentFrameHasSingleSecurityOrigin() const override;
IntSize Size() const override;
- IntSize SizeRespectingOrientation() const;
+ IntSize SizeRespectingOrientation() const override;
+ bool HasDefaultOrientation() const override;
bool GetHotSpot(IntPoint&) const override;
String FilenameExtension() const override;
@@ -91,7 +92,7 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
bool CurrentFrameIsLazyDecoded() override;
size_t FrameCount() override;
PaintImage PaintImageForCurrentFrame() override;
- ImageOrientation CurrentFrameOrientation() const;
+ ImageOrientation CurrentFrameOrientation() const override;
PaintImage PaintImageForTesting();
void AdvanceAnimationForTesting() override {
@@ -184,7 +185,10 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
PaintImage::AnimationSequenceId reset_animation_sequence_id_ = 0;
};
-DEFINE_IMAGE_TYPE_CASTS(BitmapImage);
+template <>
+struct DowncastTraits<BitmapImage> {
+ static bool AllowFrom(const Image& image) { return image.IsBitmapImage(); }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index 7960ab34ac8..dae80f756bc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -38,7 +38,6 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h"
@@ -75,17 +74,6 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
// Used by browser tests to detect the use of a Canvas2DLayerBridge.
TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation",
TRACE_EVENT_SCOPE_GLOBAL);
- StartRecording();
-
- // Clear the background transparent or opaque. Similar code at
- // CanvasResourceProvider::Clear().
- if (IsValid()) {
- DCHECK(recorder_);
- recorder_->getRecordingCanvas()->clear(
- color_params_.GetOpacityMode() == kOpaque ? SK_ColorBLACK
- : SK_ColorTRANSPARENT);
- DidDraw(FloatRect(0.f, 0.f, size_.Width(), size_.Height()));
- }
}
Canvas2DLayerBridge::~Canvas2DLayerBridge() {
@@ -98,7 +86,6 @@ Canvas2DLayerBridge::~Canvas2DLayerBridge() {
return;
if (acceleration_mode_ != kDisableAcceleration) {
- GraphicsLayer::UnregisterContentsLayer(layer_.get());
layer_->ClearTexture();
// Orphaning the layer is required to trigger the recreation of a new layer
// in the case where destruction is caused by a canvas resize. Test:
@@ -109,16 +96,12 @@ Canvas2DLayerBridge::~Canvas2DLayerBridge() {
layer_ = nullptr;
}
-void Canvas2DLayerBridge::StartRecording() {
- recorder_ = std::make_unique<PaintRecorder>();
- cc::PaintCanvas* canvas =
- recorder_->beginRecording(size_.Width(), size_.Height());
- // Always save an initial frame, to support resetting the top level matrix
- // and clip.
- canvas->save();
+void Canvas2DLayerBridge::SetCanvasResourceHost(CanvasResourceHost* host) {
+ resource_host_ = host;
- if (resource_host_)
- resource_host_->RestoreCanvasMatrixClipStack(canvas);
+ if (resource_host_ && GetOrCreateResourceProvider()) {
+ EnsureCleared();
+ }
}
void Canvas2DLayerBridge::ResetResourceProvider() {
@@ -297,9 +280,11 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
// circular callstack from HTMLCanvasElement.
resource_provider =
resource_host_->GetOrCreateCanvasResourceProviderImpl(adjusted_hint);
- if (!resource_provider)
+ if (!resource_provider || !resource_provider->IsValid())
return nullptr;
+ EnsureCleared();
+
if (IsAccelerated() && !layer_) {
layer_ = cc::TextureLayer::CreateForMailbox(this);
layer_->SetIsDrawable(true);
@@ -308,7 +293,6 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
layer_->SetBlendBackgroundColor(ColorParams().GetOpacityMode() != kOpaque);
layer_->SetNearestNeighbor(resource_host_->FilterQuality() ==
kNone_SkFilterQuality);
- GraphicsLayer::RegisterContentsLayer(layer_.get());
}
if (!IsHibernating())
@@ -325,13 +309,10 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
}
}
- PaintFlags copy_paint;
- copy_paint.setBlendMode(SkBlendMode::kSrc);
PaintImageBuilder builder = PaintImageBuilder::WithDefault();
builder.set_image(hibernation_image_, PaintImage::GetNextContentId());
builder.set_id(PaintImage::GetNextId());
- resource_provider->Canvas()->drawImage(builder.TakePaintImage(), 0, 0,
- &copy_paint);
+ resource_provider->RestoreBackBuffer(builder.TakePaintImage());
hibernation_image_.reset();
if (resource_host_) {
@@ -341,9 +322,14 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
return resource_provider;
}
-cc::PaintCanvas* Canvas2DLayerBridge::DrawingCanvas() {
+cc::PaintCanvas* Canvas2DLayerBridge::GetPaintCanvas() {
DCHECK(resource_host_);
- return recorder_->getRecordingCanvas();
+ // We avoid only using GetOrCreateResourceProvider() here to skip the
+ // IsValid/ContextLost checks since this is in hot code paths. The context
+ // does not need to be valid here since only the recording canvas is used.
+ if (!ResourceProvider() && !GetOrCreateResourceProvider())
+ return nullptr;
+ return ResourceProvider()->Canvas();
}
void Canvas2DLayerBridge::UpdateFilterQuality() {
@@ -418,7 +404,7 @@ void Canvas2DLayerBridge::SetIsBeingDisplayed(bool displayed) {
}
void Canvas2DLayerBridge::DrawFullImage(const cc::PaintImage& image) {
- DrawingCanvas()->drawImage(image, 0, 0);
+ GetPaintCanvas()->drawImage(image, 0, 0);
}
bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
@@ -440,30 +426,27 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
last_record_tainted_by_write_pixels_ = true;
have_recorded_draw_commands_ = false;
- // Add a save to initialize the transform/clip stack and then restore it after
- // the draw. This is needed because each recording initializes and the resets
- // this state after every flush.
- cc::PaintCanvas* canvas = ResourceProvider()->Canvas();
- PaintCanvasAutoRestore auto_restore(canvas, true);
- if (GetOrCreateResourceProvider()) {
- resource_host_->RestoreCanvasMatrixClipStack(canvas);
- }
ResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x, y);
return true;
}
void Canvas2DLayerBridge::SkipQueuedDrawCommands() {
- if (have_recorded_draw_commands_) {
- recorder_->finishRecordingAsPicture();
- StartRecording();
- have_recorded_draw_commands_ = false;
- }
+ ResourceProvider()->SkipQueuedDrawCommands();
+ have_recorded_draw_commands_ = false;
if (rate_limiter_)
rate_limiter_->Reset();
}
+void Canvas2DLayerBridge::EnsureCleared() {
+ if (cleared_)
+ return;
+ cleared_ = true;
+ ResourceProvider()->Clear();
+ DidDraw(FloatRect(0.f, 0.f, size_.Width(), size_.Height()));
+}
+
void Canvas2DLayerBridge::ClearPendingRasterTimers() {
gpu::raster::RasterInterface* raster_interface = nullptr;
if (IsAccelerated() && SharedGpuContext::ContextProviderWrapper() &&
@@ -546,8 +529,14 @@ void Canvas2DLayerBridge::FlushRecording() {
// Sample one out of every kRasterMetricProbability frames to time
// If the canvas is accelerated, we also need access to the raster_interface
- bool measure_raster_metric = (raster_interface || !IsAccelerated()) &&
- bernoulli_distribution_(random_generator_);
+
+ // We are using @dont_use_idle_scheduling_for_testing_ temporarily to always
+ // measure while testing.
+ const bool will_measure = dont_use_idle_scheduling_for_testing_ ||
+ bernoulli_distribution_(random_generator_);
+ const bool measure_raster_metric =
+ (raster_interface || !IsAccelerated()) && will_measure;
+
RasterTimer rasterTimer;
base::Optional<base::ElapsedTimer> timer;
// Start Recording the raster duration
@@ -561,16 +550,11 @@ void Canvas2DLayerBridge::FlushRecording() {
timer.emplace();
}
- { // Make a new scope so that PaintRecord gets deleted and that gets timed
- cc::PaintCanvas* canvas = ResourceProvider()->Canvas();
- last_recording_ = recorder_->finishRecordingAsPicture();
- canvas->drawPicture(last_recording_);
- last_record_tainted_by_write_pixels_ = false;
- if (!clear_frame_ || !resource_host_ || !resource_host_->IsPrinting()) {
- last_recording_ = nullptr;
- clear_frame_ = false;
- }
- ResourceProvider()->FlushSkia();
+ last_recording_ = ResourceProvider()->FlushCanvas();
+ last_record_tainted_by_write_pixels_ = false;
+ if (!clear_frame_ || !resource_host_ || !resource_host_->IsPrinting()) {
+ last_recording_ = nullptr;
+ clear_frame_ = false;
}
// Finish up the timing operation
@@ -594,7 +578,6 @@ void Canvas2DLayerBridge::FlushRecording() {
if (GetOrCreateResourceProvider())
ResourceProvider()->ReleaseLockedImages();
- StartRecording();
have_recorded_draw_commands_ = false;
}
@@ -716,6 +699,8 @@ cc::Layer* Canvas2DLayerBridge::Layer() {
}
void Canvas2DLayerBridge::DidDraw(const FloatRect& /* rect */) {
+ if (ResourceProvider() && ResourceProvider()->needs_flush())
+ FinalizeFrame();
have_recorded_draw_commands_ = true;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
index 16a2bcf63d9..8daad03dd61 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -44,7 +44,6 @@
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_host.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -113,7 +112,8 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
virtual void DidRestoreCanvasMatrixClipStack(cc::PaintCanvas*) {}
virtual bool IsAccelerated() const;
- cc::PaintCanvas* DrawingCanvas();
+ // This may recreate CanvasResourceProvider
+ cc::PaintCanvas* GetPaintCanvas();
bool IsValid();
bool WritePixels(const SkImageInfo&,
const void* pixels,
@@ -123,9 +123,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
void DontUseIdleSchedulingForTesting() {
dont_use_idle_scheduling_for_testing_ = true;
}
- void SetCanvasResourceHost(CanvasResourceHost* host) {
- resource_host_ = host;
- }
+ void SetCanvasResourceHost(CanvasResourceHost* host);
void Hibernate();
bool IsHibernating() const { return hibernation_image_ != nullptr; }
@@ -137,14 +135,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
cc::TextureLayer* layer_for_testing() { return layer_.get(); }
- // TODO(jochin): Remove this function completely once recorder_ has been
- // moved into CanvasResourceProvider.
- sk_sp<cc::PaintRecord> record_for_testing() {
- sk_sp<cc::PaintRecord> record = recorder_->finishRecordingAsPicture();
- StartRecording();
- return record;
- }
-
// The values of the enum entries must not change because they are used for
// usage metrics histograms. New values can be added to the end.
enum HibernationEvent {
@@ -198,12 +188,11 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
bool CheckResourceProviderValid();
void ResetResourceProvider();
- void StartRecording();
void SkipQueuedDrawCommands();
+ void EnsureCleared();
bool ShouldAccelerate(AccelerationHint) const;
- std::unique_ptr<PaintRecorder> recorder_;
sk_sp<SkImage> hibernation_image_;
scoped_refptr<cc::TextureLayer> layer_;
std::unique_ptr<SharedContextRateLimiter> rate_limiter_;
@@ -255,6 +244,10 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
sk_sp<cc::PaintRecord> last_recording_;
+ // This tracks whether the canvas has been cleared once after
+ // this bridge was created.
+ bool cleared_ = false;
+
base::WeakPtrFactory<Canvas2DLayerBridge> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Canvas2DLayerBridge);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index 438e238d047..fa1c188fb95 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -186,7 +186,7 @@ TEST_F(Canvas2DLayerBridgeTest, NoDrawOnContextLost) {
EXPECT_TRUE(bridge->IsValid());
PaintFlags flags;
uint32_t gen_id = bridge->GetOrCreateResourceProvider()->ContentUniqueID();
- bridge->DrawingCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ bridge->GetPaintCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
EXPECT_EQ(gen_id, bridge->GetOrCreateResourceProvider()->ContentUniqueID());
test_context_provider_->TestContextGL()->set_context_lost(true);
EXPECT_EQ(nullptr, bridge->GetOrCreateResourceProvider());
@@ -306,7 +306,7 @@ TEST_F(Canvas2DLayerBridgeTest, AccelerationHint) {
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
CanvasColorParams());
PaintFlags flags;
- bridge->DrawingCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ bridge->GetPaintCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
scoped_refptr<StaticBitmapImage> image =
bridge->NewImageSnapshot(kPreferAcceleration);
EXPECT_TRUE(bridge->IsValid());
@@ -318,7 +318,7 @@ TEST_F(Canvas2DLayerBridgeTest, AccelerationHint) {
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
CanvasColorParams());
PaintFlags flags;
- bridge->DrawingCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ bridge->GetPaintCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
scoped_refptr<StaticBitmapImage> image =
bridge->NewImageSnapshot(kPreferNoAcceleration);
EXPECT_TRUE(bridge->IsValid());
@@ -330,7 +330,7 @@ TEST_F(Canvas2DLayerBridgeTest, AccelerationHint) {
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kDisableAcceleration,
CanvasColorParams());
PaintFlags flags;
- bridge->DrawingCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ bridge->GetPaintCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
scoped_refptr<StaticBitmapImage> image =
bridge->NewImageSnapshot(kPreferAcceleration);
EXPECT_TRUE(bridge->IsValid());
@@ -342,7 +342,7 @@ TEST_F(Canvas2DLayerBridgeTest, AccelerationHint) {
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kDisableAcceleration,
CanvasColorParams());
PaintFlags flags;
- bridge->DrawingCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ bridge->GetPaintCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
scoped_refptr<StaticBitmapImage> image =
bridge->NewImageSnapshot(kPreferNoAcceleration);
EXPECT_TRUE(bridge->IsValid());
@@ -359,6 +359,13 @@ TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareIfContextLost) {
EXPECT_FALSE(bridge->IsAccelerated());
}
+void DrawSomething(Canvas2DLayerBridge* bridge) {
+ bridge->DidDraw(FloatRect(0, 0, 1, 1));
+ bridge->FinalizeFrame();
+ // Grabbing an image forces a flush
+ bridge->NewImageSnapshot(kPreferAcceleration);
+}
+
TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareOnFailedTextureAlloc) {
{
// No fallback case.
@@ -379,14 +386,19 @@ TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareOnFailedTextureAlloc) {
->ContextProvider()
->GetGrContext();
std::unique_ptr<Canvas2DLayerBridge> bridge =
- MakeBridge(IntSize(300, 150), Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams());
+ std::make_unique<Canvas2DLayerBridge>(
+ IntSize(300, 150), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ bridge->DontUseIdleSchedulingForTesting();
EXPECT_TRUE(bridge->IsValid());
EXPECT_TRUE(bridge->IsAccelerated()); // We don't yet know that
// allocation will fail.
// This will cause SkSurface_Gpu creation to fail without
// Canvas2DLayerBridge otherwise detecting that anything was disabled.
gr->abandonContext();
+ host_ = std::make_unique<FakeCanvasResourceHost>(IntSize(300, 150));
+ bridge->SetCanvasResourceHost(host_.get());
+ DrawSomething(bridge.get());
scoped_refptr<StaticBitmapImage> snapshot =
bridge->NewImageSnapshot(kPreferAcceleration);
EXPECT_FALSE(bridge->IsAccelerated());
@@ -402,13 +414,6 @@ class MockLogger : public Canvas2DLayerBridge::Logger {
~MockLogger() override = default;
};
-void DrawSomething(Canvas2DLayerBridge* bridge) {
- bridge->DidDraw(FloatRect(0, 0, 1, 1));
- bridge->FinalizeFrame();
- // Grabbing an image forces a flush
- bridge->NewImageSnapshot(kPreferAcceleration);
-}
-
#if CANVAS2D_HIBERNATION_ENABLED
TEST_F(Canvas2DLayerBridgeTest, HibernationLifeCycle)
#else
@@ -844,13 +849,17 @@ TEST_F(Canvas2DLayerBridgeTest, ResourceRecycling) {
viz::TransferableResource resources[3];
std::unique_ptr<viz::SingleReleaseCallback> callbacks[3];
+ PaintFlags flags;
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams());
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
DrawSomething(bridge.get());
ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[0],
&callbacks[0]));
+
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
DrawSomething(bridge.get());
ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[1],
&callbacks[1]));
@@ -860,6 +869,7 @@ TEST_F(Canvas2DLayerBridgeTest, ResourceRecycling) {
// Now release the first resource and draw again. It should be reused due to
// recycling.
callbacks[0]->Run(gpu::SyncToken(), false);
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
DrawSomething(bridge.get());
ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[2],
&callbacks[2]));
@@ -879,13 +889,16 @@ TEST_F(Canvas2DLayerBridgeTest, NoResourceRecyclingWhenPageHidden) {
viz::TransferableResource resources[2];
std::unique_ptr<viz::SingleReleaseCallback> callbacks[2];
+ PaintFlags flags;
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams());
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
DrawSomething(bridge.get());
ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[0],
&callbacks[0]));
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
DrawSomething(bridge.get());
ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[1],
&callbacks[1]));
@@ -932,9 +945,8 @@ TEST_F(Canvas2DLayerBridgeTest, ReleaseResourcesAfterBridgeDestroyed) {
}
TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
- auto color_params =
- CanvasColorParams(CanvasColorSpace::kSRGB, CanvasPixelFormat::kF16,
- kOpaque, CanvasForceRGBA::kNotForced);
+ auto color_params = CanvasColorParams(CanvasColorSpace::kSRGB,
+ CanvasPixelFormat::kF16, kOpaque);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
@@ -948,8 +960,8 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
0u, expected_color_space)};
- bridge->DrawingCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
- bridge->DrawingCanvas()->drawImageRect(
+ bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
+ bridge->GetPaintCanvas()->drawImageRect(
images[1].paint_image(), SkRect::MakeWH(5u, 5u), SkRect::MakeWH(5u, 5u),
nullptr, cc::PaintCanvas::kFast_SrcRectConstraint);
bridge->NewImageSnapshot(kPreferAcceleration);
@@ -958,9 +970,9 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
}
TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) {
- auto color_params =
- CanvasColorParams(CanvasColorSpace::kSRGB, CanvasPixelFormat::kRGBA8,
- kOpaque, CanvasForceRGBA::kNotForced);
+ auto color_params = CanvasColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kOpaque);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
color_params);
@@ -972,8 +984,8 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) {
SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
0u, color_params.GetStorageGfxColorSpace())};
- bridge->DrawingCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
- bridge->DrawingCanvas()->drawImageRect(
+ bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
+ bridge->GetPaintCanvas()->drawImageRect(
images[1].paint_image(), SkRect::MakeWH(5u, 5u), SkRect::MakeWH(5u, 5u),
nullptr, cc::PaintCanvas::kFast_SrcRectConstraint);
bridge->NewImageSnapshot(kPreferAcceleration);
@@ -982,9 +994,8 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) {
}
TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
- auto color_params =
- CanvasColorParams(CanvasColorSpace::kSRGB, CanvasPixelFormat::kF16,
- kOpaque, CanvasForceRGBA::kNotForced);
+ auto color_params = CanvasColorParams(CanvasColorSpace::kSRGB,
+ CanvasPixelFormat::kF16, kOpaque);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
color_params);
@@ -1001,19 +1012,16 @@ TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
0u, color_params.GetStorageGfxColorSpace())};
// First 2 images are budgeted, they should remain locked after the op.
- bridge->DrawingCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
- bridge->DrawingCanvas()->drawImage(images[1].paint_image(), 0u, 0u, nullptr);
- // TODO(jochin): Can just call provider::FlushSkia() once we move recorder_
- // to the resource provider. The following is a temp workaround.
- cc::PaintCanvas* canvas = bridge->GetOrCreateResourceProvider()->Canvas();
- canvas->drawPicture(bridge->record_for_testing());
+ bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
+ bridge->GetPaintCanvas()->drawImage(images[1].paint_image(), 0u, 0u, nullptr);
+ bridge->GetOrCreateResourceProvider()->FlushCanvas();
EXPECT_EQ(image_decode_cache_.num_locked_images(), 2);
// Next image is not budgeted, we should unlock all images other than the last
// image.
image_decode_cache_.set_budget_exceeded(true);
- bridge->DrawingCanvas()->drawImage(images[2].paint_image(), 0u, 0u, nullptr);
- canvas->drawPicture(bridge->record_for_testing());
+ bridge->GetPaintCanvas()->drawImage(images[2].paint_image(), 0u, 0u, nullptr);
+ bridge->GetOrCreateResourceProvider()->FlushCanvas();
EXPECT_EQ(image_decode_cache_.num_locked_images(), 1);
// Ask the provider to release everything, no locked images should remain.
@@ -1022,9 +1030,8 @@ TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
}
TEST_F(Canvas2DLayerBridgeTest, QueuesCleanupTaskForLockedImages) {
- auto color_params =
- CanvasColorParams(CanvasColorSpace::kSRGB, CanvasPixelFormat::kF16,
- kOpaque, CanvasForceRGBA::kNotForced);
+ auto color_params = CanvasColorParams(CanvasColorSpace::kSRGB,
+ CanvasPixelFormat::kF16, kOpaque);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
color_params);
@@ -1033,12 +1040,9 @@ TEST_F(Canvas2DLayerBridgeTest, QueuesCleanupTaskForLockedImages) {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace());
- bridge->DrawingCanvas()->drawImage(image.paint_image(), 0u, 0u, nullptr);
+ bridge->GetPaintCanvas()->drawImage(image.paint_image(), 0u, 0u, nullptr);
- // TODO(jochin): Can just call provider::FlushSkia() once we move recorder_
- // to the resource provider. The following is a temp workaround.
- cc::PaintCanvas* canvas = bridge->GetOrCreateResourceProvider()->Canvas();
- canvas->drawPicture(bridge->record_for_testing());
+ bridge->GetOrCreateResourceProvider()->FlushCanvas();
EXPECT_EQ(image_decode_cache_.num_locked_images(), 1);
base::RunLoop().RunUntilIdle();
@@ -1046,9 +1050,8 @@ TEST_F(Canvas2DLayerBridgeTest, QueuesCleanupTaskForLockedImages) {
}
TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
- auto color_params =
- CanvasColorParams(CanvasColorSpace::kSRGB, CanvasPixelFormat::kF16,
- kOpaque, CanvasForceRGBA::kNotForced);
+ auto color_params = CanvasColorParams(CanvasColorSpace::kSRGB,
+ CanvasPixelFormat::kF16, kOpaque);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
color_params);
@@ -1060,14 +1063,14 @@ TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
0u, color_params.GetStorageGfxColorSpace())};
- bridge->DrawingCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
+ bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
// Lose the context and ensure that the image provider is not used.
bridge->GetOrCreateResourceProvider()->OnContextDestroyed();
// We should unref all images on the cache when the context is destroyed.
EXPECT_EQ(image_decode_cache_.num_locked_images(), 0);
image_decode_cache_.set_disallow_cache_use(true);
- bridge->DrawingCanvas()->drawImage(images[1].paint_image(), 0u, 0u, &flags);
+ bridge->GetPaintCanvas()->drawImage(images[1].paint_image(), 0u, 0u, &flags);
}
TEST_F(Canvas2DLayerBridgeTest,
@@ -1076,7 +1079,7 @@ TEST_F(Canvas2DLayerBridgeTest,
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
size, Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams());
- bridge->DrawingCanvas()->clear(SK_ColorRED);
+ bridge->GetPaintCanvas()->clear(SK_ColorRED);
DrawSomething(bridge.get());
ASSERT_TRUE(bridge->layer_for_testing());
@@ -1104,8 +1107,7 @@ class CustomFakeCanvasResourceHost : public FakeCanvasResourceHost {
TEST_F(Canvas2DLayerBridgeTest, WritePixelsRestoresClipStack) {
CanvasColorParams color_params(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kF16, kOpaque,
- CanvasForceRGBA::kNotForced);
+ CanvasPixelFormat::kF16, kOpaque);
IntSize size = IntSize(300, 300);
auto host = std::make_unique<CustomFakeCanvasResourceHost>(size);
std::unique_ptr<Canvas2DLayerBridge> bridge =
@@ -1113,23 +1115,26 @@ TEST_F(Canvas2DLayerBridgeTest, WritePixelsRestoresClipStack) {
std::move(host));
PaintFlags flags;
- EXPECT_EQ(bridge->DrawingCanvas()->getTotalMatrix().get(SkMatrix::kMTransX),
- 0);
+ // MakeBridge() results in a call to restore the matrix. So we already have 1.
+ EXPECT_EQ(bridge->GetPaintCanvas()->getTotalMatrix().get(SkMatrix::kMTransX),
+ 5);
+ // Drawline so WritePixels has something to flush
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
+ bridge->DidDraw(FloatRect(0, 0, 1, 1));
- cc::PaintCanvas* canvas = bridge->GetOrCreateResourceProvider()->Canvas();
+ // WritePixels flushes recording. Post flush, a new drawing canvas is created
+ // that should have the matrix restored onto it.
bridge->WritePixels(SkImageInfo::MakeN32Premul(10, 10), nullptr, 10, 0, 0);
- // Recording canvas maintain clip stack, while underlying SkCanvas should not.
- EXPECT_EQ(canvas->getTotalMatrix().get(SkMatrix::kMTransX), 0);
- EXPECT_EQ(bridge->DrawingCanvas()->getTotalMatrix().get(SkMatrix::kMTransX),
+ EXPECT_EQ(bridge->GetPaintCanvas()->getTotalMatrix().get(SkMatrix::kMTransX),
5);
- bridge->DrawingCanvas()->drawLine(0, 0, 2, 2, flags);
- // Flush recording. Recording canvas should maintain matrix, while SkCanvas
- // should not.
+ bridge->GetPaintCanvas()->drawLine(0, 0, 2, 2, flags);
+ // Standard flush recording. Post flush, a new drawing canvas is created that
+ // should have the matrix restored onto it.
DrawSomething(bridge.get());
- EXPECT_EQ(bridge->DrawingCanvas()->getTotalMatrix().get(SkMatrix::kMTransX),
+
+ EXPECT_EQ(bridge->GetPaintCanvas()->getTotalMatrix().get(SkMatrix::kMTransX),
5);
- EXPECT_EQ(canvas->getTotalMatrix().get(SkMatrix::kMTransX), 0);
}
TEST_F(Canvas2DLayerBridgeTest, DisplayedCanvasIsRateLimited) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
index a947db5fb56..d8868023915 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -40,12 +40,10 @@ CanvasColorParams::CanvasColorParams() = default;
CanvasColorParams::CanvasColorParams(CanvasColorSpace color_space,
CanvasPixelFormat pixel_format,
- OpacityMode opacity_mode,
- CanvasForceRGBA force_rgba)
+ OpacityMode opacity_mode)
: color_space_(color_space),
pixel_format_(pixel_format),
- opacity_mode_(opacity_mode),
- force_rgba_(force_rgba) {}
+ opacity_mode_(opacity_mode) {}
CanvasColorParams::CanvasColorParams(const SkImageInfo& info)
: CanvasColorParams(info.refColorSpace(), info.colorType()) {}
@@ -63,10 +61,16 @@ bool CanvasColorParams::NeedsColorConversion(
}
SkColorType CanvasColorParams::GetSkColorType() const {
- if (pixel_format_ == CanvasPixelFormat::kF16)
- return kRGBA_F16_SkColorType;
- return force_rgba_ == CanvasForceRGBA::kForced ? kRGBA_8888_SkColorType
- : kN32_SkColorType;
+ switch (pixel_format_) {
+ case CanvasPixelFormat::kF16:
+ return kRGBA_F16_SkColorType;
+ case CanvasPixelFormat::kRGBA8:
+ return kRGBA_8888_SkColorType;
+ case CanvasPixelFormat::kBGRA8:
+ return kBGRA_8888_SkColorType;
+ }
+ NOTREACHED();
+ return kN32_SkColorType;
}
SkAlphaType CanvasColorParams::GetSkAlphaType() const {
@@ -111,6 +115,9 @@ gfx::ColorSpace CanvasColorParams::GetStorageGfxColorSpace() const {
}
sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
+ static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
+ kN32_SkColorType == kBGRA_8888_SkColorType,
+ "Unexpected kN32_SkColorType value.");
skcms_Matrix3x3 gamut = SkNamedGamut::kSRGB;
skcms_TransferFunction transferFn = SkNamedTransferFn::kSRGB;
switch (color_space_) {
@@ -132,10 +139,6 @@ sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
}
gfx::BufferFormat CanvasColorParams::GetBufferFormat() const {
- static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
- kN32_SkColorType == kBGRA_8888_SkColorType,
- "Unexpected kN32_SkColorType value.");
-
switch (GetSkColorType()) {
case kRGBA_8888_SkColorType:
return gfx::BufferFormat::RGBA_8888;
@@ -152,10 +155,6 @@ gfx::BufferFormat CanvasColorParams::GetBufferFormat() const {
GLenum CanvasColorParams::GLUnsizedInternalFormat() const {
// TODO(junov): try GL_RGB when opacity_mode_ == kOpaque
- static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
- kN32_SkColorType == kBGRA_8888_SkColorType,
- "Unexpected kN32_SkColorType value.");
-
switch (GetSkColorType()) {
case kRGBA_8888_SkColorType:
return GL_RGBA;
@@ -171,10 +170,6 @@ GLenum CanvasColorParams::GLUnsizedInternalFormat() const {
}
GLenum CanvasColorParams::GLSizedInternalFormat() const {
- static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
- kN32_SkColorType == kBGRA_8888_SkColorType,
- "Unexpected kN32_SkColorType value.");
-
switch (GetSkColorType()) {
case kRGBA_8888_SkColorType:
return GL_RGBA8;
@@ -210,10 +205,9 @@ viz::ResourceFormat CanvasColorParams::TransferableResourceFormat() const {
CanvasColorParams::CanvasColorParams(const sk_sp<SkColorSpace> color_space,
SkColorType color_type) {
color_space_ = CanvasColorSpace::kSRGB;
- pixel_format_ = CanvasPixelFormat::kRGBA8;
+ pixel_format_ = GetNativeCanvasPixelFormat();
// When there is no color space information, the SkImage is in legacy mode and
- // the color type is kN32_SkColorType (which translates to kRGBA8 canvas pixel
- // format).
+ // the color type is kRGBA8 canvas pixel format.
if (!color_space)
return;
@@ -239,7 +233,7 @@ CanvasColorParams::CanvasColorParams(const sk_sp<SkColorSpace> color_space,
if (color_type == kRGBA_F16_SkColorType)
pixel_format_ = CanvasPixelFormat::kF16;
else if (color_type == kRGBA_8888_SkColorType)
- force_rgba_ = CanvasForceRGBA::kForced;
+ pixel_format_ = CanvasPixelFormat::kRGBA8;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h
index 5c1dfde62a9..3920ea5c865 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h
@@ -34,28 +34,29 @@ enum class CanvasColorSpace {
enum class CanvasPixelFormat {
kRGBA8,
+ kBGRA8,
kF16,
};
-// todo(crbug/1021986) remove force_rgba in canvasColorParams
-enum class CanvasForceRGBA { kForced, kNotForced };
-
class PLATFORM_EXPORT CanvasColorParams {
DISALLOW_NEW();
public:
// The default constructor will create an output-blended 8-bit surface.
CanvasColorParams();
- CanvasColorParams(CanvasColorSpace,
- CanvasPixelFormat,
- OpacityMode,
- CanvasForceRGBA);
+ CanvasColorParams(CanvasColorSpace, CanvasPixelFormat, OpacityMode);
explicit CanvasColorParams(const SkImageInfo&);
+ static CanvasPixelFormat GetNativeCanvasPixelFormat() {
+ if (kN32_SkColorType == kRGBA_8888_SkColorType)
+ return CanvasPixelFormat::kRGBA8;
+ else if (kN32_SkColorType == kBGRA_8888_SkColorType)
+ return CanvasPixelFormat::kBGRA8;
+ }
+
CanvasColorSpace ColorSpace() const { return color_space_; }
CanvasPixelFormat PixelFormat() const { return pixel_format_; }
OpacityMode GetOpacityMode() const { return opacity_mode_; }
- CanvasForceRGBA GetForceRGBA() const { return force_rgba_; }
void SetCanvasColorSpace(CanvasColorSpace c) { color_space_ = c; }
void SetCanvasPixelFormat(CanvasPixelFormat f) { pixel_format_ = f; }
@@ -99,9 +100,8 @@ class PLATFORM_EXPORT CanvasColorParams {
SkColorType color_type);
CanvasColorSpace color_space_ = CanvasColorSpace::kSRGB;
- CanvasPixelFormat pixel_format_ = CanvasPixelFormat::kRGBA8;
+ CanvasPixelFormat pixel_format_ = GetNativeCanvasPixelFormat();
OpacityMode opacity_mode_ = kNonOpaque;
- CanvasForceRGBA force_rgba_ = CanvasForceRGBA::kNotForced;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc
index 352fa6c89a0..b34686a8065 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc
@@ -25,8 +25,7 @@ TEST(CanvasColorParamsTest, MatchSkColorSpaceWithGfxColorSpace) {
};
for (int iter_color_space = 0; iter_color_space < 4; iter_color_space++) {
CanvasColorParams color_params(canvas_color_spaces[iter_color_space],
- CanvasPixelFormat::kF16, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ CanvasPixelFormat::kF16, kNonOpaque);
sk_sp<SkColorSpace> canvas_drawing_color_space =
color_params.GetSkColorSpace();
sk_sp<SkColorSpace> canvas_media_color_space =
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h
deleted file mode 100644
index 417d0bf00d4..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_HEURISTIC_PARAMETERS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_HEURISTIC_PARAMETERS_H_
-
-#include "build/build_config.h"
-
-namespace blink {
-
-namespace canvas_heuristic_parameters {
-
-enum {
- // Disable Deferral overdraw parameters
- //======================================
-
- // Heuristic: Canvases that are overdrawn beyond this factor in a
- // single frame will be disabled deferral.
- kExpensiveOverdrawThreshold = 10,
-
- // GPU readback prevention heuristics
- //====================================
-
- // When a canvas is used as a source image, if its destination is
- // non-accelerated and the source canvas is accelerated, a readback
- // from the gpu is necessary. This option causes the source canvas to
- // switch to non-accelerated when this situation is encountered to
- // prevent future canvas-to-canvas draws from requiring a readback.
- kDisableAccelerationToAvoidReadbacks = 0,
-
- // See description of DisableAccelerationToAvoidReadbacks. This is the
- // opposite strategy : accelerate the destination canvas. If both
- // EnableAccelerationToAvoidReadbacks and
- // DisableAccelerationToAvoidReadbacks are specified, we try to enable
- // acceleration on the destination first. If that does not succeed,
- // we disable acceleration on the source canvas. Either way, future
- // readbacks are prevented.
- kEnableAccelerationToAvoidReadbacks = 1,
-
- // Accelerated rendering heuristics
- // =================================
-
- // Enables frequent flushing of the GrContext for accelerated canvas. Since
- // skia internally batches the GrOp list when flushing the recording onto the
- // SkCanvasand may only flush it the command buffer at the end of the frame,
- // it can lead to inefficient parallelization with the GPU. This enables
- // triggering context flushes at regular intervals, after a fixed number of
- // draws.
- kEnableGrContextFlushes = 1,
-
- // The maximum number of draw ops executed on the canvas, after which the
- // underlying GrContext is flushed.
- kMaxDrawsBeforeContextFlush = 50,
-
- // Canvas resource provider
- // ========================
-
- // The maximum number of inflight resources waiting to be used for recycling.
- kMaxRecycledCanvasResources = 2,
-}; // enum
-
-} // namespace canvas_heuristic_parameters
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 429b7c2fab1..c414406d28a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -15,6 +15,7 @@
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
+#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/sync_token.h"
@@ -48,7 +49,8 @@ gpu::mojom::blink::MailboxPtr SharedBitmapIdToGpuMailboxPtr(
CanvasResource::CanvasResource(base::WeakPtr<CanvasResourceProvider> provider,
SkFilterQuality filter_quality,
const CanvasColorParams& color_params)
- : owning_thread_id_(base::PlatformThread::CurrentId()),
+ : owning_thread_ref_(base::PlatformThread::CurrentRef()),
+ owning_thread_task_runner_(Thread::Current()->GetTaskRunner()),
provider_(std::move(provider)),
filter_quality_(filter_quality),
color_params_(color_params) {}
@@ -60,12 +62,14 @@ CanvasResource::~CanvasResource() {
}
void CanvasResource::OnDestroy() {
- if (owning_thread_id_ != base::PlatformThread::CurrentId()) {
+ if (is_cross_thread()) {
// Destroyed on wrong thread. This can happen when the thread of origin was
// torn down, in which case the GPU context owning any underlying resources
// no longer exists.
Abandon();
} else {
+ if (provider_)
+ provider_->OnDestroyResource();
TearDown();
}
#if DCHECK_IS_ON()
@@ -111,7 +115,6 @@ static void ReleaseFrameResources(
// TODO(khushalsagar): If multiple readers had access to this resource, losing
// it once should make sure subsequent releases don't try to recycle this
// resource.
- // Also what about single buffered canvas?
if (lost_resource)
resource->NotifyResourceLost();
if (resource_provider && !lost_resource && resource->IsRecycleable())
@@ -286,6 +289,12 @@ void CanvasResourceSharedBitmap::Abandon() {
shared_mapping_ = {};
}
+void CanvasResourceSharedBitmap::NotifyResourceLost() {
+ // Release our reference to the shared memory mapping since the resource can
+ // no longer be safely recycled and this memory is needed for copy-on-write.
+ shared_mapping_ = {};
+}
+
const gpu::Mailbox& CanvasResourceSharedBitmap::GetOrCreateGpuMailbox(
MailboxSyncMode sync_mode) {
return shared_bitmap_id_;
@@ -315,16 +324,16 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
base::WeakPtr<CanvasResourceProvider> provider,
SkFilterQuality filter_quality,
const CanvasColorParams& color_params,
- bool is_overlay_candidate,
bool is_origin_top_left,
- bool allow_concurrent_read_write_access,
- bool is_accelerated)
+ bool is_accelerated,
+ uint32_t shared_image_usage_flags)
: CanvasResource(std::move(provider), filter_quality, color_params),
context_provider_wrapper_(std::move(context_provider_wrapper)),
- is_overlay_candidate_(is_overlay_candidate),
size_(size),
is_origin_top_left_(is_origin_top_left),
is_accelerated_(is_accelerated),
+ is_overlay_candidate_(shared_image_usage_flags &
+ gpu::SHARED_IMAGE_USAGE_SCANOUT),
texture_target_(
is_overlay_candidate_
? gpu::GetBufferTextureTarget(
@@ -333,14 +342,14 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
context_provider_wrapper_->ContextProvider()
->GetCapabilities())
: GL_TEXTURE_2D),
- owning_thread_task_runner_(Thread::Current()->GetTaskRunner()) {
- if (!context_provider_wrapper_)
- return;
-
+ use_oop_rasterization_(context_provider_wrapper_->ContextProvider()
+ ->GetCapabilities()
+ .supports_oop_raster) {
auto* gpu_memory_buffer_manager =
Platform::Current()->GetGpuMemoryBufferManager();
if (!is_accelerated_) {
DCHECK(gpu_memory_buffer_manager);
+ DCHECK(shared_image_usage_flags & gpu::SHARED_IMAGE_USAGE_DISPLAY);
gpu_memory_buffer_ = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
gfx::Size(size), ColorParams().GetBufferFormat(),
@@ -355,23 +364,26 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
context_provider_wrapper_->ContextProvider()->SharedImageInterface();
DCHECK(shared_image_interface);
- uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY |
- gpu::SHARED_IMAGE_USAGE_GLES2 |
- gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
- if (is_overlay_candidate_)
- flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
- if (allow_concurrent_read_write_access)
- flags |= gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
+ // The GLES2 flag is needed for rendering via GL using a GrContext.
+ if (use_oop_rasterization_) {
+ shared_image_usage_flags = shared_image_usage_flags |
+ gpu::SHARED_IMAGE_USAGE_RASTER |
+ gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
+ } else {
+ shared_image_usage_flags = shared_image_usage_flags |
+ gpu::SHARED_IMAGE_USAGE_GLES2 |
+ gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
+ }
gpu::Mailbox shared_image_mailbox;
if (gpu_memory_buffer_) {
shared_image_mailbox = shared_image_interface->CreateSharedImage(
gpu_memory_buffer_.get(), gpu_memory_buffer_manager,
- ColorParams().GetStorageGfxColorSpace(), flags);
+ ColorParams().GetStorageGfxColorSpace(), shared_image_usage_flags);
} else {
shared_image_mailbox = shared_image_interface->CreateSharedImage(
ColorParams().TransferableResourceFormat(), gfx::Size(size),
- ColorParams().GetStorageGfxColorSpace(), flags);
+ ColorParams().GetStorageGfxColorSpace(), shared_image_usage_flags);
}
// Wait for the mailbox to be ready to be used.
@@ -380,6 +392,10 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
auto* raster_interface = RasterInterface();
DCHECK(raster_interface);
owning_thread_data().shared_image_mailbox = shared_image_mailbox;
+
+ if (use_oop_rasterization_)
+ return;
+
owning_thread_data().texture_id_for_read_access =
raster_interface->CreateAndConsumeForGpuRaster(shared_image_mailbox);
@@ -387,7 +403,8 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
// a texture for writes.
if (!is_accelerated_)
return;
- if (allow_concurrent_read_write_access) {
+ if (shared_image_usage_flags &
+ gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE) {
owning_thread_data().texture_id_for_write_access =
raster_interface->CreateAndConsumeForGpuRaster(shared_image_mailbox);
} else {
@@ -402,15 +419,14 @@ scoped_refptr<CanvasResourceSharedImage> CanvasResourceSharedImage::Create(
base::WeakPtr<CanvasResourceProvider> provider,
SkFilterQuality filter_quality,
const CanvasColorParams& color_params,
- bool is_overlay_candidate,
bool is_origin_top_left,
- bool allow_concurrent_read_write_access,
- bool is_accelerated) {
+ bool is_accelerated,
+ uint32_t shared_image_usage_flags) {
TRACE_EVENT0("blink", "CanvasResourceSharedImage::Create");
auto resource = base::AdoptRef(new CanvasResourceSharedImage(
size, std::move(context_provider_wrapper), std::move(provider),
- filter_quality, color_params, is_overlay_candidate, is_origin_top_left,
- allow_concurrent_read_write_access, is_accelerated));
+ filter_quality, color_params, is_origin_top_left, is_accelerated,
+ shared_image_usage_flags));
return resource->IsValid() ? resource : nullptr;
}
@@ -422,13 +438,11 @@ CanvasResourceSharedImage::~CanvasResourceSharedImage() {
OnDestroy();
}
-GLenum CanvasResourceSharedImage::TextureTarget() const {
- return texture_target_;
-}
-
void CanvasResourceSharedImage::TearDown() {
DCHECK(!is_cross_thread());
+ // The context deletes all shared images on destruction which means no
+ // cleanup is needed if the context was lost.
if (ContextProviderWrapper()) {
auto* raster_interface = RasterInterface();
auto* shared_image_interface =
@@ -459,11 +473,8 @@ void CanvasResourceSharedImage::TearDown() {
}
void CanvasResourceSharedImage::Abandon() {
- if (auto context_provider = SharedGpuContext::ContextProviderWrapper()) {
- auto* sii = context_provider->ContextProvider()->SharedImageInterface();
- if (sii)
- sii->DestroySharedImage(gpu::SyncToken(), mailbox());
- }
+ // Called when the owning thread has been torn down which will destroy the
+ // context on which the shared image was created so no cleanup is necessary.
}
void CanvasResourceSharedImage::WillDraw() {
@@ -484,17 +495,10 @@ void CanvasResourceSharedImage::OnBitmapImageDestroyed(
bool has_read_ref_on_texture,
const gpu::SyncToken& sync_token,
bool is_lost) {
- if (resource->is_cross_thread()) {
- auto& task_runner = *resource->owning_thread_task_runner_;
- PostCrossThreadTask(
- task_runner, FROM_HERE,
- CrossThreadBindOnce(&CanvasResourceSharedImage::OnBitmapImageDestroyed,
- std::move(resource), has_read_ref_on_texture,
- sync_token, is_lost));
- return;
- }
+ DCHECK(!resource->is_cross_thread());
if (has_read_ref_on_texture) {
+ DCHECK(!resource->use_oop_rasterization_);
DCHECK_GT(resource->owning_thread_data().bitmap_image_read_refs, 0u);
resource->owning_thread_data().bitmap_image_read_refs--;
@@ -546,7 +550,8 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSharedImage::Bitmap() {
// created here, the image will create a new representation from the mailbox
// rather than referring to the shared image's texture ID if it was provided
// below.
- const bool has_read_ref_on_texture = !is_cross_thread();
+ const bool has_read_ref_on_texture =
+ !is_cross_thread() && !use_oop_rasterization_;
GLuint texture_id_for_image = 0u;
if (has_read_ref_on_texture) {
texture_id_for_image = owning_thread_data().texture_id_for_read_access;
@@ -574,8 +579,8 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSharedImage::Bitmap() {
gpu::SyncToken token = is_cross_thread() ? sync_token() : gpu::SyncToken();
image = AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
mailbox(), token, texture_id_for_image, image_info, texture_target_,
- context_provider_wrapper_, owning_thread_id_, is_origin_top_left_,
- std::move(release_callback));
+ is_origin_top_left_, context_provider_wrapper_, owning_thread_ref_,
+ owning_thread_task_runner_, std::move(release_callback));
DCHECK(image);
return image;
@@ -708,8 +713,9 @@ scoped_refptr<StaticBitmapImage> ExternalCanvasResource::Bitmap() {
return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
mailbox_, GetSyncToken(), /*shared_image_texture_id=*/0u,
- CreateSkImageInfo(), texture_target_, context_provider_wrapper_,
- owning_thread_id_, is_origin_top_left_, std::move(release_callback));
+ CreateSkImageInfo(), texture_target_, is_origin_top_left_,
+ context_provider_wrapper_, owning_thread_ref_, owning_thread_task_runner_,
+ std::move(release_callback));
}
void ExternalCanvasResource::TearDown() {
@@ -793,7 +799,7 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSwapChain::Bitmap() {
// It's safe to share the front buffer texture id if we're on the same thread
// since the |release_callback| ensures this resource will be alive.
GLuint shared_texture_id = 0u;
- if (base::PlatformThread::CurrentId() == owning_thread_id_)
+ if (!is_cross_thread())
shared_texture_id = front_buffer_texture_id_;
// The |release_callback| keeps a ref on this resource to ensure the backing
@@ -806,22 +812,22 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSwapChain::Bitmap() {
return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
front_buffer_mailbox_, sync_token_, shared_texture_id, image_info,
- GL_TEXTURE_2D, context_provider_wrapper_, owning_thread_id_,
- /*is_origin_top_left=*/true, std::move(release_callback));
+ GL_TEXTURE_2D, true /*is_origin_top_left*/, context_provider_wrapper_,
+ owning_thread_ref_, owning_thread_task_runner_,
+ std::move(release_callback));
}
void CanvasResourceSwapChain::Abandon() {
- if (auto context_provider = SharedGpuContext::ContextProviderWrapper()) {
- auto* sii = context_provider->ContextProvider()->SharedImageInterface();
- DCHECK(sii);
- sii->DestroySharedImage(gpu::SyncToken(), front_buffer_mailbox_);
- sii->DestroySharedImage(gpu::SyncToken(), back_buffer_mailbox_);
- }
+ // Called when the owning thread has been torn down which will destroy the
+ // context on which the shared image was created so no cleanup is necessary.
}
void CanvasResourceSwapChain::TearDown() {
+ // The context deletes all shared images on destruction which means no
+ // cleanup is needed if the context was lost.
if (!context_provider_wrapper_)
return;
+
auto* raster_interface =
context_provider_wrapper_->ContextProvider()->RasterInterface();
DCHECK(raster_interface);
@@ -855,7 +861,7 @@ const gpu::SyncToken CanvasResourceSwapChain::GetSyncToken() {
}
void CanvasResourceSwapChain::PresentSwapChain() {
- DCHECK_EQ(base::PlatformThread::CurrentId(), owning_thread_id_);
+ DCHECK(!is_cross_thread());
DCHECK(context_provider_wrapper_);
TRACE_EVENT0("blink", "CanvasResourceSwapChain::PresentSwapChain");
@@ -882,7 +888,8 @@ void CanvasResourceSwapChain::PresentSwapChain() {
// The wait sync token ensure that the present executes before we do the copy.
raster_interface->CopySubTexture(front_buffer_mailbox_, back_buffer_mailbox_,
GL_TEXTURE_2D, 0, 0, 0, 0, size_.Width(),
- size_.Height());
+ size_.Height(), false /* unpack_flip_y */,
+ false /* unpack_premultiply_alpha */);
}
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
index b5f09b1d63d..e68d38e845b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -133,19 +133,6 @@ class PLATFORM_EXPORT CanvasResource
// CanvasResourceProvider and derivatives should call this.
virtual void TakeSkImage(sk_sp<SkImage> image) = 0;
- // Provides the texture ID that can be used to write to this resource.
- // TODO(khushalsagar): Won't work with OOPR.
- virtual GLuint GetBackingTextureHandleForOverwrite() {
- NOTREACHED();
- return 0;
- }
-
- // Returns the texture target for the ID provided above.
- virtual GLenum TextureTarget() const {
- NOTREACHED();
- return 0;
- }
-
// Called when the resource is marked lost. Losing a resource does not mean
// that the backing memory has been destroyed, since the resource itself keeps
// a ref on that memory.
@@ -153,12 +140,7 @@ class PLATFORM_EXPORT CanvasResource
// token for the resource to be safely recycled and its the GL state may be
// inconsistent with when the resource was given to the compositor. So it
// should not be recycled for writing again but can be safely read from.
- virtual void NotifyResourceLost() {
- // TODO(khushalsagar): Some implementations respect the don't write again
- // policy but some don't. Fix that once shared images replace all
- // accelerated use-cases.
- Abandon();
- }
+ virtual void NotifyResourceLost() = 0;
void SetFilterQuality(SkFilterQuality filter) { filter_quality_ = filter; }
// The filter quality to use when the resource is drawn by the compositor.
@@ -166,6 +148,10 @@ class PLATFORM_EXPORT CanvasResource
SkImageInfo CreateSkImageInfo() const;
+ bool is_cross_thread() const {
+ return base::PlatformThread::CurrentRef() != owning_thread_ref_;
+ }
+
protected:
CanvasResource(base::WeakPtr<CanvasResourceProvider>,
SkFilterQuality,
@@ -212,7 +198,15 @@ class PLATFORM_EXPORT CanvasResource
CanvasResourceProvider* Provider() { return provider_.get(); }
base::WeakPtr<CanvasResourceProvider> WeakProvider() { return provider_; }
- const base::PlatformThreadId owning_thread_id_;
+ const base::PlatformThreadRef owning_thread_ref_;
+ const scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_;
+
+ protected:
+ // Returns the texture target for the resource.
+ virtual GLenum TextureTarget() const {
+ NOTREACHED();
+ return 0;
+ }
private:
// Sync token that was provided when resource was released
@@ -245,10 +239,11 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
scoped_refptr<StaticBitmapImage> Bitmap() final;
bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool flag) final { is_origin_clean_ = flag; }
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
+ void NotifyResourceLost() override;
private:
void TearDown() override;
- const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
bool HasGpuMailbox() const override;
CanvasResourceSharedBitmap(const IntSize&,
@@ -271,10 +266,9 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
base::WeakPtr<CanvasResourceProvider>,
SkFilterQuality,
const CanvasColorParams&,
- bool is_overlay_candidate,
bool is_origin_top_left,
- bool allow_concurrent_read_write_access,
- bool is_accelerated);
+ bool is_accelerated,
+ uint32_t shared_image_usage_flags);
~CanvasResourceSharedImage() override;
bool IsRecycleable() const final { return true; }
@@ -302,16 +296,15 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
GLuint GetTextureIdForWriteAccess() const {
return owning_thread_data().texture_id_for_write_access;
}
+ GLenum TextureTarget() const override { return texture_target_; }
void WillDraw();
- bool is_cross_thread() const {
- return base::PlatformThread::CurrentId() != owning_thread_id_;
- }
bool has_read_access() const {
return owning_thread_data().bitmap_image_read_refs > 0u;
}
bool is_lost() const { return owning_thread_data().is_lost; }
void CopyRenderingResultsToGpuMemoryBuffer(const sk_sp<SkImage>& image);
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
private:
// These members are either only accessed on the owning thread, or are only
@@ -345,8 +338,6 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
void Abandon() override;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
const override;
- const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
- GLenum TextureTarget() const final;
bool HasGpuMailbox() const override;
const gpu::SyncToken GetSyncToken() override;
bool IsOverlayCandidate() const final { return is_overlay_candidate_; }
@@ -356,17 +347,16 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
base::WeakPtr<CanvasResourceProvider>,
SkFilterQuality,
const CanvasColorParams&,
- bool is_overlay_candidate,
bool is_origin_top_left,
- bool allow_concurrent_read_write_access,
- bool is_accelerated);
+ bool is_accelerated,
+ uint32_t shared_image_usage_flags);
OwningThreadData& owning_thread_data() {
- DCHECK_EQ(base::PlatformThread::CurrentId(), owning_thread_id_);
+ DCHECK(!is_cross_thread());
return owning_thread_data_;
}
const OwningThreadData& owning_thread_data() const {
- DCHECK_EQ(base::PlatformThread::CurrentId(), owning_thread_id_);
+ DCHECK(!is_cross_thread());
return owning_thread_data_;
}
@@ -394,12 +384,12 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
// Accessed on any thread.
- const bool is_overlay_candidate_;
const IntSize size_;
const bool is_origin_top_left_;
const bool is_accelerated_;
+ const bool is_overlay_candidate_;
const GLenum texture_target_;
- const scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_;
+ const bool use_oop_rasterization_;
OwningThreadData owning_thread_data_;
};
@@ -428,14 +418,18 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource {
void Abandon() final;
IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final;
+ void NotifyResourceLost() override {
+ // Used for single buffering mode which doesn't need to care about sync
+ // token synchronization.
+ }
scoped_refptr<StaticBitmapImage> Bitmap() override;
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
private:
void TearDown() override;
GLenum TextureTarget() const final { return texture_target_; }
bool IsOverlayCandidate() const final { return true; }
- const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
bool HasGpuMailbox() const override;
const gpu::SyncToken GetSyncToken() override;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
@@ -481,20 +475,24 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource {
void Abandon() final;
IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final;
+ void NotifyResourceLost() override {
+ // Used for single buffering mode which doesn't need to care about sync
+ // token synchronization.
+ }
scoped_refptr<StaticBitmapImage> Bitmap() override;
GLenum TextureTarget() const final { return GL_TEXTURE_2D; }
- GLuint GetBackingTextureHandleForOverwrite() final {
+ GLuint GetBackingTextureHandleForOverwrite() {
return back_buffer_texture_id_;
}
void PresentSwapChain();
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
private:
void TearDown() override;
bool IsOverlayCandidate() const final { return true; }
- const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
bool HasGpuMailbox() const override;
const gpu::SyncToken GetSyncToken() override;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
index 48e1f492be5..2e0040edaca 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -14,8 +14,8 @@
#include "components/viz/common/resources/single_release_callback.h"
#include "services/viz/public/mojom/compositing/frame_timing_details.mojom-blink.h"
#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom-blink.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
@@ -69,7 +69,7 @@ CanvasResourceDispatcher::CanvasResourceDispatcher(
DCHECK(!sink_.is_bound());
mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
provider.BindNewPipeAndPassReceiver());
DCHECK(provider);
@@ -216,8 +216,7 @@ bool CanvasResourceDispatcher::PrepareFrame(
// TODO(crbug.com/652931): update the device_scale_factor
frame->metadata.device_scale_factor = 1.0f;
- if (current_begin_frame_ack_.sequence_number ==
- viz::BeginFrameArgs::kInvalidFrameNumber) {
+ if (!current_begin_frame_ack_.frame_id.IsSequenceValid()) {
// TODO(eseckler): This shouldn't be necessary when OffscreenCanvas no
// longer submits CompositorFrames without prior BeginFrame.
current_begin_frame_ack_ = viz::BeginFrameAck::CreateManualAckWithDamage();
@@ -353,7 +352,7 @@ void CanvasResourceDispatcher::OnBeginFrame(
}
// TODO(fserb): Update this with the correct value if we are on RAF submit.
- current_begin_frame_ack_.sequence_number =
+ current_begin_frame_ack_.frame_id.sequence_number =
viz::BeginFrameArgs::kInvalidFrameNumber;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
index 9a6ac41b2fb..b2b6d55dbc0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -15,6 +15,8 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h"
#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
+#include "third_party/blink/renderer/platform/geometry/int_size.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
index f7c20310f27..d63606224c1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
@@ -19,6 +19,18 @@ CanvasResourceHost::ReplaceResourceProvider(
std::move(resource_provider_);
resource_provider_ = std::move(new_resource_provider);
UpdateMemoryUsage();
+ if (resource_provider_) {
+ resource_provider_->Canvas()->restoreToCount(1);
+ InitializeForRecording(resource_provider_->Canvas());
+ // Using unretained here since CanvasResourceHost owns |resource_provider_|
+ // and is guaranteed to outlive it
+ resource_provider_->SetRestoreClipStackCallback(base::BindRepeating(
+ &CanvasResourceHost::InitializeForRecording, base::Unretained(this)));
+ }
+ if (old_resource_provider) {
+ old_resource_provider->SetRestoreClipStackCallback(
+ CanvasResourceProvider::RestoreMatrixClipStackCb());
+ }
return old_resource_provider;
}
@@ -27,4 +39,9 @@ void CanvasResourceHost::DiscardResourceProvider() {
UpdateMemoryUsage();
}
+void CanvasResourceHost::InitializeForRecording(cc::PaintCanvas* canvas) {
+ canvas->save();
+ RestoreCanvasMatrixClipStack(canvas);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
index 9c1e69a63b4..16dbe14e169 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
@@ -43,6 +43,8 @@ class PLATFORM_EXPORT CanvasResourceHost {
virtual bool IsPrinting() const { return false; }
private:
+ void InitializeForRecording(cc::PaintCanvas* canvas);
+
std::unique_ptr<CanvasResourceProvider> resource_provider_;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 5ae4615f80f..7955722efa4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -9,21 +9,66 @@
#include "base/stl_util.h"
#include "build/build_config.h"
#include "cc/paint/decode_stashing_image_provider.h"
+#include "cc/paint/display_item_list.h"
#include "cc/tiles/software_image_decode_cache.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_feature_info.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
-#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
+namespace {
+
+bool IsGMBAllowed(IntSize size,
+ const CanvasColorParams& color_params,
+ const gpu::Capabilities& caps) {
+ return gpu::IsImageSizeValidForGpuMemoryBufferFormat(
+ gfx::Size(size), color_params.GetBufferFormat()) &&
+ gpu::IsImageFromGpuMemoryBufferFormatSupported(
+ color_params.GetBufferFormat(), caps);
+}
+
+} // namespace
+
+class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider {
+ public:
+ CanvasImageProvider(cc::ImageDecodeCache* cache_n32,
+ cc::ImageDecodeCache* cache_f16,
+ const gfx::ColorSpace& target_color_space,
+ SkColorType target_color_type,
+ bool is_hardware_decode_cache);
+ ~CanvasImageProvider() override = default;
+
+ // cc::ImageProvider implementation.
+ cc::ImageProvider::ScopedResult GetRasterContent(
+ const cc::DrawImage&) override;
+
+ void ReleaseLockedImages() { locked_images_.clear(); }
+
+ private:
+ void CanUnlockImage(ScopedResult);
+ void CleanupLockedImages();
+
+ bool is_hardware_decode_cache_;
+ bool cleanup_task_pending_ = false;
+ Vector<ScopedResult> locked_images_;
+ cc::PlaybackImageProvider playback_image_provider_n32_;
+ base::Optional<cc::PlaybackImageProvider> playback_image_provider_f16_;
+
+ base::WeakPtrFactory<CanvasImageProvider> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(CanvasImageProvider);
+};
// * Renders to a Skia RAM-backed bitmap.
// * Mailboxing is not supported : cannot be directly composited.
@@ -33,16 +78,14 @@ class CanvasResourceProviderBitmap : public CanvasResourceProvider {
const IntSize& size,
SkFilterQuality filter_quality,
const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: CanvasResourceProvider(kBitmap,
size,
- /*msaa_sample_count=*/0,
+ 0 /*msaa_sample_count*/,
filter_quality,
color_params,
- /*is_origin_top_left=*/true,
- std::move(context_provider_wrapper),
+ true /*is_origin_top_left*/,
+ nullptr /*context_provider_wrapper*/,
std::move(resource_dispatcher)) {}
~CanvasResourceProviderBitmap() override = default;
@@ -56,9 +99,10 @@ class CanvasResourceProviderBitmap : public CanvasResourceProvider {
return nullptr; // Does not support direct compositing
}
- scoped_refptr<StaticBitmapImage> Snapshot() override {
+ scoped_refptr<StaticBitmapImage> Snapshot(
+ const ImageOrientation& orientation) override {
TRACE_EVENT0("blink", "CanvasResourceProviderBitmap::Snapshot");
- return SnapshotInternal();
+ return SnapshotInternal(orientation);
}
sk_sp<SkSurface> CreateSkSurface() const override {
@@ -83,7 +127,6 @@ class CanvasResourceProviderSharedBitmap : public CanvasResourceProviderBitmap {
: CanvasResourceProviderBitmap(size,
filter_quality,
color_params,
- nullptr, // context_provider_wrapper
std::move(resource_dispatcher)) {
DCHECK(ResourceDispatcher());
type_ = kSharedBitmap;
@@ -97,7 +140,8 @@ class CanvasResourceProviderSharedBitmap : public CanvasResourceProviderBitmap {
if (!IsBitmapFormatSupported(color_params.TransferableResourceFormat())) {
// If the rendering format is not supported, downgrate to 8-bits.
// TODO(junov): Should we try 12-12-12-12 and 10-10-10-2?
- color_params.SetCanvasPixelFormat(CanvasPixelFormat::kRGBA8);
+ color_params.SetCanvasPixelFormat(
+ CanvasColorParams::GetNativeCanvasPixelFormat());
}
return CanvasResourceSharedBitmap::Create(Size(), color_params,
@@ -134,9 +178,8 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
context_provider_wrapper,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
bool is_origin_top_left,
- bool is_overlay_candidate,
- bool maybe_single_buffered,
- bool is_accelerated)
+ bool is_accelerated,
+ uint32_t shared_image_usage_flags)
: CanvasResourceProvider(
kSharedImage,
size,
@@ -145,16 +188,20 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
// TODO(khushalsagar): The software path seems to be assuming N32
// somewhere in the later pipeline but for offscreen canvas only.
CanvasColorParams(color_params.ColorSpace(),
- color_params.PixelFormat(),
- color_params.GetOpacityMode(),
- is_accelerated ? CanvasForceRGBA::kForced
- : CanvasForceRGBA::kNotForced),
+ is_accelerated && color_params.PixelFormat() !=
+ CanvasPixelFormat::kF16
+ ? CanvasPixelFormat::kRGBA8
+ : color_params.PixelFormat(),
+ color_params.GetOpacityMode()),
is_origin_top_left,
std::move(context_provider_wrapper),
std::move(resource_dispatcher)),
- is_overlay_candidate_(is_overlay_candidate),
- maybe_single_buffered_(maybe_single_buffered),
- is_accelerated_(is_accelerated) {
+ is_accelerated_(is_accelerated),
+ shared_image_usage_flags_(shared_image_usage_flags),
+ use_oop_rasterization_(ContextProviderWrapper()
+ ->ContextProvider()
+ ->GetCapabilities()
+ .supports_oop_raster) {
resource_ = NewOrRecycledResource();
if (resource_)
EnsureWriteAccess();
@@ -162,24 +209,32 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
~CanvasResourceProviderSharedImage() override {}
- bool IsValid() const final { return GetSkSurface() && !IsGpuContextLost(); }
bool IsAccelerated() const final { return is_accelerated_; }
bool SupportsDirectCompositing() const override { return true; }
+ bool IsValid() const final {
+ if (use_oop_rasterization_)
+ return !IsGpuContextLost();
+ else
+ return GetSkSurface() && !IsGpuContextLost();
+ }
+
bool SupportsSingleBuffering() const override {
- return maybe_single_buffered_;
+ return shared_image_usage_flags_ &
+ gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
}
- GLuint GetBackingTextureHandleForOverwrite() override {
+ gpu::Mailbox GetBackingMailboxForOverwrite(
+ MailboxSyncMode sync_mode) override {
DCHECK(is_accelerated_);
if (IsGpuContextLost())
- return 0u;
+ return gpu::Mailbox();
- FlushGrContext();
- WillDraw();
- return resource()->GetTextureIdForWriteAccess();
+ WillDrawInternal(false);
+ return resource_->GetOrCreateGpuMailbox(sync_mode);
}
+
GLenum GetBackingTextureTarget() const override {
- return resource_->TextureTarget();
+ return resource()->TextureTarget();
}
scoped_refptr<CanvasResource> CreateResource() final {
@@ -187,15 +242,14 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
if (IsGpuContextLost())
return nullptr;
- bool allow_concurrent_read_write_access = maybe_single_buffered_;
return CanvasResourceSharedImage::Create(
Size(), ContextProviderWrapper(), CreateWeakPtr(), FilterQuality(),
- ColorParams(), is_overlay_candidate_, IsOriginTopLeft(),
- allow_concurrent_read_write_access, is_accelerated_);
+ ColorParams(), IsOriginTopLeft(), is_accelerated_,
+ shared_image_usage_flags_);
}
void NotifyTexParamsModified(const CanvasResource* resource) override {
- if (!is_accelerated_)
+ if (!is_accelerated_ || use_oop_rasterization_)
return;
if (resource_.get() == resource) {
@@ -215,6 +269,7 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
if (IsGpuContextLost())
return nullptr;
+ FlushCanvas();
// Its important to end read access and ref the resource before the WillDraw
// call below. Since it relies on resource ref-count to trigger
// copy-on-write and asserts that we only have write access when the
@@ -237,7 +292,8 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
return resource;
}
- scoped_refptr<StaticBitmapImage> Snapshot() override {
+ scoped_refptr<StaticBitmapImage> Snapshot(
+ const ImageOrientation& orientation) override {
TRACE_EVENT0("blink", "CanvasResourceProviderSharedImage::Snapshot");
if (!IsValid())
return nullptr;
@@ -246,9 +302,10 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
// rendering results visible on the GpuMemoryBuffer while we return cpu
// memory, rendererd to by skia, here.
if (!is_accelerated_)
- return SnapshotInternal();
+ return SnapshotInternal(orientation);
if (!cached_snapshot_) {
+ FlushCanvas();
EndWriteAccess();
cached_snapshot_ = resource_->Bitmap();
}
@@ -258,7 +315,7 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
return cached_snapshot_;
}
- void WillDraw() override {
+ void WillDrawInternal(bool write_to_local_texture) {
DCHECK(resource_);
if (IsGpuContextLost())
@@ -293,9 +350,11 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
old_resource_shared_image->GetTextureIdForReadAccess(),
GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
}
+ UMA_HISTOGRAM_BOOLEAN("Blink.Canvas.ContentChangeMode",
+ mode_ == SkSurface::kRetain_ContentChangeMode);
surface_->replaceBackendTexture(CreateGrTextureForResource(),
- GetGrSurfaceOrigin());
- surface_->flush();
+ GetGrSurfaceOrigin(), mode_);
+ mode_ = SkSurface::kRetain_ContentChangeMode;
if (!old_resource_shared_image->has_read_access()) {
RasterInterface()->EndSharedImageAccessDirectCHROMIUM(
old_resource_shared_image->GetTextureIdForReadAccess());
@@ -303,10 +362,55 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
}
}
- EnsureWriteAccess();
+ if (write_to_local_texture)
+ EnsureWriteAccess();
+ else
+ EndWriteAccess();
+
resource()->WillDraw();
}
+ void WillDraw() override { WillDrawInternal(true); }
+
+ void RasterRecord(sk_sp<cc::PaintRecord> last_recording) override {
+ if (!use_oop_rasterization_) {
+ CanvasResourceProvider::RasterRecord(std::move(last_recording));
+ return;
+ }
+ gpu::raster::RasterInterface* ri = RasterInterface();
+ SkColor background_color = ColorParams().GetOpacityMode() == kOpaque
+ ? SK_ColorBLACK
+ : SK_ColorTRANSPARENT;
+
+ auto list = base::MakeRefCounted<cc::DisplayItemList>(
+ cc::DisplayItemList::kTopLevelDisplayItemList);
+
+ list->StartPaint();
+ list->push<cc::DrawRecordOp>(std::move(last_recording));
+ list->EndPaintOfUnpaired(gfx::Rect(Size().Width(), Size().Height()));
+ list->Finalize();
+
+ gfx::Size size(Size().Width(), Size().Height());
+ size_t max_op_size_hint =
+ gpu::raster::RasterInterface::kDefaultMaxOpSizeHint;
+ bool use_lcd = false;
+ gfx::Rect full_raster_rect(Size().Width(), Size().Height());
+ gfx::Rect playback_rect(Size().Width(), Size().Height());
+ gfx::Vector2dF post_translate(0.f, 0.f);
+
+ ri->BeginRasterCHROMIUM(
+ background_color, GetMSAASampleCount(), use_lcd,
+ ColorParams().GetStorageGfxColorSpace(),
+ resource()->GetOrCreateGpuMailbox(kUnverifiedSyncToken).name);
+
+ ri->RasterCHROMIUM(list.get(), GetOrCreateCanvasImageProvider(), size,
+ full_raster_rect, playback_rect, post_translate,
+ 1.f /* post_scale */, false /* requires_clear */,
+ &max_op_size_hint);
+
+ ri->EndRasterCHROMIUM();
+ }
+
bool DoCopyOnWrite() {
// If the canvas is single buffered, concurrent read/writes to the resource
// are allowed. Note that we ignore the resource lost case as well since
@@ -358,7 +462,7 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
GrGLTextureInfo texture_info = {};
texture_info.fID = resource()->GetTextureIdForWriteAccess();
- texture_info.fTarget = resource_->TextureTarget();
+ texture_info.fTarget = resource()->TextureTarget();
texture_info.fFormat = ColorParams().GLSizedInternalFormat();
return GrBackendTexture(Size().Width(), Size().Height(), GrMipMapped::kNo,
texture_info);
@@ -389,7 +493,8 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
DCHECK(!resource()->is_cross_thread())
<< "Write access is only allowed on the owning thread";
- if (current_resource_has_write_access_ || IsGpuContextLost())
+ if (current_resource_has_write_access_ || IsGpuContextLost() ||
+ use_oop_rasterization_)
return;
if (is_accelerated_) {
@@ -410,7 +515,13 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
if (!current_resource_has_write_access_ || IsGpuContextLost())
return;
+ DCHECK(!use_oop_rasterization_);
+
if (is_accelerated_) {
+ // We reset |mode_| here since the draw commands which overwrite the
+ // complete canvas must have been flushed at this point without triggering
+ // copy-on-write.
+ mode_ = SkSurface::kRetain_ContentChangeMode;
// Issue any skia work using this resource before releasing write access.
FlushGrContext();
auto texture_id = resource()->GetTextureIdForWriteAccess();
@@ -432,10 +543,10 @@ class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
return static_cast<const CanvasResourceSharedImage*>(resource_.get());
}
- const bool is_overlay_candidate_;
- const bool maybe_single_buffered_;
const bool is_accelerated_;
+ const uint32_t shared_image_usage_flags_;
bool current_resource_has_write_access_ = false;
+ const bool use_oop_rasterization_;
scoped_refptr<CanvasResource> resource_;
scoped_refptr<StaticBitmapImage> cached_snapshot_;
};
@@ -486,7 +597,7 @@ class CanvasResourceProviderPassThrough final : public CanvasResourceProvider {
return nullptr;
}
- scoped_refptr<StaticBitmapImage> Snapshot() override {
+ scoped_refptr<StaticBitmapImage> Snapshot(const ImageOrientation&) override {
auto resource = GetImportedResource();
if (IsGpuContextLost() || !resource)
return nullptr;
@@ -513,7 +624,7 @@ class CanvasResourceProviderSwapChain final : public CanvasResourceProvider {
msaa_sample_count,
filter_quality,
color_params,
- /*is_origin_top_left=*/true,
+ true /*is_origin_top_left*/,
std::move(context_provider_wrapper),
std::move(resource_dispatcher)),
msaa_sample_count_(msaa_sample_count) {
@@ -542,15 +653,15 @@ class CanvasResourceProviderSwapChain final : public CanvasResourceProvider {
"CanvasResourceProviderSwapChain::ProduceCanvasResource");
if (!IsValid())
return nullptr;
+ FlushCanvas();
if (dirty_) {
- FlushSkia();
resource_->PresentSwapChain();
dirty_ = false;
}
return resource_;
}
- scoped_refptr<StaticBitmapImage> Snapshot() override {
+ scoped_refptr<StaticBitmapImage> Snapshot(const ImageOrientation&) override {
TRACE_EVENT0("blink", "CanvasResourceProviderSwapChain::Snapshot");
// Use ProduceCanvasResource to ensure any queued commands are flushed and
@@ -598,15 +709,6 @@ enum class CanvasResourceType {
const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
CanvasResourceProvider::ResourceUsage usage) {
- static const Vector<CanvasResourceType> kSoftwareFallbackList({
- CanvasResourceType::kBitmap,
- });
-
- static const Vector<CanvasResourceType> kAcceleratedFallbackList({
- CanvasResourceType::kSharedImage,
- // Fallback to software
- CanvasResourceType::kBitmap,
- });
static const Vector<CanvasResourceType> kCompositedFallbackList({
CanvasResourceType::kSharedImage,
@@ -644,14 +746,16 @@ const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
kCompositedFallbackList.begin(),
kCompositedFallbackList.end()));
+ static const Vector<CanvasResourceType> kEmptyList;
switch (usage) {
+ case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
- return kSoftwareFallbackList;
+ NOTREACHED();
+ return kEmptyList;
case CanvasResourceProvider::ResourceUsage::
kSoftwareCompositedResourceUsage:
return kCompositedFallbackList;
- case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
- return kAcceleratedFallbackList;
+
case CanvasResourceProvider::ResourceUsage::
kAcceleratedCompositedResourceUsage:
return kCompositedFallbackList;
@@ -663,39 +767,15 @@ const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
return kAcceleratedDirect3DFallbackList;
case CanvasResourceProvider::ResourceUsage::
kSoftwareCompositedDirect2DResourceUsage:
- return kCompositedFallbackList;
+ NOTREACHED();
+ return kEmptyList;
}
NOTREACHED();
+ return kEmptyList;
}
} // unnamed namespace
-std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::CreateForCanvas(
- const IntSize& size,
- ResourceUsage usage,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
- unsigned msaa_sample_count,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params,
- uint8_t presentation_mode,
- base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
- bool is_origin_top_left) {
- base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage", usage);
-
- std::unique_ptr<CanvasResourceProvider> provider = Create(
- size, usage, context_provider_wrapper, msaa_sample_count, filter_quality,
- color_params, presentation_mode, resource_dispatcher, is_origin_top_left);
-
- if (provider && provider->IsValid()) {
- base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
- provider->IsAccelerated());
- base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
- provider->type_);
- }
-
- return provider;
-}
-
std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
const IntSize& size,
ResourceUsage usage,
@@ -706,6 +786,9 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
uint8_t presentation_mode,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
bool is_origin_top_left) {
+ DCHECK_EQ(msaa_sample_count, 0u);
+ DCHECK(usage != ResourceUsage::kSoftwareResourceUsage);
+
std::unique_ptr<CanvasResourceProvider> provider;
bool is_gpu_memory_buffer_image_allowed = false;
@@ -718,15 +801,12 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
const int max_texture_size = context_capabilities.max_texture_size;
if (size.Width() > max_texture_size || size.Height() > max_texture_size)
- usage = ResourceUsage::kSoftwareResourceUsage;
+ return CreateBitmapProvider(size, filter_quality, color_params);
is_gpu_memory_buffer_image_allowed =
(presentation_mode & kAllowImageChromiumPresentationMode) &&
Platform::Current()->GetGpuMemoryBufferManager() &&
- gpu::IsImageSizeValidForGpuMemoryBufferFormat(
- gfx::Size(size), color_params.GetBufferFormat()) &&
- gpu::IsImageFromGpuMemoryBufferFormatSupported(
- color_params.GetBufferFormat(), context_capabilities);
+ IsGMBAllowed(size, color_params, context_capabilities);
is_swap_chain_allowed =
(presentation_mode & kAllowSwapChainPresentationMode) &&
@@ -764,54 +844,57 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
break;
case CanvasResourceType::kBitmap:
provider = std::make_unique<CanvasResourceProviderBitmap>(
- size, filter_quality, color_params, context_provider_wrapper,
- resource_dispatcher);
+ size, filter_quality, color_params, resource_dispatcher);
break;
case CanvasResourceType::kSharedImage: {
- DCHECK_NE(usage, ResourceUsage::kSoftwareResourceUsage);
-
if (!context_provider_wrapper)
continue;
- const bool is_accelerated =
- usage == ResourceUsage::kAcceleratedResourceUsage ||
- usage == ResourceUsage::kAcceleratedCompositedResourceUsage ||
- usage == ResourceUsage::kAcceleratedDirect2DResourceUsage ||
- usage == ResourceUsage::kAcceleratedDirect3DResourceUsage;
-
- // If the rendering will be in software and we don't have GMB support,
- // fallback to bitmap provider type.
- if (!is_accelerated && !is_gpu_memory_buffer_image_allowed)
- continue;
-
- // texture_storage_image is required to create shared images supporting
- // scanout usage.
const bool can_use_overlays =
is_gpu_memory_buffer_image_allowed &&
context_provider_wrapper->ContextProvider()
->GetCapabilities()
.texture_storage_image;
- const bool is_overlay_candidate =
- (usage == ResourceUsage::kAcceleratedDirect2DResourceUsage ||
- usage == ResourceUsage::kAcceleratedDirect3DResourceUsage ||
- usage == ResourceUsage::kAcceleratedCompositedResourceUsage ||
- usage == ResourceUsage::kSoftwareCompositedResourceUsage) &&
- can_use_overlays;
-
- // Single buffering requires concurrent read/write access to the
- // resource which is sub-optimal for software raster since that would
- // require concurrent access to the resource on the CPU and GPU, so
- // enable it for accelerated low latency canvas only.
- const bool maybe_single_buffered =
- (usage == ResourceUsage::kAcceleratedDirect2DResourceUsage ||
- usage == ResourceUsage::kAcceleratedDirect3DResourceUsage) &&
- is_gpu_memory_buffer_image_allowed;
+ bool is_accelerated = false;
+ uint32_t shared_image_usage_flags = 0u;
+ switch (usage) {
+ case ResourceUsage::kSoftwareResourceUsage:
+ NOTREACHED();
+ continue;
+ case ResourceUsage::kSoftwareCompositedResourceUsage:
+ // Rendering in software with accelerated compositing.
+ if (!is_gpu_memory_buffer_image_allowed)
+ continue;
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_DISPLAY;
+ if (can_use_overlays)
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
+ is_accelerated = false;
+ break;
+ case ResourceUsage::kAcceleratedDirect2DResourceUsage:
+ case ResourceUsage::kAcceleratedDirect3DResourceUsage:
+ if (can_use_overlays) {
+ shared_image_usage_flags |=
+ gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
+ }
+ FALLTHROUGH;
+ case ResourceUsage::kAcceleratedCompositedResourceUsage:
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_DISPLAY;
+ if (can_use_overlays)
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
+ FALLTHROUGH;
+ case ResourceUsage::kAcceleratedResourceUsage:
+ is_accelerated = true;
+ break;
+ case ResourceUsage::kSoftwareCompositedDirect2DResourceUsage:
+ NOTREACHED();
+ continue;
+ }
provider = std::make_unique<CanvasResourceProviderSharedImage>(
size, msaa_sample_count, filter_quality, color_params,
context_provider_wrapper, resource_dispatcher, is_origin_top_left,
- is_overlay_candidate, maybe_single_buffered, is_accelerated);
+ is_accelerated, shared_image_usage_flags);
} break;
}
if (!provider->IsValid())
@@ -822,35 +905,53 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
return nullptr;
}
-class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider {
- public:
- CanvasImageProvider(cc::ImageDecodeCache* cache_n32,
- cc::ImageDecodeCache* cache_f16,
- const gfx::ColorSpace& target_color_space,
- SkColorType target_color_type,
- bool is_hardware_decode_cache);
- ~CanvasImageProvider() override = default;
-
- // cc::ImageProvider implementation.
- cc::ImageProvider::ScopedResult GetRasterContent(
- const cc::DrawImage&) override;
+std::unique_ptr<CanvasResourceProvider>
+CanvasResourceProvider::CreateBitmapProvider(
+ const IntSize& size,
+ SkFilterQuality filter_quality,
+ const CanvasColorParams& color_params) {
+ auto provider = std::make_unique<CanvasResourceProviderBitmap>(
+ size, filter_quality, color_params, nullptr /*resource_dispatcher*/);
+ if (provider->IsValid())
+ return provider;
- void ReleaseLockedImages() { locked_images_.clear(); }
+ return nullptr;
+}
- private:
- void CanUnlockImage(ScopedResult);
- void CleanupLockedImages();
+std::unique_ptr<CanvasResourceProvider>
+CanvasResourceProvider::CreateSharedImageProvider(
+ const IntSize& size,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
+ SkFilterQuality filter_quality,
+ const CanvasColorParams& color_params,
+ bool is_origin_top_left,
+ RasterMode raster_mode,
+ uint32_t shared_image_usage_flags) {
+ if (!context_provider_wrapper)
+ return nullptr;
- bool is_hardware_decode_cache_;
- bool cleanup_task_pending_ = false;
- Vector<ScopedResult> locked_images_;
- cc::PlaybackImageProvider playback_image_provider_n32_;
- base::Optional<cc::PlaybackImageProvider> playback_image_provider_f16_;
+ const auto& caps =
+ context_provider_wrapper->ContextProvider()->GetCapabilities();
+ if (size.Width() > caps.max_texture_size ||
+ size.Height() > caps.max_texture_size) {
+ return nullptr;
+ }
- base::WeakPtrFactory<CanvasImageProvider> weak_factory_{this};
+ bool can_use_overlays =
+ IsGMBAllowed(size, color_params, caps) && caps.texture_storage_image;
+ if (!can_use_overlays)
+ shared_image_usage_flags &= ~gpu::SHARED_IMAGE_USAGE_SCANOUT;
+
+ auto provider = std::make_unique<CanvasResourceProviderSharedImage>(
+ size, 0 /* msaa_sample_count */, filter_quality, color_params,
+ context_provider_wrapper, nullptr /*resource_dispatcher*/,
+ is_origin_top_left, raster_mode == RasterMode::kGPU,
+ shared_image_usage_flags);
+ if (provider->IsValid())
+ return provider;
- DISALLOW_COPY_AND_ASSIGN(CanvasImageProvider);
-};
+ return nullptr;
+}
CanvasResourceProvider::CanvasImageProvider::CanvasImageProvider(
cc::ImageDecodeCache* cache_n32,
@@ -962,6 +1063,8 @@ CanvasResourceProvider::CanvasResourceProvider(
}
CanvasResourceProvider::~CanvasResourceProvider() {
+ UMA_HISTOGRAM_EXACT_LINEAR("Blink.Canvas.MaximumInflightResources",
+ max_inflight_resources_, 20);
if (context_provider_wrapper_)
context_provider_wrapper_->RemoveObserver(this);
}
@@ -972,52 +1075,57 @@ SkSurface* CanvasResourceProvider::GetSkSurface() const {
return surface_.get();
}
-void CanvasResourceProvider::InitializePaintCanvas() {
- // Since canvas_ has a reference to canvas_image_provider_, canvas must be
- // deleted before the image_provider.
- canvas_ = nullptr;
- canvas_image_provider_ = nullptr;
-
- // Create an ImageDecodeCache for half float images only if the canvas is
- // using half float back storage.
- cc::ImageDecodeCache* cache_f16 = nullptr;
- if (ColorParams().GetSkColorType() == kRGBA_F16_SkColorType)
- cache_f16 = ImageDecodeCacheF16();
- canvas_image_provider_ = std::make_unique<CanvasImageProvider>(
- ImageDecodeCacheRGBA8(), cache_f16, gfx::ColorSpace::CreateSRGB(),
- color_params_.GetSkColorType(), use_hardware_decode_cache());
+void CanvasResourceProvider::EnsureSkiaCanvas() {
+ WillDraw();
+
+ if (skia_canvas_)
+ return;
cc::SkiaPaintCanvas::ContextFlushes context_flushes;
- if (IsAccelerated() &&
+ if (IsAccelerated() && ContextProviderWrapper() &&
!ContextProviderWrapper()
->ContextProvider()
->GetGpuFeatureInfo()
.IsWorkaroundEnabled(gpu::DISABLE_2D_CANVAS_AUTO_FLUSH)) {
- context_flushes.enable =
- canvas_heuristic_parameters::kEnableGrContextFlushes;
- context_flushes.max_draws_before_flush =
- canvas_heuristic_parameters::kMaxDrawsBeforeContextFlush;
+ context_flushes.enable = true;
+ context_flushes.max_draws_before_flush = kMaxDrawsBeforeContextFlush;
}
- canvas_ = std::make_unique<cc::SkiaPaintCanvas>(GetSkSurface()->getCanvas(),
- canvas_image_provider_.get(),
- context_flushes);
+ skia_canvas_ = std::make_unique<cc::SkiaPaintCanvas>(
+ GetSkSurface()->getCanvas(), GetOrCreateCanvasImageProvider(),
+ context_flushes);
+}
+
+CanvasResourceProvider::CanvasImageProvider*
+CanvasResourceProvider::GetOrCreateCanvasImageProvider() {
+ if (!canvas_image_provider_) {
+ // Create an ImageDecodeCache for half float images only if the canvas is
+ // using half float back storage.
+ cc::ImageDecodeCache* cache_f16 = nullptr;
+ if (ColorParams().GetSkColorType() == kRGBA_F16_SkColorType)
+ cache_f16 = ImageDecodeCacheF16();
+ canvas_image_provider_ = std::make_unique<CanvasImageProvider>(
+ ImageDecodeCacheRGBA8(), cache_f16, gfx::ColorSpace::CreateSRGB(),
+ color_params_.GetSkColorType(), use_hardware_decode_cache());
+ }
+ return canvas_image_provider_.get();
}
cc::PaintCanvas* CanvasResourceProvider::Canvas() {
- WillDraw();
+ if (!recorder_) {
+ // A raw pointer is safe here because the callback is only used by the
+ // |recorder_|.
+ recorder_ = std::make_unique<MemoryManagedPaintRecorder>(WTF::BindRepeating(
+ &CanvasResourceProvider::SetNeedsFlush, WTF::Unretained(this)));
- if (!canvas_) {
- TRACE_EVENT0("blink", "CanvasResourceProvider::Canvas");
- DCHECK(!canvas_image_provider_);
- InitializePaintCanvas();
+ return recorder_->beginRecording(Size().Width(), Size().Height());
}
- return canvas_.get();
+ return recorder_->getRecordingCanvas();
}
void CanvasResourceProvider::OnContextDestroyed() {
if (canvas_image_provider_) {
- DCHECK(canvas_);
- canvas_->reset_image_provider();
+ DCHECK(skia_canvas_);
+ skia_canvas_->reset_image_provider();
canvas_image_provider_.reset();
}
}
@@ -1027,16 +1135,19 @@ void CanvasResourceProvider::ReleaseLockedImages() {
canvas_image_provider_->ReleaseLockedImages();
}
-scoped_refptr<StaticBitmapImage> CanvasResourceProvider::SnapshotInternal() {
+scoped_refptr<StaticBitmapImage> CanvasResourceProvider::SnapshotInternal(
+ const ImageOrientation& orientation) {
if (!IsValid())
return nullptr;
auto paint_image = MakeImageSnapshot();
DCHECK(!paint_image.GetSkImage()->isTextureBacked());
- return UnacceleratedStaticBitmapImage::Create(std::move(paint_image));
+ return UnacceleratedStaticBitmapImage::Create(std::move(paint_image),
+ orientation);
}
cc::PaintImage CanvasResourceProvider::MakeImageSnapshot() {
+ FlushCanvas();
auto sk_image = GetSkSurface()->makeImageSnapshot();
if (!sk_image)
return cc::PaintImage();
@@ -1076,7 +1187,23 @@ GrContext* CanvasResourceProvider::GetGrContext() const {
return context_provider_wrapper_->ContextProvider()->GetGrContext();
}
-void CanvasResourceProvider::FlushSkia() const {
+sk_sp<cc::PaintRecord> CanvasResourceProvider::FlushCanvas() {
+ if (!HasRecordedDrawOps())
+ return nullptr;
+ sk_sp<cc::PaintRecord> last_recording = recorder_->finishRecordingAsPicture();
+ RasterRecord(last_recording);
+ needs_flush_ = false;
+ cc::PaintCanvas* canvas =
+ recorder_->beginRecording(Size().Width(), Size().Height());
+ if (restore_clip_stack_callback_)
+ restore_clip_stack_callback_.Run(canvas);
+ return last_recording;
+}
+
+void CanvasResourceProvider::RasterRecord(
+ sk_sp<cc::PaintRecord> last_recording) {
+ EnsureSkiaCanvas();
+ skia_canvas_->drawPicture(std::move(last_recording));
GetSkSurface()->flush();
}
@@ -1094,6 +1221,18 @@ bool CanvasResourceProvider::WritePixels(const SkImageInfo& orig_info,
TRACE_EVENT0("blink", "CanvasResourceProvider::WritePixels");
DCHECK(IsValid());
+ DCHECK(!HasRecordedDrawOps());
+
+ EnsureSkiaCanvas();
+
+ // Apply clipstack to skia_canvas_ and then restore it to original state once
+ // we leave this scope. This is needed because each recording initializes and
+ // resets this state after every flush. restore_clip_stack_callback_ sets the
+ // initial save required for a restore.
+ cc::PaintCanvasAutoRestore auto_restore(skia_canvas_.get(), false);
+ if (restore_clip_stack_callback_)
+ restore_clip_stack_callback_.Run(skia_canvas_.get());
+
return GetSkSurface()->getCanvas()->writePixels(orig_info, pixels, row_bytes,
x, y);
}
@@ -1142,7 +1281,7 @@ void CanvasResourceProvider::RecycleResource(
scoped_refptr<CanvasResource> resource) {
// We don't want to keep an arbitrary large number of canvases.
if (canvas_resources_.size() >
- canvas_heuristic_parameters::kMaxRecycledCanvasResources)
+ static_cast<unsigned int>(kMaxRecycledCanvasResources))
return;
// Need to check HasOneRef() because if there are outstanding references to
@@ -1163,9 +1302,17 @@ void CanvasResourceProvider::ClearRecycledResources() {
canvas_resources_.clear();
}
+void CanvasResourceProvider::OnDestroyResource() {
+ --num_inflight_resources_;
+}
+
scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() {
- if (canvas_resources_.IsEmpty())
+ if (canvas_resources_.IsEmpty()) {
canvas_resources_.push_back(CreateResource());
+ ++num_inflight_resources_;
+ if (num_inflight_resources_ > max_inflight_resources_)
+ max_inflight_resources_ = num_inflight_resources_;
+ }
if (IsSingleBuffered()) {
DCHECK_EQ(canvas_resources_.size(), 1u);
@@ -1203,4 +1350,37 @@ scoped_refptr<CanvasResource> CanvasResourceProvider::GetImportedResource()
return canvas_resources_.back();
}
+void CanvasResourceProvider::SkipQueuedDrawCommands() {
+ // Note that this function only gets called when canvas needs a full repaint,
+ // so always update the |mode_| to discard the old copy of canvas content.
+ mode_ = SkSurface::kDiscard_ContentChangeMode;
+
+ if (!HasRecordedDrawOps())
+ return;
+ recorder_->finishRecordingAsPicture();
+ cc::PaintCanvas* canvas =
+ recorder_->beginRecording(Size().Width(), Size().Height());
+ if (restore_clip_stack_callback_)
+ restore_clip_stack_callback_.Run(canvas);
+}
+
+void CanvasResourceProvider::SetRestoreClipStackCallback(
+ RestoreMatrixClipStackCb callback) {
+ DCHECK(restore_clip_stack_callback_.is_null() || callback.is_null());
+ restore_clip_stack_callback_ = std::move(callback);
+}
+
+void CanvasResourceProvider::RestoreBackBuffer(const cc::PaintImage& image) {
+ DCHECK_EQ(image.height(), Size().Height());
+ DCHECK_EQ(image.width(), Size().Width());
+ EnsureSkiaCanvas();
+ cc::PaintFlags copy_paint;
+ copy_paint.setBlendMode(SkBlendMode::kSrc);
+ skia_canvas_->drawImage(image, 0, 0, &copy_paint);
+}
+
+bool CanvasResourceProvider::HasRecordedDrawOps() const {
+ return recorder_ && recorder_->ListHasDrawOps();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
index 910b0e526c0..e88d3511299 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -8,6 +8,8 @@
#include "cc/paint/skia_paint_canvas.h"
#include "cc/raster/playback_image_provider.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
+#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/skia/include/core/SkSurface.h"
class GrContext;
@@ -56,8 +58,9 @@ class PLATFORM_EXPORT CanvasResourceProvider
public:
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
+ // todo(juanmihd@) ResourceUsage will be removed soon, try avoiding using this
enum class ResourceUsage {
- kSoftwareResourceUsage = 0,
+ kSoftwareResourceUsage = 0, // deprecated
kSoftwareCompositedResourceUsage = 1,
kAcceleratedResourceUsage = 2,
kAcceleratedCompositedResourceUsage = 3,
@@ -92,19 +95,33 @@ class PLATFORM_EXPORT CanvasResourceProvider
kMaxValue = kSwapChain,
};
- void static RecordTypeToUMA(ResourceProviderType type);
+ using RestoreMatrixClipStackCb =
+ base::RepeatingCallback<void(cc::PaintCanvas*)>;
- static std::unique_ptr<CanvasResourceProvider> CreateForCanvas(
+ // todo(juanmihd@) Check whether SkFilterQuality is needed in all of this, or
+ // just call setFilterQuality explicitly
+ static std::unique_ptr<CanvasResourceProvider> CreateBitmapProvider(
+ const IntSize&,
+ SkFilterQuality,
+ const CanvasColorParams&);
+
+ // Specifies whether the provider should rasterize paint commands on the CPU
+ // or GPU. This is used to support software raster with GPU compositing
+ enum class RasterMode {
+ kGPU,
+ kCPU,
+ };
+
+ static std::unique_ptr<CanvasResourceProvider> CreateSharedImageProvider(
const IntSize&,
- ResourceUsage,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
- unsigned msaa_sample_count,
SkFilterQuality,
const CanvasColorParams&,
- uint8_t presentation_mode,
- base::WeakPtr<CanvasResourceDispatcher>,
- bool is_origin_top_left = true);
+ bool is_origin_top_left,
+ RasterMode raster_mode,
+ uint32_t shared_image_usage_flags);
+ // TODO(juanmihd): Clean up creation methods/usage. See crbug.com/1035589.
static std::unique_ptr<CanvasResourceProvider> Create(
const IntSize&,
ResourceUsage,
@@ -119,16 +136,18 @@ class PLATFORM_EXPORT CanvasResourceProvider
// Use Snapshot() for capturing a frame that is intended to be displayed via
// the compositor. Cases that are destined to be transferred via a
// TransferableResource should call ProduceCanvasResource() instead.
+ // The ImageOrientationEnum conveys the desired orientation of the image, and
+ // should be derived from the source of the bitmap data.
virtual scoped_refptr<CanvasResource> ProduceCanvasResource() = 0;
- virtual scoped_refptr<StaticBitmapImage> Snapshot() = 0;
+ virtual scoped_refptr<StaticBitmapImage> Snapshot(
+ const ImageOrientation& = kDefaultImageOrientation) = 0;
// WebGraphicsContext3DProvider::DestructionObserver implementation.
void OnContextDestroyed() override;
cc::PaintCanvas* Canvas();
- void InitializePaintCanvas();
void ReleaseLockedImages();
- void FlushSkia() const;
+ sk_sp<cc::PaintRecord> FlushCanvas();
const CanvasColorParams& ColorParams() const { return color_params_; }
void SetFilterQuality(SkFilterQuality quality) { filter_quality_ = quality; }
const IntSize& Size() const { return size_; }
@@ -172,9 +191,11 @@ class PLATFORM_EXPORT CanvasResourceProvider
size_t row_bytes,
int x,
int y);
- virtual GLuint GetBackingTextureHandleForOverwrite() {
+
+ virtual gpu::Mailbox GetBackingMailboxForOverwrite(
+ MailboxSyncMode sync_mode) {
NOTREACHED();
- return 0;
+ return gpu::Mailbox();
}
virtual GLenum GetBackingTextureTarget() const { return GL_TEXTURE_2D; }
virtual void* GetPixelBufferAddressForOverwrite() {
@@ -196,7 +217,19 @@ class PLATFORM_EXPORT CanvasResourceProvider
return canvas_resources_.size();
}
+ void SkipQueuedDrawCommands();
+ void SetRestoreClipStackCallback(RestoreMatrixClipStackCb);
+ bool needs_flush() const { return needs_flush_; }
+ void RestoreBackBuffer(const cc::PaintImage&);
+
+ ResourceProviderType GetType() const { return type_; }
+ bool HasRecordedDrawOps() const;
+
+ void OnDestroyResource();
+
protected:
+ class CanvasImageProvider;
+
gpu::gles2::GLES2Interface* ContextGL() const;
gpu::raster::RasterInterface* RasterInterface() const;
GrContext* GetGrContext() const;
@@ -209,7 +242,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
: kBottomLeft_GrSurfaceOrigin;
}
SkFilterQuality FilterQuality() const { return filter_quality_; }
- scoped_refptr<StaticBitmapImage> SnapshotInternal();
+ scoped_refptr<StaticBitmapImage> SnapshotInternal(const ImageOrientation&);
scoped_refptr<CanvasResource> GetImportedResource() const;
CanvasResourceProvider(const ResourceProviderType&,
@@ -227,13 +260,14 @@ class PLATFORM_EXPORT CanvasResourceProvider
// decodes/uploads in the cache is invalidated only when the canvas contents
// change.
cc::PaintImage MakeImageSnapshot();
+ virtual void RasterRecord(sk_sp<cc::PaintRecord>);
+ CanvasImageProvider* GetOrCreateCanvasImageProvider();
ResourceProviderType type_;
mutable sk_sp<SkSurface> surface_; // mutable for lazy init
+ SkSurface::ContentChangeMode mode_ = SkSurface::kRetain_ContentChangeMode;
private:
- class CanvasImageProvider;
-
virtual sk_sp<SkSurface> CreateSkSurface() const = 0;
virtual scoped_refptr<CanvasResource> CreateResource();
bool use_hardware_decode_cache() const {
@@ -245,6 +279,8 @@ class PLATFORM_EXPORT CanvasResourceProvider
cc::ImageDecodeCache* ImageDecodeCacheRGBA8();
cc::ImageDecodeCache* ImageDecodeCacheF16();
+ void EnsureSkiaCanvas();
+ void SetNeedsFlush() { needs_flush_ = true; }
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher_;
@@ -254,7 +290,10 @@ class PLATFORM_EXPORT CanvasResourceProvider
const CanvasColorParams color_params_;
const bool is_origin_top_left_;
std::unique_ptr<CanvasImageProvider> canvas_image_provider_;
- std::unique_ptr<cc::SkiaPaintCanvas> canvas_;
+ std::unique_ptr<cc::SkiaPaintCanvas> skia_canvas_;
+ std::unique_ptr<PaintRecorder> recorder_;
+
+ bool needs_flush_ = false;
const cc::PaintImage::Id snapshot_paint_image_id_;
cc::PaintImage::ContentId snapshot_paint_image_content_id_ =
@@ -267,6 +306,17 @@ class PLATFORM_EXPORT CanvasResourceProvider
bool resource_recycling_enabled_ = true;
bool is_single_buffered_ = false;
+ // The maximum number of in-flight resources waiting to be used for recycling.
+ static constexpr int kMaxRecycledCanvasResources = 2;
+ // The maximum number of draw ops executed on the canvas, after which the
+ // underlying GrContext is flushed.
+ static constexpr int kMaxDrawsBeforeContextFlush = 50;
+
+ size_t num_inflight_resources_ = 0;
+ size_t max_inflight_resources_ = 0;
+
+ RestoreMatrixClipStackCb restore_clip_stack_callback_;
+
base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
index 85b64c72473..2924293e7bd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -74,9 +74,9 @@ class CanvasResourceProviderTest : public Test {
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -92,7 +92,9 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
EXPECT_TRUE(provider->SupportsDirectCompositing());
EXPECT_TRUE(provider->SupportsSingleBuffering());
EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
- EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
+ // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
+ // will internally force it to kRGBA8
+ EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
kColorParams.GetOpacityMode());
@@ -103,16 +105,14 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
- auto provider = CanvasResourceProvider::Create(
- kSize, CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
- context_provider_wrapper_, 0 /* msaa_sample_count */,
- kLow_SkFilterQuality, kColorParams,
- CanvasResourceProvider::kDefaultPresentationMode,
- nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ auto provider = CanvasResourceProvider::CreateSharedImageProvider(
+ kSize, context_provider_wrapper_, kLow_SkFilterQuality, kColorParams,
+ true /*is_origin_top_left*/, CanvasResourceProvider::RasterMode::kGPU,
+ 0u /*shared_image_usage_flags*/);
EXPECT_EQ(provider->Size(), kSize);
EXPECT_TRUE(provider->IsValid());
@@ -120,7 +120,9 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
EXPECT_TRUE(provider->SupportsDirectCompositing());
EXPECT_FALSE(provider->SupportsSingleBuffering());
EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
- EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
+ // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
+ // will internally force it to kRGBA8
+ EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
kColorParams.GetOpacityMode());
@@ -129,14 +131,13 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderUnacceleratedOverlay) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
- CanvasResourceProvider::ResourceUsage::
- kSoftwareCompositedDirect2DResourceUsage,
+ CanvasResourceProvider::ResourceUsage::kSoftwareCompositedResourceUsage,
context_provider_wrapper_, 0 /* msaa_sample_count */,
kLow_SkFilterQuality, kColorParams,
CanvasResourceProvider::kAllowImageChromiumPresentationMode,
@@ -161,9 +162,9 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderUnacceleratedOverlay) {
TEST_F(CanvasResourceProviderTest,
CanvasResourceProviderSharedImageResourceRecycling) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -180,7 +181,9 @@ TEST_F(CanvasResourceProviderTest,
EXPECT_FALSE(provider->IsSingleBuffered());
EXPECT_FALSE(provider->SupportsSingleBuffering());
EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
- EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
+ // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
+ // will internally force it to kRGBA8
+ EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
kColorParams.GetOpacityMode());
@@ -215,9 +218,9 @@ TEST_F(CanvasResourceProviderTest,
TEST_F(CanvasResourceProviderTest,
CanvasResourceProviderSharedImageStaticBitmapImage) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -233,21 +236,25 @@ TEST_F(CanvasResourceProviderTest,
auto image = provider->Snapshot();
ASSERT_TRUE(image);
auto new_image = provider->Snapshot();
- EXPECT_EQ(image->GetMailbox(), new_image->GetMailbox());
+ EXPECT_EQ(image->GetMailboxHolder().mailbox,
+ new_image->GetMailboxHolder().mailbox);
EXPECT_EQ(provider->ProduceCanvasResource()->GetOrCreateGpuMailbox(
kOrderingBarrier),
- image->GetMailbox());
+ image->GetMailboxHolder().mailbox);
// Resource updated after draw.
provider->Canvas()->clear(SK_ColorWHITE);
+ provider->FlushCanvas();
new_image = provider->Snapshot();
- EXPECT_NE(new_image->GetMailbox(), image->GetMailbox());
+ EXPECT_NE(new_image->GetMailboxHolder().mailbox,
+ image->GetMailboxHolder().mailbox);
// Resource recycled.
- auto original_mailbox = image->GetMailbox();
+ auto original_mailbox = image->GetMailboxHolder().mailbox;
image.reset();
provider->Canvas()->clear(SK_ColorBLACK);
- EXPECT_EQ(original_mailbox, provider->Snapshot()->GetMailbox());
+ provider->FlushCanvas();
+ EXPECT_EQ(original_mailbox, provider->Snapshot()->GetMailboxHolder().mailbox);
}
TEST_F(CanvasResourceProviderTest,
@@ -259,9 +266,9 @@ TEST_F(CanvasResourceProviderTest,
fake_context->SetCapabilities(caps);
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -282,16 +289,12 @@ TEST_F(CanvasResourceProviderTest,
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderBitmap) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
- auto provider = CanvasResourceProvider::Create(
- kSize, CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
- context_provider_wrapper_, 0 /* msaa_sample_count */,
- kLow_SkFilterQuality, kColorParams,
- CanvasResourceProvider::kAllowImageChromiumPresentationMode,
- nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ auto provider = CanvasResourceProvider::CreateBitmapProvider(
+ kSize, kLow_SkFilterQuality, kColorParams);
EXPECT_EQ(provider->Size(), kSize);
EXPECT_TRUE(provider->IsValid());
@@ -308,9 +311,9 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderBitmap) {
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedBitmap) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
MockCanvasResourceDispatcherClient client;
CanvasResourceDispatcher resource_dispatcher(
@@ -343,9 +346,9 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedBitmap) {
TEST_F(CanvasResourceProviderTest,
CanvasResourceProviderDirect2DGpuMemoryBuffer) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -361,7 +364,9 @@ TEST_F(CanvasResourceProviderTest,
EXPECT_TRUE(provider->SupportsDirectCompositing());
EXPECT_TRUE(provider->SupportsSingleBuffering());
EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
- EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
+ // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
+ // will internally force it to kRGBA8
+ EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
kColorParams.GetOpacityMode());
@@ -373,9 +378,9 @@ TEST_F(CanvasResourceProviderTest,
TEST_F(CanvasResourceProviderTest,
CanvasResourceProviderDirect3DGpuMemoryBuffer) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -404,7 +409,7 @@ TEST_F(CanvasResourceProviderTest,
ExternalCanvasResource::Create(
mailbox, kSize, GL_TEXTURE_2D, kColorParams,
SharedGpuContext::ContextProviderWrapper(), provider->CreateWeakPtr(),
- kMedium_SkFilterQuality, /*is_origin_top_left=*/true);
+ kMedium_SkFilterQuality, true /*is_origin_top_left*/);
// NewOrRecycledResource() would return nullptr before an ImportResource().
EXPECT_TRUE(provider->ImportResource(resource));
@@ -417,9 +422,9 @@ TEST_F(CanvasResourceProviderTest,
// https://crbug.com/985366
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect3DTexture) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -435,7 +440,9 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect3DTexture) {
EXPECT_TRUE(provider->SupportsDirectCompositing());
EXPECT_FALSE(provider->SupportsSingleBuffering());
EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
- EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
+ // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
+ // will internally force it to kRGBA8
+ EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
kColorParams.GetOpacityMode());
@@ -453,10 +460,56 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect3DTexture) {
callback->Run(gpu::SyncToken(), true /* is_lost */);
}
+TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_Bitmap) {
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
+
+ auto provider = CanvasResourceProvider::CreateBitmapProvider(
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
+ kColorParams);
+ EXPECT_FALSE(provider->SupportsDirectCompositing());
+ provider = CanvasResourceProvider::CreateBitmapProvider(
+ IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
+ kColorParams);
+ EXPECT_FALSE(provider->SupportsDirectCompositing());
+ provider = CanvasResourceProvider::CreateBitmapProvider(
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
+ kColorParams);
+ EXPECT_FALSE(provider->SupportsDirectCompositing());
+}
+
+TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_SharedImage) {
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
+
+ auto provider = CanvasResourceProvider::CreateSharedImageProvider(
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize), context_provider_wrapper_,
+ kLow_SkFilterQuality, kColorParams, true /*is_origin_top_left*/,
+ CanvasResourceProvider::RasterMode::kGPU,
+ 0u /*shared_image_usage_flags*/);
+ EXPECT_TRUE(provider->SupportsDirectCompositing());
+ provider = CanvasResourceProvider::CreateSharedImageProvider(
+ IntSize(kMaxTextureSize, kMaxTextureSize), context_provider_wrapper_,
+ kLow_SkFilterQuality, kColorParams, true /*is_origin_top_left*/,
+ CanvasResourceProvider::RasterMode::kGPU,
+ 0u /*shared_image_usage_flags*/);
+ EXPECT_TRUE(provider->SupportsDirectCompositing());
+ provider = CanvasResourceProvider::CreateSharedImageProvider(
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize), context_provider_wrapper_,
+ kLow_SkFilterQuality, kColorParams, true /*is_origin_top_left*/,
+ CanvasResourceProvider::RasterMode::kGPU,
+ 0u /*shared_image_usage_flags*/);
+ // The CanvasResourceProvider for SharedImage should not be created or valid
+ // if the texture size is greater than the maximum value
+ EXPECT_TRUE(!provider || !provider->IsValid());
+}
+
TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize) {
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
for (int i = 0;
i < static_cast<int>(CanvasResourceProvider::ResourceUsage::kMaxValue);
@@ -464,18 +517,20 @@ TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize) {
SCOPED_TRACE(i);
auto usage = static_cast<CanvasResourceProvider::ResourceUsage>(i);
bool should_support_compositing = false;
+ std::unique_ptr<CanvasResourceProvider> provider;
switch (usage) {
+ // Skipping ResourceUsages that will be removed after this refactor
+ // bug(1035589)
case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
- should_support_compositing = false;
- break;
+ continue;
+ case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
+ continue;
case CanvasResourceProvider::ResourceUsage::
kSoftwareCompositedResourceUsage:
FALLTHROUGH;
case CanvasResourceProvider::ResourceUsage::
kSoftwareCompositedDirect2DResourceUsage:
FALLTHROUGH;
- case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
- FALLTHROUGH;
case CanvasResourceProvider::ResourceUsage::
kAcceleratedCompositedResourceUsage:
FALLTHROUGH;
@@ -488,39 +543,42 @@ TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize) {
break;
}
- auto provider = CanvasResourceProvider::Create(
- IntSize(kMaxTextureSize - 1, kMaxTextureSize), usage,
- context_provider_wrapper_, 0 /* msaa_sample_count */,
- kLow_SkFilterQuality, kColorParams,
- CanvasResourceProvider::kAllowImageChromiumPresentationMode,
- nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ provider = CanvasResourceProvider::Create(
+ IntSize(kMaxTextureSize - 1, kMaxTextureSize), usage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+
EXPECT_EQ(provider->SupportsDirectCompositing(),
should_support_compositing);
- provider = CanvasResourceProvider::Create(
- IntSize(kMaxTextureSize, kMaxTextureSize), usage,
- context_provider_wrapper_, 0 /* msaa_sample_count */,
- kLow_SkFilterQuality, kColorParams,
- CanvasResourceProvider::kAllowImageChromiumPresentationMode,
- nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ provider = CanvasResourceProvider::Create(
+ IntSize(kMaxTextureSize, kMaxTextureSize), usage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+
EXPECT_EQ(provider->SupportsDirectCompositing(),
should_support_compositing);
- provider = CanvasResourceProvider::Create(
- IntSize(kMaxTextureSize + 1, kMaxTextureSize), usage,
- context_provider_wrapper_, 0 /* msaa_sample_count */,
- kLow_SkFilterQuality, kColorParams,
- CanvasResourceProvider::kAllowImageChromiumPresentationMode,
- nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ provider = CanvasResourceProvider::Create(
+ IntSize(kMaxTextureSize + 1, kMaxTextureSize), usage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+
EXPECT_FALSE(provider->SupportsDirectCompositing());
}
}
TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect2DSwapChain) {
const IntSize kSize(10, 10);
- const CanvasColorParams kColorParams(CanvasColorSpace::kSRGB,
- CanvasPixelFormat::kRGBA8, kNonOpaque,
- CanvasForceRGBA::kNotForced);
+ const CanvasColorParams kColorParams(
+ CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
+ kNonOpaque);
auto provider = CanvasResourceProvider::Create(
kSize,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
index 680b810bf83..20929011633 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
@@ -194,7 +194,7 @@ void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
void* src_data,
- int num_elements,
+ size_t num_elements,
CanvasColorSpace src_color_space,
ImageDataStorageFormat src_storage_format,
CanvasColorSpace dst_color_space,
@@ -221,14 +221,13 @@ bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
(src_storage_format == kUint8ClampedArrayStorageFormat)
? CanvasPixelFormat::kRGBA8
: CanvasPixelFormat::kF16,
- kNonOpaque, CanvasForceRGBA::kNotForced)
+ kNonOpaque)
.GetSkColorSpaceForSkSurfaces();
if (!src_sk_color_space.get())
src_sk_color_space = SkColorSpace::MakeSRGB();
sk_sp<SkColorSpace> dst_sk_color_space =
- CanvasColorParams(dst_color_space, dst_canvas_pixel_format, kNonOpaque,
- CanvasForceRGBA::kNotForced)
+ CanvasColorParams(dst_color_space, dst_canvas_pixel_format, kNonOpaque)
.GetSkColorSpaceForSkSurfaces();
if (!dst_sk_color_space.get())
dst_sk_color_space = SkColorSpace::MakeSRGB();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
index 30c6c677174..3323b5d2bf9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
@@ -65,7 +65,7 @@ class ColorCorrectionTestUtils {
static bool ConvertPixelsToColorSpaceAndPixelFormatForTest(
void* src_data,
- int num_elements,
+ size_t num_elements,
CanvasColorSpace src_color_space,
ImageDataStorageFormat src_storage_format,
CanvasColorSpace dst_color_space,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md b/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md
index f8334d739ce..d40b6ed2b7a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md
@@ -16,7 +16,7 @@ Inputs: `PaintArtifact`
Outputs: List of `cc::Layer` objects and `cc::PropertyTree`'s.
The algorithm walks through the list of `PaintChunks` in the `PaintArtifact`,
-allocating new `c::Layers` if the `PaintChunk` cannot merge into an existing
+allocating new `cc::Layers` if the `PaintChunk` cannot merge into an existing
`cc::Layer`. The reasons why it would not be able to do so are:
1. The `PaintChunk` requires a foreign layer (see below)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
index 70cd474d009..9f8c025c661 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
@@ -21,7 +21,7 @@ class ChunkToLayerMapperTest : public testing::Test {
DEFINE_STATIC_LOCAL(
base::Optional<PaintChunk::Id>, id,
(PaintChunk::Id(fake_client, DisplayItem::kDrawingFirst)));
- PaintChunk chunk(0, 0, *id, state);
+ PaintChunk chunk(0, 1, *id, state);
return chunk;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
index cdaf3e8115e..1e7e0c1f113 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -24,7 +24,7 @@ namespace blink {
ContentLayerClientImpl::ContentLayerClientImpl()
: cc_picture_layer_(cc::PictureLayer::Create(this)),
- raster_invalidator_(
+ raster_invalidation_function_(
base::BindRepeating(&ContentLayerClientImpl::InvalidateRect,
base::Unretained(this))),
layer_state_(PropertyTreeState::Uninitialized()) {}
@@ -42,9 +42,12 @@ void ContentLayerClientImpl::AppendAdditionalInfoAsJSON(
json.SetValue("paintChunkContents", paint_chunk_debug_data_->Clone());
#endif
- if ((flags & kLayerTreeIncludesPaintInvalidations) &&
- raster_invalidator_.GetTracking())
- raster_invalidator_.GetTracking()->AsJSON(&json);
+ if ((flags & (kLayerTreeIncludesInvalidations |
+ kLayerTreeIncludesDetailedInvalidations)) &&
+ raster_invalidator_.GetTracking()) {
+ raster_invalidator_.GetTracking()->AsJSON(
+ &json, flags & kLayerTreeIncludesDetailedInvalidations);
+ }
#if DCHECK_IS_ON()
if (flags & kLayerTreeIncludesPaintRecords) {
@@ -73,7 +76,7 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
auto json = std::make_unique<JSONObject>();
json->SetString("data", chunk.ToString());
json->SetArray("displayItems",
- paint_artifact->GetDisplayItemList().SubsequenceAsJSON(
+ paint_artifact->GetDisplayItemList().DisplayItemsAsJSON(
chunk.begin_index, chunk.end_index,
DisplayItemList::kShowOnlyDisplayItemTypes));
paint_chunk_debug_data_->PushObject(std::move(json));
@@ -85,8 +88,8 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
if (layer_state != layer_state_)
cc_picture_layer_->SetSubtreePropertyChanged();
- raster_invalidator_.Generate(paint_artifact, paint_chunks, layer_bounds,
- layer_state);
+ raster_invalidator_.Generate(raster_invalidation_function_, paint_artifact,
+ paint_chunks, layer_bounds, layer_state);
layer_state_ = layer_state;
// Note: cc::Layer API assumes the layer bounds start at (0, 0), but the
@@ -97,7 +100,6 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
cc_picture_layer_->SetOffsetToTransformParent(
layer_bounds.OffsetFromOrigin());
cc_picture_layer_->SetBounds(layer_bounds.size());
- cc_picture_layer_->SetIsDrawable(true);
cc_picture_layer_->SetHitTestable(true);
base::Optional<RasterUnderInvalidationCheckingParams> params;
@@ -111,14 +113,20 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
display_item_list, cc::DisplayItemList::kTopLevelDisplayItemList,
base::OptionalOrNullptr(params));
- cc_picture_layer_->SetSafeOpaqueBackgroundColor(
- paint_chunks[0].safe_opaque_background_color);
+ cc_picture_layer_->SetIsDrawable(
+ (!layer_bounds.IsEmpty() && cc_display_item_list_->TotalOpCount()) ||
+ // Backdrop filters require the layer to be drawable even if the layer
+ // draws nothing.
+ !layer_state.Effect().BackdropFilter().IsEmpty());
+
+ auto safe_opaque_background_color =
+ paint_artifact->SafeOpaqueBackgroundColor(paint_chunks);
+ cc_picture_layer_->SetSafeOpaqueBackgroundColor(safe_opaque_background_color);
// TODO(masonfreed): We don't need to set the background color here; only the
// safe opaque background color matters. But making that change would require
// rebaselining 787 tests to remove the "background_color" property from the
// layer dumps.
- cc_picture_layer_->SetBackgroundColor(
- paint_chunks[0].safe_opaque_background_color);
+ cc_picture_layer_->SetBackgroundColor(safe_opaque_background_color);
return cc_picture_layer_;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
index 5ce14faec81..aeb201b488f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
@@ -74,6 +74,8 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
scoped_refptr<cc::PictureLayer> cc_picture_layer_;
scoped_refptr<cc::DisplayItemList> cc_display_item_list_;
RasterInvalidator raster_invalidator_;
+ RasterInvalidator::RasterInvalidationFunction raster_invalidation_function_;
+
PropertyTreeState layer_state_;
String debug_name_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
index 318662e15cc..3502e78074f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
@@ -25,10 +25,8 @@ String PointerAsString(const void* ptr) {
} // namespace
// Create a JSON version of the specified |layer|.
-std::unique_ptr<JSONObject> CCLayerAsJSON(
- const cc::Layer* layer,
- LayerTreeFlags flags,
- const FloatPoint& offset_from_transform_node) {
+std::unique_ptr<JSONObject> CCLayerAsJSON(const cc::Layer* layer,
+ LayerTreeFlags flags) {
auto json = std::make_unique<JSONObject>();
if (flags & kLayerTreeIncludesDebugInfo) {
@@ -38,8 +36,11 @@ std::unique_ptr<JSONObject> CCLayerAsJSON(
json->SetString("name", String(layer->DebugName().c_str()));
- if (offset_from_transform_node != FloatPoint())
- json->SetArray("position", PointAsJSONArray(offset_from_transform_node));
+ if (layer->offset_to_transform_parent() != gfx::Vector2dF()) {
+ json->SetArray(
+ "position",
+ PointAsJSONArray(FloatPoint(layer->offset_to_transform_parent())));
+ }
// This is testing against gfx::Size(), *not* whether the size is empty.
if (layer->bounds() != gfx::Size())
@@ -127,13 +128,15 @@ int LayersAsJSON::AddTransformJSON(
}
void LayersAsJSON::AddLayer(const cc::Layer& layer,
- const FloatPoint& offset,
const TransformPaintPropertyNode& transform,
const LayerAsJSONClient* json_client) {
- if (!(flags_ & kLayerTreeIncludesAllLayers) && !layer.DrawsContent())
+ if (!(flags_ & kLayerTreeIncludesAllLayers) && !layer.DrawsContent() &&
+ (layer.DebugName() == "LayoutView #document" ||
+ layer.DebugName() == "Inner Viewport Scroll Layer" ||
+ layer.DebugName() == "Scrolling Contents Layer"))
return;
- auto layer_json = CCLayerAsJSON(&layer, flags_, offset);
+ auto layer_json = CCLayerAsJSON(&layer, flags_);
if (json_client) {
json_client->AppendAdditionalInfoAsJSON(flags_, layer, *(layer_json.get()));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h
index 0008f97f94a..4be8eed283d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h
@@ -16,7 +16,6 @@ class Layer;
namespace blink {
-class FloatPoint;
class JSONArray;
class JSONObject;
class TransformPaintPropertyNode;
@@ -27,9 +26,10 @@ enum {
kLayerTreeNormal = 0,
// Dump extra debugging info like layer addresses.
kLayerTreeIncludesDebugInfo = 1 << 0,
- kLayerTreeIncludesPaintInvalidations = 1 << 1,
- kLayerTreeIncludesPaintingPhases = 1 << 2,
- kLayerTreeIncludesAllLayers = 1 << 3,
+ kLayerTreeIncludesInvalidations = 1 << 1,
+ kLayerTreeIncludesDetailedInvalidations = 1 << 2,
+ kLayerTreeIncludesPaintingPhases = 1 << 3,
+ kLayerTreeIncludesAllLayers = 1 << 4,
kLayerTreeIncludesCompositingReasons = 1 << 5,
kLayerTreeIncludesPaintRecords = 1 << 6,
// Outputs all layers as a layer tree. The default is output children
@@ -50,7 +50,6 @@ class PLATFORM_EXPORT LayersAsJSON {
LayersAsJSON(LayerTreeFlags);
void AddLayer(const cc::Layer& layer,
- const FloatPoint& offset,
const TransformPaintPropertyNode& transform,
const LayerAsJSONClient* json_client);
@@ -69,8 +68,7 @@ class PLATFORM_EXPORT LayersAsJSON {
PLATFORM_EXPORT std::unique_ptr<JSONObject> CCLayerAsJSON(
const cc::Layer* layer,
- LayerTreeFlags flags,
- const FloatPoint& position);
+ LayerTreeFlags flags);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 76d426253a5..015e3f9418f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -7,24 +7,26 @@
#include <memory>
#include <utility>
-#include "cc/layers/layer.h"
+#include "cc/layers/scrollbar_layer_base.h"
#include "cc/paint/display_item_list.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/mutator_host.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
@@ -60,6 +62,14 @@ void PaintArtifactCompositor::WillBeRemovedFromFrame() {
root_layer_->RemoveAllChildren();
}
+std::unique_ptr<JSONArray> PaintArtifactCompositor::GetPendingLayersAsJSON(
+ const PaintArtifact* paint_artifact) const {
+ std::unique_ptr<JSONArray> result = std::make_unique<JSONArray>();
+ for (const PendingLayer& pending_layer : pending_layers_)
+ result->PushObject(pending_layer.ToJSON(paint_artifact));
+ return result;
+}
+
// Get a JSON representation of what layers exist for this PAC. Note that
// |paint_artifact| is only needed for pre-CAP mode.
std::unique_ptr<JSONObject> PaintArtifactCompositor::GetLayersAsJSON(
@@ -67,6 +77,13 @@ std::unique_ptr<JSONObject> PaintArtifactCompositor::GetLayersAsJSON(
const PaintArtifact* paint_artifact) const {
DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
paint_artifact);
+
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ !tracks_raster_invalidations_) {
+ flags &= ~(kLayerTreeIncludesInvalidations |
+ kLayerTreeIncludesDetailedInvalidations);
+ }
+
LayersAsJSON layers_as_json(flags);
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
for (const auto& layer : root_layer_->children()) {
@@ -90,28 +107,47 @@ std::unique_ptr<JSONObject> PaintArtifactCompositor::GetLayersAsJSON(
}
}
DCHECK(transform);
- layers_as_json.AddLayer(*layer,
- FloatPoint(layer->offset_to_transform_parent()),
- *transform, json_client);
+ layers_as_json.AddLayer(*layer, *transform, json_client);
}
} else {
for (const auto& paint_chunk : paint_artifact->PaintChunks()) {
const auto& display_item =
paint_artifact->GetDisplayItemList()[paint_chunk.begin_index];
- DCHECK(display_item.IsForeignLayer());
- const auto& foreign_layer_display_item =
- static_cast<const ForeignLayerDisplayItem&>(display_item);
- cc::Layer* layer = foreign_layer_display_item.GetLayer();
- layers_as_json.AddLayer(
- *layer, foreign_layer_display_item.Offset(),
- paint_chunk.properties.Transform(),
- foreign_layer_display_item.GetLayerAsJSONClient());
+ cc::Layer* layer = nullptr;
+ const LayerAsJSONClient* json_client = nullptr;
+ if (display_item.IsGraphicsLayerWrapper()) {
+ const GraphicsLayerDisplayItem& graphics_layer_display_item =
+ static_cast<const GraphicsLayerDisplayItem&>(display_item);
+ layer = graphics_layer_display_item.GetGraphicsLayer().CcLayer();
+ json_client = &graphics_layer_display_item.GetGraphicsLayer();
+ } else {
+ DCHECK(display_item.IsForeignLayer());
+ const auto& foreign_layer_display_item =
+ static_cast<const ForeignLayerDisplayItem&>(display_item);
+ layer = foreign_layer_display_item.GetLayer();
+ json_client = foreign_layer_display_item.GetLayerAsJSONClient();
+ }
+ // Need to retrieve the transform from |pending_layers_| so that
+ // any decomposition is not double-reported via |layer|'s
+ // offset_from_transform_parent and |paint_chunk|'s transform inside
+ // AddLayer.
+ const TransformPaintPropertyNode* transform = nullptr;
+ for (const auto& pending_layer : pending_layers_) {
+ if (pending_layer.property_tree_state.Transform().CcNodeId(
+ layer->property_tree_sequence_number()) ==
+ layer->transform_tree_index()) {
+ transform = &pending_layer.property_tree_state.Transform();
+ break;
+ }
+ }
+ DCHECK(transform);
+ layers_as_json.AddLayer(*layer, *transform, json_client);
}
}
return layers_as_json.Finalize();
}
-static scoped_refptr<cc::Layer> ForeignLayerForPaintChunk(
+static scoped_refptr<cc::Layer> CcLayerForPaintChunk(
const PaintArtifact& paint_artifact,
const PaintChunk& paint_chunk,
const FloatPoint& pending_layer_offset) {
@@ -120,33 +156,44 @@ static scoped_refptr<cc::Layer> ForeignLayerForPaintChunk(
const auto& display_item =
paint_artifact.GetDisplayItemList()[paint_chunk.begin_index];
- if (!display_item.IsForeignLayer())
+ if (!display_item.IsForeignLayer() &&
+ !display_item.IsGraphicsLayerWrapper()) {
return nullptr;
+ }
- // When a foreign layer's offset_to_transform_parent() changes, we don't
- // call PaintArtifaceCompositor::SetNeedsUpdate() because the update won't
- // change anything but cause unnecessary commit. Though
- // UpdateTouchActionRects() depends on offset_to_transform_parent(), a
- // foreign layer chunk doesn't have hit_test_data.
+ // UpdateTouchActionRects() depends on the layer's offset, but when the
+ // layer's offset changes, we do not call SetNeedsUpdate() (this is an
+ // optimization because the update would only cause an extra commit). This is
+ // only OK if the [Foreign|Graphics]Layer doesn't have hit test data.
DCHECK(!paint_chunk.hit_test_data);
- const auto& foreign_layer_display_item =
- static_cast<const ForeignLayerDisplayItem&>(display_item);
- auto* layer = foreign_layer_display_item.GetLayer();
- layer->SetOffsetToTransformParent(gfx::Vector2dF(
- foreign_layer_display_item.Offset() + pending_layer_offset));
+ cc::Layer* layer = nullptr;
+ FloatPoint layer_offset;
+ if (display_item.IsGraphicsLayerWrapper()) {
+ const auto& graphics_layer_display_item =
+ static_cast<const GraphicsLayerDisplayItem&>(display_item);
+ layer = graphics_layer_display_item.GetGraphicsLayer().CcLayer();
+ layer_offset = FloatPoint(graphics_layer_display_item.GetGraphicsLayer()
+ .GetOffsetFromTransformNode());
+ } else {
+ const auto& foreign_layer_display_item =
+ static_cast<const ForeignLayerDisplayItem&>(display_item);
+ layer = foreign_layer_display_item.GetLayer();
+ layer_offset = foreign_layer_display_item.Offset();
+ }
+ layer->SetOffsetToTransformParent(
+ gfx::Vector2dF(layer_offset + pending_layer_offset));
return layer;
}
const TransformPaintPropertyNode&
-PaintArtifactCompositor::ScrollOffsetTranslationForLayer(
+PaintArtifactCompositor::NearestScrollTranslationForLayer(
const PaintArtifact& paint_artifact,
const PendingLayer& pending_layer) {
- if (const auto* scroll_hit_test =
- ScrollHitTestForLayer(paint_artifact, pending_layer)) {
- if (scroll_hit_test->scroll_offset)
- return *scroll_hit_test->scroll_offset;
- }
+ if (const auto* scroll_translation =
+ ScrollTranslationForLayer(paint_artifact, pending_layer))
+ return *scroll_translation;
+
const auto& transform = pending_layer.property_tree_state.Transform();
// TODO(pdr): This could be a performance issue because it crawls up the
// transform tree for each pending layer. If this is on profiles, we should
@@ -154,41 +201,33 @@ PaintArtifactCompositor::ScrollOffsetTranslationForLayer(
return transform.NearestScrollTranslationNode();
}
-const HitTestData::ScrollHitTest*
-PaintArtifactCompositor::ScrollHitTestForLayer(
+const TransformPaintPropertyNode*
+PaintArtifactCompositor::ScrollTranslationForLayer(
const PaintArtifact& paint_artifact,
const PendingLayer& pending_layer) {
if (pending_layer.paint_chunk_indices.size() != 1)
return nullptr;
- const auto& paint_chunk =
- paint_artifact.PaintChunks()[pending_layer.paint_chunk_indices[0]];
- if (paint_chunk.size() != 1)
- return nullptr;
-
- const HitTestData* hit_test_data = paint_chunk.hit_test_data.get();
- if (!hit_test_data)
+ const auto& paint_chunk = pending_layer.FirstPaintChunk(paint_artifact);
+ if (!paint_chunk.hit_test_data)
return nullptr;
- return base::OptionalOrNullptr(hit_test_data->scroll_hit_test);
+ return paint_chunk.hit_test_data->scroll_translation;
}
scoped_refptr<cc::Layer>
PaintArtifactCompositor::ScrollHitTestLayerForPendingLayer(
const PaintArtifact& paint_artifact,
const PendingLayer& pending_layer) {
- const auto* scroll_hit_test =
- ScrollHitTestForLayer(paint_artifact, pending_layer);
- if (!scroll_hit_test)
- return nullptr;
- const auto* scroll_offset = scroll_hit_test->scroll_offset;
- if (!scroll_offset)
+ const auto* scroll_translation =
+ ScrollTranslationForLayer(paint_artifact, pending_layer);
+ if (!scroll_translation)
return nullptr;
// We shouldn't decomposite scroll transform nodes.
DCHECK_EQ(FloatPoint(), pending_layer.offset_of_decomposited_transforms);
- const auto& scroll_node = *scroll_offset->ScrollNode();
+ const auto& scroll_node = *scroll_translation->ScrollNode();
auto scroll_element_id = scroll_node.GetCompositorElementId();
scoped_refptr<cc::Layer> scroll_layer;
@@ -209,17 +248,20 @@ PaintArtifactCompositor::ScrollHitTestLayerForPendingLayer(
// match (see: crbug.com/753124). To do this, use
// |scroll_hit_test->scroll_container_bounds|.
auto bounds = scroll_node.ContainerRect().Size();
- // Mark the layer as scrollable.
- // TODO(pdr): When CAP launches this parameter for bounds will not be
- // needed.
- scroll_layer->SetScrollable(static_cast<gfx::Size>(bounds));
// Set the layer's bounds equal to the container because the scroll layer
// does not scroll.
scroll_layer->SetBounds(static_cast<gfx::Size>(bounds));
+
+ if (scroll_node.NodeChanged() != PaintPropertyChangeType::kUnchanged) {
+ scroll_layer->SetNeedsPushProperties();
+ scroll_layer->SetNeedsCommit();
+ }
+
return scroll_layer;
}
-scoped_refptr<cc::Layer> PaintArtifactCompositor::ScrollbarLayerForPendingLayer(
+scoped_refptr<cc::ScrollbarLayerBase>
+PaintArtifactCompositor::ScrollbarLayerForPendingLayer(
const PaintArtifact& paint_artifact,
const PendingLayer& pending_layer) {
if (pending_layer.paint_chunk_indices.size() != 1)
@@ -235,29 +277,11 @@ scoped_refptr<cc::Layer> PaintArtifactCompositor::ScrollbarLayerForPendingLayer(
if (!item.IsScrollbar())
return nullptr;
- const auto& scrollbar_item = static_cast<const ScrollbarDisplayItem&>(item);
- scoped_refptr<cc::Layer> scrollbar_layer;
- for (auto& existing_layer : scrollbar_layers_) {
- if (existing_layer->element_id() == scrollbar_item.ElementId())
- scrollbar_layer = existing_layer;
- }
- if (scrollbar_layer) {
- cc::Scrollbar* scrollbar = scrollbar_item.GetScrollbar();
- if (scrollbar->NeedsRepaintPart(cc::THUMB) ||
- scrollbar->NeedsRepaintPart(cc::TRACK_BUTTONS_TICKMARKS))
- scrollbar_layer->SetNeedsDisplay();
- } else {
- scrollbar_layer = scrollbar_item.CreateLayer();
- }
-
// We should never decomposite scroll translations, so we don't need to adjust
// the layer's offset for decomposited transforms.
DCHECK_EQ(FloatPoint(), pending_layer.offset_of_decomposited_transforms);
- const IntRect& rect = scrollbar_item.GetRect();
- scrollbar_layer->SetOffsetToTransformParent(
- gfx::Vector2dF(FloatPoint(rect.Location())));
- scrollbar_layer->SetBounds(gfx::Size(rect.Size()));
- return scrollbar_layer;
+
+ return static_cast<const ScrollbarDisplayItem&>(item).GetLayer();
}
std::unique_ptr<ContentLayerClientImpl>
@@ -281,20 +305,20 @@ PaintArtifactCompositor::CompositedLayerForPendingLayer(
scoped_refptr<const PaintArtifact> paint_artifact,
const PendingLayer& pending_layer,
Vector<std::unique_ptr<ContentLayerClientImpl>>& new_content_layer_clients,
- Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers,
- Vector<scoped_refptr<cc::Layer>>& new_scrollbar_layers) {
+ Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers) {
auto paint_chunks =
paint_artifact->GetPaintChunkSubset(pending_layer.paint_chunk_indices);
DCHECK(paint_chunks.size());
const PaintChunk& first_paint_chunk = paint_chunks[0];
- DCHECK(first_paint_chunk.size());
- // If the paint chunk is a foreign layer, just return that layer.
- if (scoped_refptr<cc::Layer> foreign_layer = ForeignLayerForPaintChunk(
- *paint_artifact, first_paint_chunk,
- pending_layer.offset_of_decomposited_transforms)) {
+ scoped_refptr<cc::Layer> cc_layer;
+ // If the paint chunk is a foreign layer or placeholder for a GraphicsLayer,
+ // just return its cc::Layer.
+ if ((cc_layer = CcLayerForPaintChunk(
+ *paint_artifact, first_paint_chunk,
+ pending_layer.offset_of_decomposited_transforms))) {
DCHECK_EQ(paint_chunks.size(), 1u);
- return foreign_layer;
+ return cc_layer;
}
// If the paint chunk is a scroll hit test layer, lookup/create the layer.
@@ -304,9 +328,8 @@ PaintArtifactCompositor::CompositedLayerForPendingLayer(
return scroll_layer;
}
- if (scoped_refptr<cc::Layer> scrollbar_layer =
+ if (auto scrollbar_layer =
ScrollbarLayerForPendingLayer(*paint_artifact, pending_layer)) {
- new_scrollbar_layers.push_back(scrollbar_layer);
return scrollbar_layer;
}
@@ -315,11 +338,9 @@ PaintArtifactCompositor::CompositedLayerForPendingLayer(
ClientForPaintChunk(first_paint_chunk);
IntRect cc_combined_bounds = EnclosingIntRect(pending_layer.bounds);
- auto cc_layer = content_layer_client->UpdateCcPictureLayer(
+ cc_layer = content_layer_client->UpdateCcPictureLayer(
paint_artifact, paint_chunks, cc_combined_bounds,
pending_layer.property_tree_state);
- if (cc_combined_bounds.IsEmpty())
- cc_layer->SetIsDrawable(false);
new_content_layer_clients.push_back(std::move(content_layer_client));
@@ -345,8 +366,7 @@ void PaintArtifactCompositor::UpdateTouchActionRects(
const auto& chunk_state = chunk.properties.GetPropertyTreeState();
for (const auto& touch_action_rect : hit_test_data->touch_action_rects) {
- auto rect =
- FloatClipRect(FloatRect(PixelSnappedIntRect(touch_action_rect.rect)));
+ auto rect = FloatClipRect(FloatRect(touch_action_rect.rect));
if (!GeometryMapper::LocalToAncestorVisualRect(chunk_state, layer_state,
rect)) {
continue;
@@ -364,12 +384,13 @@ void PaintArtifactCompositor::UpdateNonFastScrollableRegions(
cc::Layer* layer,
const gfx::Vector2dF& layer_offset,
const PropertyTreeState& layer_state,
- const PaintChunkSubset& paint_chunks) {
+ const PaintChunkSubset& paint_chunks,
+ PropertyTreeManager* property_tree_manager) {
cc::Region non_fast_scrollable_regions_in_layer_space;
for (const auto& chunk : paint_chunks) {
// Add any non-fast scrollable hit test data from the paint chunk.
const auto* hit_test_data = chunk.hit_test_data.get();
- if (!hit_test_data || !hit_test_data->scroll_hit_test)
+ if (!hit_test_data || hit_test_data->scroll_hit_test_rect.IsEmpty())
continue;
// Skip the scroll hit test rect if it is for scrolling this cc::Layer.
@@ -377,21 +398,21 @@ void PaintArtifactCompositor::UpdateNonFastScrollableRegions(
// pre-CompositeAfterPaint does not paint scroll hit test data for
// composited scrollers.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- if (layer->scrollable()) {
- const auto* scroll_offset =
- hit_test_data->scroll_hit_test->scroll_offset;
- if (scroll_offset) {
- const auto& scroll_node = *scroll_offset->ScrollNode();
- auto scroll_element_id = scroll_node.GetCompositorElementId();
- if (layer->element_id() == scroll_element_id)
- continue;
- }
+ if (const auto* scroll_translation = hit_test_data->scroll_translation) {
+ const auto& scroll_node = *scroll_translation->ScrollNode();
+ auto scroll_element_id = scroll_node.GetCompositorElementId();
+ if (layer->element_id() == scroll_element_id)
+ continue;
+ // Ensure the cc scroll node to prepare for possible descendant nodes
+ // referenced by later composited layers. This can't be done by ensuring
+ // parent transform node in EnsureCompositorTransformNode() if the
+ // transform tree and the scroll tree have different topologies.
+ DCHECK(property_tree_manager);
+ property_tree_manager->EnsureCompositorScrollNode(*scroll_translation);
}
}
- const auto& bounds =
- hit_test_data->scroll_hit_test->scroll_container_bounds;
- auto rect = FloatClipRect(FloatRect(bounds));
+ FloatClipRect rect(FloatRect(chunk.hit_test_data->scroll_hit_test_rect));
const auto& chunk_state = chunk.properties.GetPropertyTreeState();
if (!GeometryMapper::LocalToAncestorVisualRect(chunk_state, layer_state,
rect)) {
@@ -399,7 +420,7 @@ void PaintArtifactCompositor::UpdateNonFastScrollableRegions(
}
rect.MoveBy(FloatPoint(-layer_offset.x(), -layer_offset.y()));
non_fast_scrollable_regions_in_layer_space.Union(
- (gfx::Rect)EnclosingIntRect(rect.Rect()));
+ EnclosingIntRect(rect.Rect()));
}
layer->SetNonFastScrollableRegion(non_fast_scrollable_regions_in_layer_space);
}
@@ -436,53 +457,111 @@ PaintArtifactCompositor::PendingLayer::PendingLayer(
paint_chunk_indices.push_back(chunk_index);
}
-void PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) {
- DCHECK(compositing_type != kRequiresOwnLayer &&
- guest.compositing_type != kRequiresOwnLayer);
- paint_chunk_indices.AppendVector(guest.paint_chunk_indices);
- FloatClipRect guest_bounds_in_home(guest.bounds);
- GeometryMapper::LocalToAncestorVisualRect(
- guest.property_tree_state, property_tree_state, guest_bounds_in_home);
- bounds.Unite(guest_bounds_in_home.Rect());
- // TODO(crbug.com/701991): Upgrade GeometryMapper.
- // If we knew the new bounds is enclosed by the mapped opaque region of
- // the guest layer, we can deduce the merged layer being opaque too, and
- // update rect_known_to_be_opaque accordingly.
+FloatRect PaintArtifactCompositor::PendingLayer::UniteRectsKnownToBeOpaque(
+ const FloatRect& a,
+ const FloatRect& b) {
+ // Check a or b by itself.
+ FloatRect maximum(a);
+ float maximum_area = a.Size().Area();
+ if (b.Size().Area() > maximum_area) {
+ maximum = b;
+ maximum_area = b.Size().Area();
+ }
+ // Check the regions that include the intersection of a and b. This can be
+ // done by taking the intersection and expanding it vertically and
+ // horizontally. These expanded intersections will both still be fully opaque.
+ FloatRect intersection = a;
+ intersection.InclusiveIntersect(b);
+ if (!intersection.IsZero()) {
+ FloatRect vert_expanded_intersection(intersection);
+ vert_expanded_intersection.ShiftYEdgeTo(std::min(a.Y(), b.Y()));
+ vert_expanded_intersection.ShiftMaxYEdgeTo(std::max(a.MaxY(), b.MaxY()));
+ if (vert_expanded_intersection.Size().Area() > maximum_area) {
+ maximum = vert_expanded_intersection;
+ maximum_area = vert_expanded_intersection.Size().Area();
+ }
+ FloatRect horiz_expanded_intersection(intersection);
+ horiz_expanded_intersection.ShiftXEdgeTo(std::min(a.X(), b.X()));
+ horiz_expanded_intersection.ShiftMaxXEdgeTo(std::max(a.MaxX(), b.MaxX()));
+ if (horiz_expanded_intersection.Size().Area() > maximum_area) {
+ maximum = horiz_expanded_intersection;
+ maximum_area = horiz_expanded_intersection.Size().Area();
+ }
+ }
+ return maximum;
}
-static bool CanUpcastTo(const PropertyTreeState& guest,
- const PropertyTreeState& home);
+FloatRect PaintArtifactCompositor::PendingLayer::MapRectKnownToBeOpaque(
+ const PropertyTreeState& new_state) const {
+ if (rect_known_to_be_opaque.IsEmpty())
+ return FloatRect();
-bool PaintArtifactCompositor::PendingLayer::CanMerge(
- const PendingLayer& guest,
- const PropertyTreeState& guest_state) const {
- if (compositing_type == kRequiresOwnLayer ||
- guest.compositing_type == kRequiresOwnLayer) {
- return false;
+ FloatClipRect float_clip_rect(rect_known_to_be_opaque);
+ GeometryMapper::LocalToAncestorVisualRect(property_tree_state, new_state,
+ float_clip_rect);
+ return float_clip_rect.IsTight() ? float_clip_rect.Rect() : FloatRect();
+}
+
+std::unique_ptr<JSONObject> PaintArtifactCompositor::PendingLayer::ToJSON(
+ const PaintArtifact* paint_artifact) const {
+ std::unique_ptr<JSONObject> result = std::make_unique<JSONObject>();
+ result->SetArray("bounds", RectAsJSONArray(bounds));
+ result->SetArray("rect_known_to_be_opaque",
+ RectAsJSONArray(rect_known_to_be_opaque));
+ result->SetObject("property_tree_state", property_tree_state.ToJSON());
+ result->SetArray("offset_of_decomposited_transforms",
+ PointAsJSONArray(offset_of_decomposited_transforms));
+ std::unique_ptr<JSONArray> chunks = std::make_unique<JSONArray>();
+ for (wtf_size_t chunk_index : paint_chunk_indices) {
+ if (paint_artifact) {
+ StringBuilder sb;
+ sb.AppendFormat("index=%i ", chunk_index);
+ sb.Append(paint_artifact->PaintChunks()[chunk_index].ToString());
+ chunks->PushString(sb.ToString());
+ } else {
+ chunks->PushInteger(chunk_index);
+ }
}
- if (&property_tree_state.Effect().Unalias() !=
- &guest_state.Effect().Unalias()) {
+ result->SetArray("paint_chunks", std::move(chunks));
+ return result;
+}
+
+FloatRect PaintArtifactCompositor::PendingLayer::VisualRectForOverlapTesting()
+ const {
+ FloatClipRect visual_rect(bounds);
+ GeometryMapper::LocalToAncestorVisualRect(
+ property_tree_state, PropertyTreeState::Root(), visual_rect,
+ kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect,
+ kExpandVisualRectForAnimation);
+ return visual_rect.Rect();
+}
+
+bool PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) {
+ PropertyTreeState new_state = PropertyTreeState::Uninitialized();
+ if (!CanMerge(guest, guest.property_tree_state, &new_state, &bounds))
return false;
- }
- return CanUpcastTo(guest_state, property_tree_state);
+
+ paint_chunk_indices.AppendVector(guest.paint_chunk_indices);
+ rect_known_to_be_opaque =
+ UniteRectsKnownToBeOpaque(MapRectKnownToBeOpaque(new_state),
+ guest.MapRectKnownToBeOpaque(new_state));
+ property_tree_state = new_state;
+ return true;
}
void PaintArtifactCompositor::PendingLayer::Upcast(
const PropertyTreeState& new_state) {
DCHECK(compositing_type != kRequiresOwnLayer);
+ if (property_tree_state == new_state)
+ return;
+
FloatClipRect float_clip_rect(bounds);
GeometryMapper::LocalToAncestorVisualRect(property_tree_state, new_state,
float_clip_rect);
bounds = float_clip_rect.Rect();
+ rect_known_to_be_opaque = MapRectKnownToBeOpaque(new_state);
property_tree_state = new_state;
- // TODO(crbug.com/701991): Upgrade GeometryMapper.
- // A local visual rect mapped to an ancestor space may become a polygon
- // (e.g. consider transformed clip), also effects may affect the opaque
- // region. To determine whether the layer is still opaque, we need to
- // query conservative opaque rect after mapping to an ancestor space,
- // which is not supported by GeometryMapper yet.
- rect_known_to_be_opaque = FloatRect();
}
const PaintChunk& PaintArtifactCompositor::PendingLayer::FirstPaintChunk(
@@ -490,55 +569,127 @@ const PaintChunk& PaintArtifactCompositor::PendingLayer::FirstPaintChunk(
return paint_artifact.PaintChunks()[paint_chunk_indices[0]];
}
-static bool IsNonCompositingAncestorOf(
- const TransformPaintPropertyNode& unaliased_ancestor,
- const TransformPaintPropertyNode& node) {
- for (const auto* n = &node; n != &unaliased_ancestor;
+static bool HasCompositedTransformToAncestor(
+ const TransformPaintPropertyNode& node,
+ const TransformPaintPropertyNode& unaliased_ancestor) {
+ for (const auto* n = &node.Unalias(); n != &unaliased_ancestor;
n = SafeUnalias(n->Parent())) {
- if (!n || n->HasDirectCompositingReasons())
- return false;
+ if (n->HasDirectCompositingReasons())
+ return true;
}
- return true;
+ return false;
+}
+
+// Returns the lowest common ancestor if there is no composited transform
+// between the two transforms.
+static const TransformPaintPropertyNode* NonCompositedLowestCommonAncestor(
+ const TransformPaintPropertyNode& transform1,
+ const TransformPaintPropertyNode& transform2) {
+ const auto& lca = LowestCommonAncestor(transform1, transform2).Unalias();
+ if (HasCompositedTransformToAncestor(transform1, lca) ||
+ HasCompositedTransformToAncestor(transform2, lca))
+ return nullptr;
+ return &lca;
+}
+
+static bool ClipChainHasCompositedTransformTo(
+ const ClipPaintPropertyNode& node,
+ const ClipPaintPropertyNode& unaliased_ancestor,
+ const TransformPaintPropertyNode& transform) {
+ for (const auto* n = &node.Unalias(); n != &unaliased_ancestor;
+ n = SafeUnalias(n->Parent())) {
+ if (!NonCompositedLowestCommonAncestor(n->LocalTransformSpace(), transform))
+ return true;
+ }
+ return false;
}
// Determines whether drawings based on the 'guest' state can be painted into
-// a layer with the 'home' state. A number of criteria need to be met:
+// a layer with the 'home' state, and if yes, returns the common ancestor state
+// to which both layer will be upcasted.
+// A number of criteria need to be met:
// 1. The guest effect must be a descendant of the home effect. However this
// check is enforced by the layerization recursion. Here we assume the
// guest has already been upcasted to the same effect.
// 2. The guest transform and the home transform have compatible backface
// visibility.
-// 3. The guest clip must be a descendant of the home clip.
+// 3. The guest transform space must be within compositing boundary of the home
+// transform space.
// 4. The local space of each clip and effect node on the ancestor chain must
// be within compositing boundary of the home transform space.
-// 5. The guest transform space must be within compositing boundary of the
-// home
-// transform space.
-static bool CanUpcastTo(const PropertyTreeState& guest,
- const PropertyTreeState& home) {
+base::Optional<PropertyTreeState> CanUpcastWith(const PropertyTreeState& guest,
+ const PropertyTreeState& home) {
DCHECK_EQ(&home.Effect().Unalias(), &guest.Effect().Unalias());
if (home.Transform().IsBackfaceHidden() !=
guest.Transform().IsBackfaceHidden())
+ return base::nullopt;
+
+ auto* upcast_transform =
+ NonCompositedLowestCommonAncestor(home.Transform(), guest.Transform());
+ if (!upcast_transform)
+ return base::nullopt;
+
+ const auto& clip_lca =
+ LowestCommonAncestor(home.Clip(), guest.Clip()).Unalias();
+ if (ClipChainHasCompositedTransformTo(home.Clip(), clip_lca,
+ *upcast_transform) ||
+ ClipChainHasCompositedTransformTo(guest.Clip(), clip_lca,
+ *upcast_transform))
+ return base::nullopt;
+
+ return PropertyTreeState(*upcast_transform, clip_lca, home.Effect());
+}
+
+// We will only allow merging if the merged-area:home-area+guest-area doesn't
+// exceed the ratio |kMergingSparsityTolerance|:1.
+static constexpr float kMergeSparsityTolerance = 6;
+
+bool PaintArtifactCompositor::PendingLayer::CanMerge(
+ const PendingLayer& guest,
+ const PropertyTreeState& guest_state,
+ PropertyTreeState* out_merged_state,
+ FloatRect* out_merged_bounds) const {
+ if (compositing_type == kRequiresOwnLayer ||
+ guest.compositing_type == kRequiresOwnLayer) {
return false;
+ }
+ if (&property_tree_state.Effect().Unalias() !=
+ &guest_state.Effect().Unalias()) {
+ return false;
+ }
- const auto& home_clip = home.Clip().Unalias();
- for (const auto* current_clip = &guest.Clip().Unalias();
- current_clip != &home_clip;
- current_clip = SafeUnalias(current_clip->Parent())) {
- // If we had direct compositing reasons on a clip node, we would want to
- // return false here.
- if (!current_clip)
- return false;
- if (!IsNonCompositingAncestorOf(
- home.Transform().Unalias(),
- current_clip->LocalTransformSpace().Unalias())) {
+ const base::Optional<PropertyTreeState>& merged_state =
+ CanUpcastWith(guest_state, property_tree_state);
+ if (!merged_state)
+ return false;
+
+ FloatClipRect new_home_bounds(bounds);
+ GeometryMapper::LocalToAncestorVisualRect(property_tree_state, *merged_state,
+ new_home_bounds);
+ FloatClipRect new_guest_bounds(guest.bounds);
+ GeometryMapper::LocalToAncestorVisualRect(guest_state, *merged_state,
+ new_guest_bounds);
+
+ FloatRect merged_bounds =
+ UnionRect(new_home_bounds.Rect(), new_guest_bounds.Rect());
+ // Don't check for sparcity if we may further decomposite the effect, so that
+ // the merged layer may be merged to other layers with the decomposited
+ // effect, which is often better than not merging even if the merged layer is
+ // sparse because we may create less composited effects and render surfaces.
+ if (guest_state.Effect().IsRoot() ||
+ guest_state.Effect().HasDirectCompositingReasons()) {
+ float sum_area = new_home_bounds.Rect().Size().Area() +
+ new_guest_bounds.Rect().Size().Area();
+ if (merged_bounds.Size().Area() > kMergeSparsityTolerance * sum_area)
return false;
- }
}
- return IsNonCompositingAncestorOf(home.Transform().Unalias(),
- guest.Transform().Unalias());
+ if (out_merged_state)
+ *out_merged_state = *merged_state;
+ if (out_merged_bounds)
+ *out_merged_bounds = merged_bounds;
+ return true;
}
// Returns nullptr if 'ancestor' is not a strict ancestor of 'node'.
@@ -559,21 +710,15 @@ static const EffectPaintPropertyNode* StrictUnaliasedChildOfAlongPath(
bool PaintArtifactCompositor::MightOverlap(const PendingLayer& layer_a,
const PendingLayer& layer_b) {
- FloatClipRect bounds_a(layer_a.bounds);
- GeometryMapper::LocalToAncestorVisualRect(
- layer_a.property_tree_state, PropertyTreeState::Root(), bounds_a);
- FloatClipRect bounds_b(layer_b.bounds);
- GeometryMapper::LocalToAncestorVisualRect(
- layer_b.property_tree_state, PropertyTreeState::Root(), bounds_b);
-
- return bounds_a.Rect().Intersects(bounds_b.Rect());
+ return layer_a.VisualRectForOverlapTesting().Intersects(
+ layer_b.VisualRectForOverlapTesting());
}
bool PaintArtifactCompositor::DecompositeEffect(
const EffectPaintPropertyNode& unaliased_parent_effect,
- size_t first_layer_in_parent_group_index,
+ wtf_size_t first_layer_in_parent_group_index,
const EffectPaintPropertyNode& unaliased_effect,
- size_t layer_index) {
+ wtf_size_t layer_index) {
// The layer must be the last layer in pending_layers_.
DCHECK_EQ(layer_index, pending_layers_.size() - 1);
@@ -593,24 +738,29 @@ bool PaintArtifactCompositor::DecompositeEffect(
? *unaliased_effect.OutputClip()
: layer.property_tree_state.Clip(),
unaliased_effect);
- if (!CanUpcastTo(layer.property_tree_state, group_state))
+ base::Optional<PropertyTreeState> upcast_state =
+ CanUpcastWith(layer.property_tree_state, group_state);
+ if (!upcast_state)
return false;
- PropertyTreeState upcast_state = group_state;
- upcast_state.SetEffect(unaliased_parent_effect);
+ upcast_state->SetEffect(unaliased_parent_effect);
// Exotic blending layer can be decomposited only if its parent group
- // (which defines the scope of the blending) has only one layer before it,
+ // (which defines the scope of the blending) has zero or one layer before it,
// and it can be merged into that layer.
if (unaliased_effect.BlendMode() != SkBlendMode::kSrcOver) {
- if (layer_index - 1 != first_layer_in_parent_group_index)
- return false;
- if (!pending_layers_[first_layer_in_parent_group_index].CanMerge(
- layer, upcast_state))
- return false;
+ auto num_previous_siblings =
+ layer_index - first_layer_in_parent_group_index;
+ if (num_previous_siblings) {
+ if (num_previous_siblings > 1)
+ return false;
+ if (!pending_layers_[first_layer_in_parent_group_index].CanMerge(
+ layer, *upcast_state))
+ return false;
+ }
}
- layer.Upcast(upcast_state);
+ layer.Upcast(*upcast_state);
return true;
}
@@ -657,13 +807,12 @@ static bool SkipGroupIfEffectivelyInvisible(
return true;
}
-static bool IsCompositedScrollHitTest(const DisplayItem& item) {
- if (!item.IsScrollHitTest())
+static bool IsCompositedScrollHitTest(const PaintChunk& chunk) {
+ if (!chunk.hit_test_data)
return false;
- const auto* scroll_offset_node =
- static_cast<const ScrollHitTestDisplayItem&>(item).scroll_offset_node();
- return scroll_offset_node &&
- scroll_offset_node->HasDirectCompositingReasons();
+ const auto* scroll_translation = chunk.hit_test_data->scroll_translation;
+ return scroll_translation &&
+ scroll_translation->HasDirectCompositingReasons();
}
static bool IsCompositedScrollbar(const DisplayItem& item) {
@@ -697,10 +846,10 @@ void PaintArtifactCompositor::LayerizeGroup(
// Every paint chunk will be visited by the main loop below for exactly
// once, except for chunks that enter or exit groups (case B & C below). For
// normal chunk visit (case A), the only cost is determining squash, which
- // costs O(qd), where d came from "canUpcastTo" and geometry mapping.
+ // costs O(qd), where d came from |CanUpcastWith| and geometry mapping.
// Subtotal: O(pqd)
// For group entering and exiting, it could cost O(d) for each group, for
- // searching the shallowest subgroup (strictChildOfAlongPath), thus O(d^2)
+ // searching the shallowest subgroup (StrictChildOfAlongPath), thus O(d^2)
// in total.
// Also when exiting group, the group may be decomposited and squashed to a
// previous layer. Again finding the host costs O(qd). Merging would cost
@@ -714,12 +863,17 @@ void PaintArtifactCompositor::LayerizeGroup(
const auto& chunk_effect = chunk_it->properties.Effect().Unalias();
if (&chunk_effect == &unaliased_group) {
// Case A: The next chunk belongs to the current group but no subgroup.
- const auto& first_display_item =
- paint_artifact.GetDisplayItemList()[chunk_it->begin_index];
- bool requires_own_layer = first_display_item.IsForeignLayer() ||
- IsCompositedScrollHitTest(first_display_item) ||
- IsCompositedScrollbar(first_display_item);
- DCHECK(!requires_own_layer || chunk_it->size() == 1u);
+ bool requires_own_layer = false;
+ if (IsCompositedScrollHitTest(*chunk_it)) {
+ requires_own_layer = true;
+ } else if (chunk_it->size()) {
+ const auto& first_display_item =
+ paint_artifact.GetDisplayItemList()[chunk_it->begin_index];
+ requires_own_layer = first_display_item.IsForeignLayer() ||
+ first_display_item.IsGraphicsLayerWrapper() ||
+ IsCompositedScrollbar(first_display_item);
+ }
+ DCHECK(!requires_own_layer || chunk_it->size() <= 1u);
pending_layers_.emplace_back(
*chunk_it, chunk_it - paint_artifact.PaintChunks().begin(),
@@ -761,8 +915,7 @@ void PaintArtifactCompositor::LayerizeGroup(
for (wtf_size_t candidate_index = pending_layers_.size() - 1;
candidate_index-- > first_layer_in_current_group;) {
PendingLayer& candidate_layer = pending_layers_[candidate_index];
- if (candidate_layer.CanMerge(new_layer, new_layer.property_tree_state)) {
- candidate_layer.Merge(new_layer);
+ if (candidate_layer.Merge(new_layer)) {
pending_layers_.pop_back();
break;
}
@@ -788,8 +941,8 @@ void PaintArtifactCompositor::CollectPendingLayers(
}
void SynthesizedClip::UpdateLayer(bool needs_layer,
- const FloatRoundedRect& rrect,
- scoped_refptr<const RefCountedPath> path) {
+ const ClipPaintPropertyNode& clip,
+ const TransformPaintPropertyNode& transform) {
if (!needs_layer) {
layer_.reset();
return;
@@ -799,33 +952,40 @@ void SynthesizedClip::UpdateLayer(bool needs_layer,
layer_->SetIsDrawable(true);
}
- IntRect layer_bounds = EnclosingIntRect(rrect.Rect());
- gfx::Vector2dF new_layer_origin(layer_bounds.X(), layer_bounds.Y());
-
- SkRRect new_local_rrect = rrect;
- new_local_rrect.offset(-new_layer_origin.x(), -new_layer_origin.y());
-
- bool path_in_layer_changed = false;
- if (path_ == path) {
- path_in_layer_changed = path && layer_origin_ != new_layer_origin;
- } else if (!path_ || !path) {
- path_in_layer_changed = true;
+ const RefCountedPath* path = clip.ClipPath();
+ SkRRect new_rrect = clip.PixelSnappedClipRect();
+ IntRect layer_bounds = EnclosingIntRect(clip.PixelSnappedClipRect().Rect());
+ bool needs_display = false;
+
+ auto new_translation_2d_or_matrix =
+ GeometryMapper::SourceToDestinationProjection(clip.LocalTransformSpace(),
+ transform);
+ new_translation_2d_or_matrix.MapRect(layer_bounds);
+ new_translation_2d_or_matrix.PostTranslate(-layer_bounds.X(),
+ -layer_bounds.Y());
+
+ if (!path && new_translation_2d_or_matrix.IsIdentityOr2DTranslation()) {
+ const auto& translation = new_translation_2d_or_matrix.Translation2D();
+ new_rrect.offset(translation.Width(), translation.Height());
+ needs_display = !rrect_is_local_ || new_rrect != rrect_;
+ translation_2d_or_matrix_ = GeometryMapper::Translation2DOrMatrix();
+ rrect_is_local_ = true;
} else {
- SkPath new_path = path->GetSkPath();
- new_path.offset(layer_origin_.x() - new_layer_origin.x(),
- layer_origin_.y() - new_layer_origin.y());
- path_in_layer_changed = path_->GetSkPath() != new_path;
+ needs_display = rrect_is_local_ || new_rrect != rrect_ ||
+ new_translation_2d_or_matrix != translation_2d_or_matrix_ ||
+ (path_ != path && (!path_ || !path || *path_ != *path));
+ translation_2d_or_matrix_ = new_translation_2d_or_matrix;
+ rrect_is_local_ = false;
}
- if (local_rrect_ != new_local_rrect || path_in_layer_changed) {
+ if (needs_display)
layer_->SetNeedsDisplay();
- }
- layer_->SetOffsetToTransformParent(new_layer_origin);
- layer_->SetBounds(gfx::Size(layer_bounds.Width(), layer_bounds.Height()));
- layer_origin_ = new_layer_origin;
- local_rrect_ = new_local_rrect;
- path_ = std::move(path);
+ layer_->SetOffsetToTransformParent(
+ gfx::Vector2dF(layer_bounds.X(), layer_bounds.Y()));
+ layer_->SetBounds(gfx::Size(layer_bounds.Size()));
+ rrect_ = new_rrect;
+ path_ = path;
}
scoped_refptr<cc::DisplayItemList> SynthesizedClip::PaintContentsToDisplayList(
@@ -835,16 +995,22 @@ scoped_refptr<cc::DisplayItemList> SynthesizedClip::PaintContentsToDisplayList(
PaintFlags flags;
flags.setAntiAlias(true);
cc_list->StartPaint();
- if (!path_) {
- cc_list->push<cc::DrawRRectOp>(local_rrect_, flags);
+ if (rrect_is_local_) {
+ cc_list->push<cc::DrawRRectOp>(rrect_, flags);
} else {
cc_list->push<cc::SaveOp>();
- cc_list->push<cc::TranslateOp>(-layer_origin_.x(), -layer_origin_.y());
- cc_list->push<cc::ClipPathOp>(path_->GetSkPath(), SkClipOp::kIntersect,
- true);
- SkRRect rrect = local_rrect_;
- rrect.offset(layer_origin_.x(), layer_origin_.y());
- cc_list->push<cc::DrawRRectOp>(rrect, flags);
+ if (translation_2d_or_matrix_.IsIdentityOr2DTranslation()) {
+ const auto& translation = translation_2d_or_matrix_.Translation2D();
+ cc_list->push<cc::TranslateOp>(translation.Width(), translation.Height());
+ } else {
+ cc_list->push<cc::ConcatOp>(SkMatrix(TransformationMatrix::ToSkMatrix44(
+ translation_2d_or_matrix_.Matrix())));
+ }
+ if (path_) {
+ cc_list->push<cc::ClipPathOp>(path_->GetSkPath(), SkClipOp::kIntersect,
+ true);
+ }
+ cc_list->push<cc::DrawRRectOp>(rrect_, flags);
cc_list->push<cc::RestoreOp>();
}
cc_list->EndPaintOfUnpaired(gfx::Rect(layer_->bounds()));
@@ -853,26 +1019,26 @@ scoped_refptr<cc::DisplayItemList> SynthesizedClip::PaintContentsToDisplayList(
}
SynthesizedClip& PaintArtifactCompositor::CreateOrReuseSynthesizedClipLayer(
- const ClipPaintPropertyNode& node,
+ const ClipPaintPropertyNode& clip,
+ const TransformPaintPropertyNode& transform,
bool needs_layer,
CompositorElementId& mask_isolation_id,
CompositorElementId& mask_effect_id) {
auto* entry =
std::find_if(synthesized_clip_cache_.begin(),
- synthesized_clip_cache_.end(), [&node](const auto& entry) {
- return entry.key == &node && !entry.in_use;
+ synthesized_clip_cache_.end(), [&clip](const auto& entry) {
+ return entry.key == &clip && !entry.in_use;
});
if (entry == synthesized_clip_cache_.end()) {
- auto clip = std::make_unique<SynthesizedClip>();
- synthesized_clip_cache_.push_back(
- SynthesizedClipEntry{&node, std::move(clip), false});
+ synthesized_clip_cache_.push_back(SynthesizedClipEntry{
+ &clip, std::make_unique<SynthesizedClip>(), false});
entry = synthesized_clip_cache_.end() - 1;
}
entry->in_use = true;
SynthesizedClip& synthesized_clip = *entry->synthesized_clip;
if (needs_layer) {
- synthesized_clip.UpdateLayer(needs_layer, node.ClipRect(), node.ClipPath());
+ synthesized_clip.UpdateLayer(needs_layer, clip, transform);
synthesized_clip.Layer()->SetLayerTreeHost(root_layer_->layer_tree_host());
}
mask_isolation_id = synthesized_clip.GetMaskIsolationId();
@@ -903,14 +1069,14 @@ static void UpdateCompositorViewportProperties(
*properties.page_scale);
}
if (properties.inner_scroll_translation) {
- ids.inner_scroll = property_tree_manager.EnsureCompositorScrollNode(
+ ids.inner_scroll = property_tree_manager.EnsureCompositorInnerScrollNode(
*properties.inner_scroll_translation);
if (properties.outer_clip) {
ids.outer_clip = property_tree_manager.EnsureCompositorClipNode(
*properties.outer_clip);
}
if (properties.outer_scroll_translation) {
- ids.outer_scroll = property_tree_manager.EnsureCompositorScrollNode(
+ ids.outer_scroll = property_tree_manager.EnsureCompositorOuterScrollNode(
*properties.outer_scroll_translation);
}
}
@@ -995,11 +1161,9 @@ void PaintArtifactCompositor::DecompositeTransforms(
// The scroll translation node of a scroll hit test layer may not be
// referenced by any pending layer's property tree state. Disallow
// decomposition of it (and its ancestors).
- if (const auto* scroll_hit_test =
- ScrollHitTestForLayer(paint_artifact, pending_layer)) {
- if (const auto* scroll_offset = scroll_hit_test->scroll_offset)
- mark_not_decompositable(scroll_offset);
- }
+ if (const auto* scroll_translation =
+ ScrollTranslationForLayer(paint_artifact, pending_layer))
+ mark_not_decompositable(scroll_translation);
}
}
@@ -1053,7 +1217,6 @@ void PaintArtifactCompositor::Update(
Vector<std::unique_ptr<ContentLayerClientImpl>> new_content_layer_clients;
new_content_layer_clients.ReserveCapacity(pending_layers_.size());
Vector<scoped_refptr<cc::Layer>> new_scroll_hit_test_layers;
- Vector<scoped_refptr<cc::Layer>> new_scrollbar_layers;
// Maps from cc effect id to blink effects. Containing only the effects
// having composited layers.
@@ -1074,7 +1237,7 @@ void PaintArtifactCompositor::Update(
if (&clip.LocalTransformSpace() == &transform) {
// Limit layer bounds to hide the areas that will be never visible
// because of the clip.
- pending_layer.bounds.Intersect(clip.ClipRect().Rect());
+ pending_layer.bounds.Intersect(clip.PixelSnappedClipRect().Rect());
} else if (const auto* scroll = transform.ScrollNode()) {
// Limit layer bounds to the scroll range to hide the areas that will
// never be scrolled into the visible area.
@@ -1084,7 +1247,7 @@ void PaintArtifactCompositor::Update(
scoped_refptr<cc::Layer> layer = CompositedLayerForPendingLayer(
paint_artifact, pending_layer, new_content_layer_clients,
- new_scroll_hit_test_layers, new_scrollbar_layers);
+ new_scroll_hit_test_layers);
// In Pre-CompositeAfterPaint, touch action rects and non-fast scrollable
// regions are updated through ScrollingCoordinator.
@@ -1093,9 +1256,9 @@ void PaintArtifactCompositor::Update(
pending_layer.paint_chunk_indices);
UpdateTouchActionRects(layer.get(), layer->offset_to_transform_parent(),
property_state, paint_chunks);
- UpdateNonFastScrollableRegions(layer.get(),
- layer->offset_to_transform_parent(),
- property_state, paint_chunks);
+ UpdateNonFastScrollableRegions(
+ layer.get(), layer->offset_to_transform_parent(), property_state,
+ paint_chunks, &property_tree_manager);
}
layer->SetLayerTreeHost(root_layer_->layer_tree_host());
@@ -1110,7 +1273,7 @@ void PaintArtifactCompositor::Update(
// The compositor scroll node is not directly stored in the property tree
// state but can be created via the scroll offset translation node.
const auto& scroll_translation =
- ScrollOffsetTranslationForLayer(*paint_artifact, pending_layer);
+ NearestScrollTranslationForLayer(*paint_artifact, pending_layer);
int scroll_id =
property_tree_manager.EnsureCompositorScrollNode(scroll_translation);
@@ -1125,6 +1288,9 @@ void PaintArtifactCompositor::Update(
bool backface_hidden = property_state.Transform().IsBackfaceHidden();
layer->SetDoubleSided(!backface_hidden);
layer->SetShouldCheckBackfaceVisibility(backface_hidden);
+ bool has_will_change_transform =
+ property_state.Transform().RequiresCompositingForWillChangeTransform();
+ layer->SetHasWillChangeTransformHint(has_will_change_transform);
// If the property tree state has changed between the layer and the root,
// we need to inform the compositor so damage can be calculated. Calling
@@ -1164,7 +1330,6 @@ void PaintArtifactCompositor::Update(
property_tree_manager.Finalize();
content_layer_clients_.swap(new_content_layer_clients);
scroll_hit_test_layers_.swap(new_scroll_hit_test_layers);
- scrollbar_layers_.swap(new_scrollbar_layers);
auto pos = std::remove_if(synthesized_clip_cache_.begin(),
synthesized_clip_cache_.end(),
@@ -1207,20 +1372,14 @@ void PaintArtifactCompositor::Update(
#endif
}
-cc::PropertyTrees* PaintArtifactCompositor::GetPropertyTreesForDirectUpdate() {
+bool PaintArtifactCompositor::CanDirectlyUpdateProperties() const {
// Don't try to retrieve property trees if we need an update. The full
// update will update all of the nodes, so a direct update doesn't need to
// do anything.
if (needs_update_)
- return nullptr;
-
- if (!root_layer_)
- return nullptr;
+ return false;
- auto* host = root_layer_->layer_tree_host();
- if (!host)
- return nullptr;
- return host->property_trees();
+ return root_layer_ && root_layer_->layer_tree_host();
}
bool PaintArtifactCompositor::DirectlyUpdateCompositedOpacityValue(
@@ -1228,9 +1387,9 @@ bool PaintArtifactCompositor::DirectlyUpdateCompositedOpacityValue(
// We can only directly-update compositor values if all content associated
// with the node is known to be composited.
DCHECK(effect.HasDirectCompositingReasons());
- if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
+ if (CanDirectlyUpdateProperties()) {
return PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
- property_trees, *root_layer_->layer_tree_host(), effect);
+ *root_layer_->layer_tree_host(), effect);
}
return false;
}
@@ -1243,9 +1402,9 @@ bool PaintArtifactCompositor::DirectlyUpdateScrollOffsetTransform(
// CompositeAfterPaint because we cannot query CompositedLayerMapping here.
DCHECK(transform.HasDirectCompositingReasons());
}
- if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
+ if (CanDirectlyUpdateProperties()) {
return PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
- property_trees, *root_layer_->layer_tree_host(), transform);
+ *root_layer_->layer_tree_host(), transform);
}
return false;
}
@@ -1255,9 +1414,9 @@ bool PaintArtifactCompositor::DirectlyUpdateTransform(
// We can only directly-update compositor values if all content associated
// with the node is known to be composited.
DCHECK(transform.HasDirectCompositingReasons());
- if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
+ if (CanDirectlyUpdateProperties()) {
return PropertyTreeManager::DirectlyUpdateTransform(
- property_trees, *root_layer_->layer_tree_host(), transform);
+ *root_layer_->layer_tree_host(), transform);
}
return false;
}
@@ -1267,13 +1426,27 @@ bool PaintArtifactCompositor::DirectlyUpdatePageScaleTransform(
// We can only directly-update compositor values if all content associated
// with the node is known to be composited.
DCHECK(transform.HasDirectCompositingReasons());
- if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
+ if (CanDirectlyUpdateProperties()) {
return PropertyTreeManager::DirectlyUpdatePageScaleTransform(
- property_trees, *root_layer_->layer_tree_host(), transform);
+ *root_layer_->layer_tree_host(), transform);
}
return false;
}
+bool PaintArtifactCompositor::DirectlySetScrollOffset(
+ CompositorElementId element_id,
+ const FloatPoint& scroll_offset) {
+ if (!root_layer_ || !root_layer_->layer_tree_host())
+ return false;
+ auto* property_trees = root_layer_->layer_tree_host()->property_trees();
+ if (!property_trees->element_id_to_scroll_node_index.contains(element_id))
+ return false;
+ PropertyTreeManager::DirectlySetScrollOffset(
+ *root_layer_->layer_tree_host(), element_id,
+ gfx::ScrollOffset(scroll_offset));
+ return true;
+}
+
static cc::RenderSurfaceReason GetRenderSurfaceCandidateReason(
const cc::EffectNode& effect,
const Vector<const EffectPaintPropertyNode*>& blink_effects) {
@@ -1283,7 +1456,7 @@ static cc::RenderSurfaceReason GetRenderSurfaceCandidateReason(
return cc::RenderSurfaceReason::kBlendModeDstIn;
if (effect.opacity != 1.f)
return cc::RenderSurfaceReason::kOpacity;
- if (static_cast<size_t>(effect.id) < blink_effects.size() &&
+ if (static_cast<wtf_size_t>(effect.id) < blink_effects.size() &&
blink_effects[effect.id] &&
blink_effects[effect.id]->HasActiveOpacityAnimation())
return cc::RenderSurfaceReason::kOpacityAnimation;
@@ -1379,6 +1552,8 @@ void PaintArtifactCompositor::UpdateLayerDebugInfo(
debug_info.compositing_reasons =
CompositingReason::Descriptions(compositing_reasons);
+ debug_info.compositing_reason_ids =
+ CompositingReason::ShortNames(compositing_reasons);
debug_info.owner_node_id = id.client.OwnerNodeId();
if (RasterInvalidationTracking::IsTracingRasterInvalidations() &&
@@ -1398,9 +1573,11 @@ CompositingReasons PaintArtifactCompositor::GetCompositingReasons(
return CompositingReason::kOverlap;
if (layer.compositing_type == PendingLayer::kRequiresOwnLayer) {
+ const auto& first_chunk = layer.FirstPaintChunk(paint_artifact);
+ if (IsCompositedScrollHitTest(first_chunk))
+ return CompositingReason::kOverflowScrolling;
const auto& display_item =
- paint_artifact.GetDisplayItemList()
- [layer.FirstPaintChunk(paint_artifact).begin_index];
+ paint_artifact.GetDisplayItemList()[first_chunk.begin_index];
switch (display_item.GetType()) {
case DisplayItem::kForeignLayerCanvas:
return CompositingReason::kCanvas;
@@ -1408,8 +1585,6 @@ CompositingReasons PaintArtifactCompositor::GetCompositingReasons(
return CompositingReason::kPlugin;
case DisplayItem::kForeignLayerVideo:
return CompositingReason::kVideo;
- case DisplayItem::kScrollHitTest:
- return CompositingReason::kOverflowScrolling;
case DisplayItem::kScrollbarHorizontal:
return CompositingReason::kLayerForHorizontalScrollbar;
case DisplayItem::kScrollbarVertical:
@@ -1442,7 +1617,11 @@ Vector<cc::Layer*> PaintArtifactCompositor::SynthesizedClipLayersForTesting()
}
void LayerListBuilder::Add(scoped_refptr<cc::Layer> layer) {
+#if DCHECK_IS_ON()
DCHECK(list_valid_);
+ DCHECK(!layer_ids_.Contains(layer->id()));
+ layer_ids_.insert(layer->id());
+#endif
list_.push_back(layer);
}
@@ -1455,7 +1634,7 @@ cc::LayerList LayerListBuilder::Finalize() {
#if DCHECK_IS_ON()
void PaintArtifactCompositor::ShowDebugData() {
LOG(ERROR) << GetLayersAsJSON(kLayerTreeIncludesDebugInfo |
- kLayerTreeIncludesPaintInvalidations)
+ kLayerTreeIncludesDetailedInvalidations)
->ToPrettyJSONString()
.Utf8();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
index 25abeddc235..766de18b6ae 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -18,10 +18,19 @@
#include "third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h"
#include "third_party/blink/renderer/platform/graphics/compositing_reasons.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+#if DCHECK_IS_ON()
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#endif
+
+namespace cc {
+class ScrollbarLayerBase;
+}
+
namespace gfx {
class Vector2dF;
}
@@ -31,6 +40,7 @@ namespace blink {
class ContentLayerClientImpl;
class JSONObject;
class PaintArtifact;
+class PropertyTreeManager;
class SynthesizedClip;
struct PaintChunk;
@@ -45,6 +55,9 @@ class LayerListBuilder {
// The list becomes invalid once |Finalize| is called.
bool list_valid_ = true;
cc::LayerList list_;
+#if DCHECK_IS_ON()
+ HashSet<int> layer_ids_;
+#endif
};
// This class maintains unique stable cc effect IDs (and optionally a persistent
@@ -73,10 +86,10 @@ class SynthesizedClip : private cc::ContentLayerClient {
}
void UpdateLayer(bool needs_layer,
- const FloatRoundedRect& rrect,
- scoped_refptr<const RefCountedPath> path);
+ const ClipPaintPropertyNode&,
+ const TransformPaintPropertyNode&);
- cc::Layer* Layer() { return layer_.get(); }
+ cc::PictureLayer* Layer() { return layer_.get(); }
CompositorElementId GetMaskIsolationId() const { return mask_isolation_id_; }
CompositorElementId GetMaskEffectId() const { return mask_effect_id_; }
@@ -91,8 +104,9 @@ class SynthesizedClip : private cc::ContentLayerClient {
private:
scoped_refptr<cc::PictureLayer> layer_;
- gfx::Vector2dF layer_origin_;
- SkRRect local_rrect_ = SkRRect::MakeEmpty();
+ GeometryMapper::Translation2DOrMatrix translation_2d_or_matrix_;
+ bool rrect_is_local_ = false;
+ SkRRect rrect_;
scoped_refptr<const RefCountedPath> path_;
CompositorElementId mask_isolation_id_;
CompositorElementId mask_effect_id_;
@@ -139,6 +153,12 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
bool DirectlyUpdateTransform(const TransformPaintPropertyNode&);
bool DirectlyUpdatePageScaleTransform(const TransformPaintPropertyNode&);
+ // Directly sets cc::ScrollTree::current_scroll_offset. This doesn't affect
+ // cc::TransformNode::scroll_offset (which will be synched with blink
+ // transform node in DirectlyUpdateScrollOffsetTransform() or Update()).
+ bool DirectlySetScrollOffset(CompositorElementId,
+ const FloatPoint& scroll_offset);
+
// The root layer of the tree managed by this object.
cc::Layer* RootLayer() const { return root_layer_.get(); }
@@ -148,6 +168,9 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// going to be removed from its frame.
void WillBeRemovedFromFrame();
+ std::unique_ptr<JSONArray> GetPendingLayersAsJSON(
+ const PaintArtifact* = nullptr) const;
+
std::unique_ptr<JSONObject> GetLayersAsJSON(
LayerTreeFlags,
const PaintArtifact* = nullptr) const;
@@ -174,7 +197,8 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
cc::Layer*,
const gfx::Vector2dF& layer_offset,
const PropertyTreeState& layer_state,
- const PaintChunkSubset& paint_chunks);
+ const PaintChunkSubset& paint_chunks,
+ PropertyTreeManager* = nullptr);
void SetNeedsUpdate() { needs_update_ = true; }
bool NeedsUpdate() const { return needs_update_; }
@@ -202,15 +226,23 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
PendingLayer(const PaintChunk& first_paint_chunk,
wtf_size_t first_chunk_index,
bool requires_own_layer);
- // Merge another pending layer after this one, appending all its paint
- // chunks after chunks in this layer, with appropriate space conversion
- // applied. The merged layer must have a property tree state that's deeper
- // than this layer, i.e. can "upcast" to this layer's state.
- void Merge(const PendingLayer& guest);
+
+ // Merges |guest| into |this| if it can, by appending chunks of |guest|
+ // after chunks of |this|, with appropriate space conversion applied to
+ // both layers from their original property tree states to |merged_state|.
+ // Returns whether the merge is successful.
+ bool Merge(const PendingLayer& guest);
+
+ // Returns true if |guest| can be merged into |this|, and sets the output
+ // paramsters with the property tree state and bounds of the merged layer.
// |guest_state| is for cases that we want to check if we can merge |guest|
- // if it has |guest_state| (which may be different from its current state).
+ // if it has |guest_state| in the future (which may be different from its
+ // current state).
bool CanMerge(const PendingLayer& guest,
- const PropertyTreeState& guest_state) const;
+ const PropertyTreeState& guest_state,
+ PropertyTreeState* merged_state = nullptr,
+ FloatRect* merged_bounds = nullptr) const;
+
// Mutate this layer's property tree state to a more general (shallower)
// state, thus the name "upcast". The concrete effect of this is to
// "decomposite" some of the properties, so that fewer properties will be
@@ -220,6 +252,15 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
const PaintChunk& FirstPaintChunk(const PaintArtifact&) const;
+ // Returns the largest rect known to be opaque given two opaque rects.
+ static FloatRect UniteRectsKnownToBeOpaque(const FloatRect&,
+ const FloatRect&);
+ FloatRect MapRectKnownToBeOpaque(const PropertyTreeState&) const;
+
+ std::unique_ptr<JSONObject> ToJSON(const PaintArtifact* = nullptr) const;
+
+ FloatRect VisualRectForOverlapTesting() const;
+
// The rects are in the space of property_tree_state.
FloatRect bounds;
FloatRect rect_known_to_be_opaque;
@@ -263,9 +304,9 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
Vector<PaintChunk>::const_iterator& chunk_cursor);
static bool MightOverlap(const PendingLayer&, const PendingLayer&);
bool DecompositeEffect(const EffectPaintPropertyNode& unaliased_parent_effect,
- size_t first_layer_in_parent_group_index,
+ wtf_size_t first_layer_in_parent_group_index,
const EffectPaintPropertyNode& unaliased_effect,
- size_t layer_index);
+ wtf_size_t layer_index);
// Builds a leaf layer that represents a single paint chunk.
scoped_refptr<cc::Layer> CompositedLayerForPendingLayer(
@@ -273,19 +314,19 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
const PendingLayer&,
Vector<std::unique_ptr<ContentLayerClientImpl>>&
new_content_layer_clients,
- Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers,
- Vector<scoped_refptr<cc::Layer>>& new_scrollbar_layers);
+ Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers);
bool PropertyTreeStateChanged(const PropertyTreeState&) const;
- const TransformPaintPropertyNode& ScrollOffsetTranslationForLayer(
+ const TransformPaintPropertyNode& NearestScrollTranslationForLayer(
const PaintArtifact&,
const PendingLayer&);
- // If the pending layer is a special scroll hit test layer, return the
- // associated hit test information.
- const HitTestData::ScrollHitTest* ScrollHitTestForLayer(const PaintArtifact&,
- const PendingLayer&);
+ // If the pending layer has scroll hit test data, return the associated
+ // scroll translation node.
+ const TransformPaintPropertyNode* ScrollTranslationForLayer(
+ const PaintArtifact&,
+ const PendingLayer&);
// Finds an existing or creates a new scroll hit test layer for the pending
// layer, returning nullptr if the layer is not a scroll hit test layer.
@@ -295,8 +336,9 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// Finds an existing or creates a new scrollbar layer for the pending layer,
// returning nullptr if the layer is not a scrollbar layer.
- scoped_refptr<cc::Layer> ScrollbarLayerForPendingLayer(const PaintArtifact&,
- const PendingLayer&);
+ scoped_refptr<cc::ScrollbarLayerBase> ScrollbarLayerForPendingLayer(
+ const PaintArtifact&,
+ const PendingLayer&);
// Finds a client among the current vector of clients that matches the paint
// chunk's id, or otherwise allocates a new one.
@@ -309,6 +351,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// However, |mask_isolation_id| is always set.
SynthesizedClip& CreateOrReuseSynthesizedClipLayer(
const ClipPaintPropertyNode&,
+ const TransformPaintPropertyNode&,
bool needs_layer,
CompositorElementId& mask_isolation_id,
CompositorElementId& mask_effect_id) final;
@@ -318,7 +361,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
const cc::LayerList&,
const Vector<const EffectPaintPropertyNode*>&);
- cc::PropertyTrees* GetPropertyTreesForDirectUpdate();
+ bool CanDirectlyUpdateProperties() const;
CompositingReasons GetCompositingReasons(const PendingLayer& layer,
const PendingLayer* previous_layer,
@@ -341,7 +384,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
Vector<SynthesizedClipEntry> synthesized_clip_cache_;
Vector<scoped_refptr<cc::Layer>> scroll_hit_test_layers_;
- Vector<scoped_refptr<cc::Layer>> scrollbar_layers_;
Vector<PendingLayer, 0> pending_layers_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index e5df1538463..34024cdd908 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -52,7 +52,7 @@ PaintChunk DefaultChunk() {
return PaintChunk(0, 1, DefaultId(), PropertyTreeState::Root());
}
-gfx::Transform Translation(SkMScalar x, SkMScalar y) {
+gfx::Transform Translation(SkScalar x, SkScalar y) {
gfx::Transform transform;
transform.Translate(x, y);
return transform;
@@ -122,7 +122,7 @@ class PaintArtifactCompositorTest : public testing::Test,
return *GetPropertyTrees().effect_tree.Node(layer->effect_tree_index());
}
- const cc::LayerTreeHost& GetLayerTreeHost() {
+ cc::LayerTreeHost& GetLayerTreeHost() {
return *layer_tree_->layer_tree_host();
}
@@ -159,12 +159,11 @@ class PaintArtifactCompositorTest : public testing::Test,
cc::Layer* RootLayer() { return paint_artifact_compositor_->RootLayer(); }
- // CompositeAfterPaint creates scroll hit test display items (which create
- // scroll hit test layers in PaintArtifactCompositor) whereas before
- // CompositeAfterPaint, scrollable foreign layers are created in
- // ScrollingCoordinator and passed to PaintArtifactCompositor. This function
- // is used to create a chunk representing the scrollable layer in either of
- // these modes.
+ // CompositeAfterPaint creates scroll hit test data (which create scroll hit
+ // test layers in PaintArtifactCompositor) whereas before CompositeAfterPaint,
+ // scrollable foreign layers are created in ScrollingCoordinator and passed
+ // to PaintArtifactCompositor. This function is used to create a chunk
+ // representing the scrollable layer in either of these modes.
void CreateScrollableChunk(TestPaintArtifact& artifact,
const TransformPaintPropertyNode& scroll_offset,
const ClipPaintPropertyNode& clip,
@@ -174,7 +173,6 @@ class PaintArtifactCompositorTest : public testing::Test,
const auto* scroll_node = scroll_offset.ScrollNode();
scoped_refptr<cc::Layer> layer = cc::Layer::Create();
auto rect = scroll_node->ContainerRect();
- layer->SetScrollable(gfx::Size(rect.Size()));
layer->SetBounds(gfx::Size(rect.Size()));
layer->SetElementId(scroll_node->GetCompositorElementId());
artifact.Chunk(scroll_offset, clip, effect)
@@ -184,8 +182,9 @@ class PaintArtifactCompositorTest : public testing::Test,
// Returns the |num|th scrollable layer. In CompositeAfterPaint, this will be
// a scroll hit test layer, whereas currently this will be a content layer.
cc::Layer* ScrollableLayerAt(size_t num) {
+ const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
for (auto& layer : RootLayer()->children()) {
- if (layer->scrollable()) {
+ if (scroll_tree.FindNodeFromElementId(layer->element_id())) {
if (num == 0)
return layer.get();
num--;
@@ -199,8 +198,9 @@ class PaintArtifactCompositorTest : public testing::Test,
// content layers are scrollable and non-scrollable, so this will return the
// |num|th content layer that is not scrollable.
cc::Layer* NonScrollableLayerAt(size_t num) {
+ const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
for (auto& layer : RootLayer()->children()) {
- if (!layer->scrollable()) {
+ if (!scroll_tree.FindNodeFromElementId(layer->element_id())) {
if (num == 0)
return layer.get();
num--;
@@ -240,7 +240,7 @@ class PaintArtifactCompositorTest : public testing::Test,
}
void AddSimpleRectChunk(TestPaintArtifact& artifact) {
- artifact.Chunk().RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ artifact.Chunk().RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
}
void UpdateWithArtifactWithOpacity(float opacity,
@@ -251,7 +251,7 @@ class PaintArtifactCompositorTest : public testing::Test,
AddSimpleRectChunk(artifact);
auto effect = CreateOpacityEffect(e0(), opacity);
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
if (include_subsequent_chunk)
AddSimpleRectChunk(artifact);
Update(artifact.Build());
@@ -265,6 +265,10 @@ class PaintArtifactCompositorTest : public testing::Test,
MockScrollCallbacks& ScrollCallbacks() { return scroll_callbacks_; }
+ PaintArtifactCompositor& GetPaintArtifactCompositor() {
+ return *paint_artifact_compositor_;
+ }
+
private:
MockScrollCallbacks scroll_callbacks_;
std::unique_ptr<PaintArtifactCompositor> paint_artifact_compositor_;
@@ -274,7 +278,7 @@ class PaintArtifactCompositorTest : public testing::Test,
std::unique_ptr<LayerTreeHostEmbedder> layer_tree_;
};
-INSTANTIATE_LAYER_LIST_TEST_SUITE_P(PaintArtifactCompositorTest);
+INSTANTIATE_PAINT_TEST_SUITE_P(PaintArtifactCompositorTest);
const auto kNotScrollingOnMain =
cc::MainThreadScrollingReason::kNotScrollingOnMain;
@@ -286,7 +290,7 @@ TEST_P(PaintArtifactCompositorTest, EmptyPaintArtifact) {
TEST_P(PaintArtifactCompositorTest, OneChunkWithAnOffset) {
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, -50, 100, 100), Color::kWhite);
+ artifact.Chunk().RectDrawing(IntRect(50, -50, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -307,10 +311,10 @@ TEST_P(PaintArtifactCompositorTest, OneTransform) {
TestPaintArtifact artifact;
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
+ artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -349,10 +353,10 @@ TEST_P(PaintArtifactCompositorTest, OneTransformWithAlias) {
TestPaintArtifact artifact;
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
+ artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -393,9 +397,9 @@ TEST_P(PaintArtifactCompositorTest, TransformCombining) {
TestPaintArtifact artifact;
artifact.Chunk(*transform1, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kWhite);
artifact.Chunk(*transform2, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -441,11 +445,11 @@ TEST_P(PaintArtifactCompositorTest, BackfaceVisibility) {
TestPaintArtifact artifact;
artifact.Chunk(*backface_hidden_transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kWhite);
artifact.Chunk(*backface_inherited_transform, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 100, 100), Color::kBlack);
artifact.Chunk(*backface_visible_transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kDarkGray);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kDarkGray);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -479,7 +483,7 @@ TEST_P(PaintArtifactCompositorTest, FlattensInheritedTransform) {
TestPaintArtifact artifact;
artifact.Chunk(*transform3, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -534,7 +538,7 @@ TEST_P(PaintArtifactCompositorTest, FlattensInheritedTransformWithAlias) {
TestPaintArtifact artifact;
artifact.Chunk(*transform3, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -588,13 +592,13 @@ TEST_P(PaintArtifactCompositorTest, SortingContextID) {
TestPaintArtifact artifact;
artifact.Chunk(*transform1, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kWhite);
artifact.Chunk(*transform2, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kLightGray);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kLightGray);
artifact.Chunk(*transform3, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kDarkGray);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kDarkGray);
artifact.Chunk(*transform4, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 300, 200), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 300, 200), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(4u, LayerCount());
@@ -646,7 +650,7 @@ TEST_P(PaintArtifactCompositorTest, OneClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip, e0())
- .RectDrawing(FloatRect(220, 80, 300, 200), Color::kBlack);
+ .RectDrawing(IntRect(220, 80, 300, 200), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -671,7 +675,7 @@ TEST_P(PaintArtifactCompositorTest, OneClipWithAlias) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip, e0())
- .RectDrawing(FloatRect(220, 80, 300, 200), Color::kBlack);
+ .RectDrawing(IntRect(220, 80, 300, 200), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -705,13 +709,13 @@ TEST_P(PaintArtifactCompositorTest, NestedClips) {
TestPaintArtifact artifact;
artifact.Chunk(*transform1, *clip1, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kWhite);
artifact.Chunk(*transform2, *clip2, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kLightGray);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kLightGray);
artifact.Chunk(*transform1, *clip1, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kDarkGray);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kDarkGray);
artifact.Chunk(*transform2, *clip2, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(4u, LayerCount());
@@ -771,13 +775,13 @@ TEST_P(PaintArtifactCompositorTest, NestedClipsWithAlias) {
TestPaintArtifact artifact;
artifact.Chunk(*transform1, *clip1, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kWhite);
artifact.Chunk(*transform2, *clip2, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kLightGray);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kLightGray);
artifact.Chunk(*transform1, *clip1, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kDarkGray);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kDarkGray);
artifact.Chunk(*transform2, *clip2, e0())
- .RectDrawing(FloatRect(300, 350, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(300, 350, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(4u, LayerCount());
@@ -830,7 +834,7 @@ TEST_P(PaintArtifactCompositorTest, DeeplyNestedClips) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clips.back(), e0())
- .RectDrawing(FloatRect(0, 0, 200, 200), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 200, 200), Color::kWhite);
Update(artifact.Build());
// Check the drawing layer. It's clipped.
@@ -849,20 +853,122 @@ TEST_P(PaintArtifactCompositorTest, DeeplyNestedClips) {
for (auto it = clips.rbegin(); it != clips.rend(); ++it) {
const ClipPaintPropertyNode* paint_clip_node = it->get();
EXPECT_EQ(cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP, clip_node->clip_type);
- EXPECT_EQ(paint_clip_node->ClipRect().Rect(), clip_node->clip);
+ EXPECT_EQ(paint_clip_node->UnsnappedClipRect().Rect(), clip_node->clip);
clip_node = GetPropertyTrees().clip_tree.Node(clip_node->parent_id);
}
}
+TEST_P(PaintArtifactCompositorTest, SiblingClipsWithAlias) {
+ auto real_common_clip =
+ CreateClip(c0(), t0(), FloatRoundedRect(0, 0, 800, 600));
+ auto common_clip = ClipPaintPropertyNode::CreateAlias(*real_common_clip);
+ auto real_clip1 =
+ CreateClip(*common_clip, t0(), FloatRoundedRect(0, 0, 300, 200));
+ auto clip1 = ClipPaintPropertyNode::CreateAlias(*real_clip1);
+ auto real_clip2 =
+ CreateClip(*common_clip, t0(), FloatRoundedRect(400, 0, 400, 600));
+ auto clip2 = ClipPaintPropertyNode::CreateAlias(*real_clip2);
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *clip1, e0())
+ .RectDrawing(IntRect(0, 0, 111, 222), Color::kWhite);
+ artifact.Chunk(t0(), *clip2, e0())
+ .RectDrawing(IntRect(333, 444, 555, 666), Color::kBlack);
+ Update(artifact.Build());
+
+ // The two chunks are merged together.
+ ASSERT_EQ(1u, LayerCount());
+ const cc::Layer* layer = LayerAt(0);
+ EXPECT_THAT(
+ layer->GetPicture(),
+ Pointee(DrawsRectangles(Vector<RectWithColor>{
+ // This is the first RectDrawing with real_clip1 applied.
+ RectWithColor(FloatRect(0, 0, 111, 200), Color::kWhite),
+ // This is the second RectDrawing with real_clip2 applied.
+ RectWithColor(FloatRect(400, 444, 400, 156), Color::kBlack)})));
+ EXPECT_EQ(gfx::Transform(), layer->ScreenSpaceTransform());
+ const cc::ClipNode* clip_node =
+ GetPropertyTrees().clip_tree.Node(layer->clip_tree_index());
+ EXPECT_EQ(cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP, clip_node->clip_type);
+ ASSERT_EQ(gfx::RectF(0, 0, 800, 600), clip_node->clip);
+}
+
+TEST_P(PaintArtifactCompositorTest, SiblingClipsWithCompositedTransform) {
+ auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
+ CompositingReason::kWillChangeTransform);
+ auto t2 = CreateTransform(*t1, TransformationMatrix().Translate(1, 2));
+ auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0, 0, 400, 600));
+ auto c2 = CreateClip(c0(), *t2, FloatRoundedRect(400, 0, 400, 600));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *c1, e0())
+ .RectDrawing(IntRect(0, 0, 640, 480), Color::kWhite);
+ artifact.Chunk(t0(), *c2, e0())
+ .RectDrawing(IntRect(0, 0, 640, 480), Color::kBlack);
+ Update(artifact.Build());
+
+ // We can't merge the two chunks because their clips have unmergeable
+ // transforms.
+ ASSERT_EQ(2u, LayerCount());
+}
+
+TEST_P(PaintArtifactCompositorTest, SiblingTransformsWithAlias) {
+ auto real_common_transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(5, 6));
+ auto common_transform =
+ TransformPaintPropertyNode::CreateAlias(*real_common_transform);
+ auto real_transform1 =
+ CreateTransform(*common_transform, TransformationMatrix().Scale(2));
+ auto transform1 = TransformPaintPropertyNode::CreateAlias(*real_transform1);
+ auto real_transform2 =
+ CreateTransform(*common_transform, TransformationMatrix().Scale(0.5));
+ auto transform2 = TransformPaintPropertyNode::CreateAlias(*real_transform2);
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(*transform1, c0(), e0())
+ .RectDrawing(IntRect(0, 0, 111, 222), Color::kWhite);
+ artifact.Chunk(*transform2, c0(), e0())
+ .RectDrawing(IntRect(0, 0, 333, 444), Color::kBlack);
+ Update(artifact.Build());
+
+ // The two chunks are merged together.
+ ASSERT_EQ(1u, LayerCount());
+ const cc::Layer* layer = LayerAt(0);
+ EXPECT_THAT(layer->GetPicture(),
+ Pointee(DrawsRectangles(Vector<RectWithColor>{
+ RectWithColor(FloatRect(0, 0, 222, 444), Color::kWhite),
+ RectWithColor(FloatRect(0, 0, 166.5, 222), Color::kBlack)})));
+ gfx::Transform expected_transform;
+ expected_transform.Translate(5, 6);
+ EXPECT_EQ(expected_transform, layer->ScreenSpaceTransform());
+}
+
+TEST_P(PaintArtifactCompositorTest, SiblingTransformsWithComposited) {
+ auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
+ CompositingReason::kWillChangeTransform);
+ auto t2 = CreateTransform(*t1, TransformationMatrix().Translate(1, 2));
+ auto t3 = CreateTransform(t0(), TransformationMatrix().Translate(3, 4));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(*t2, c0(), e0())
+ .RectDrawing(IntRect(0, 0, 640, 480), Color::kWhite);
+ artifact.Chunk(*t3, c0(), e0())
+ .RectDrawing(IntRect(0, 0, 640, 480), Color::kBlack);
+ Update(artifact.Build());
+
+ // We can't merge the two chunks because their transforms are not mergeable.
+ ASSERT_EQ(2u, LayerCount());
+}
+
TEST_P(PaintArtifactCompositorTest, ForeignLayerPassesThrough) {
scoped_refptr<cc::Layer> layer = cc::Layer::Create();
layer->SetIsDrawable(true);
layer->SetBounds(gfx::Size(400, 300));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk().ForeignLayer(layer, FloatPoint(50, 60));
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -877,7 +983,7 @@ TEST_P(PaintArtifactCompositorTest, ForeignLayerPassesThrough) {
TEST_P(PaintArtifactCompositorTest, EffectTreeConversionWithAlias) {
Update(TestPaintArtifact()
.Chunk()
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite)
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite)
.Build());
auto root_stable_id = GetPropertyTrees().effect_tree.Node(1)->stable_id;
@@ -892,11 +998,11 @@ TEST_P(PaintArtifactCompositorTest, EffectTreeConversionWithAlias) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *effect2)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
artifact.Chunk(t0(), c0(), *effect1)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
artifact.Chunk(t0(), c0(), *effect3)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -961,6 +1067,7 @@ static scoped_refptr<ScrollPaintPropertyNode> CreateScroll(
static void CheckCcScrollNode(const ScrollPaintPropertyNode& blink_scroll,
const cc::ScrollNode& cc_scroll) {
+ EXPECT_TRUE(cc_scroll.scrollable);
EXPECT_EQ(static_cast<gfx::Size>(blink_scroll.ContainerRect().Size()),
cc_scroll.container_bounds);
EXPECT_EQ(static_cast<gfx::Size>(blink_scroll.ContentsSize()),
@@ -983,7 +1090,7 @@ TEST_P(PaintArtifactCompositorTest, OneScrollNode) {
TestPaintArtifact artifact;
CreateScrollableChunk(artifact, *scroll_translation, c0(), e0());
artifact.Chunk(*scroll_translation, c0(), e0())
- .RectDrawing(FloatRect(-110, 12, 170, 19), Color::kWhite);
+ .RectDrawing(IntRect(-110, 12, 170, 19), Color::kWhite);
// Scroll node ElementIds are referenced by scroll animations.
Update(artifact.Build());
@@ -1017,7 +1124,6 @@ TEST_P(PaintArtifactCompositorTest, OneScrollNode) {
Pointee(DrawsRectangle(FloatRect(0, 0, 57, 19), Color::kWhite)));
auto* scroll_layer = ScrollableLayerAt(0);
- EXPECT_TRUE(scroll_layer->scrollable());
// The scroll layer should be sized to the container bounds.
// TODO(pdr): The container bounds will not include scrollbars but the scroll
// layer should extend below scrollbars.
@@ -1047,9 +1153,9 @@ TEST_P(PaintArtifactCompositorTest, TransformUnderScrollNode) {
TestPaintArtifact artifact;
artifact.Chunk(*scroll_translation, c0(), e0())
- .RectDrawing(FloatRect(-20, 4, 60, 8), Color::kBlack)
+ .RectDrawing(IntRect(-20, 4, 60, 8), Color::kBlack)
.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(1, -30, 5, 70), Color::kWhite);
+ .RectDrawing(IntRect(1, -30, 5, 70), Color::kWhite);
Update(artifact.Build());
const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
@@ -1101,10 +1207,10 @@ TEST_P(PaintArtifactCompositorTest, NestedScrollNodes) {
CreateScrollTranslation(*scroll_translation_a, 37, 41, *scroll_b);
TestPaintArtifact artifact;
artifact.Chunk(*scroll_translation_a, c0(), *effect)
- .RectDrawing(FloatRect(7, 11, 13, 17), Color::kWhite);
+ .RectDrawing(IntRect(7, 11, 13, 17), Color::kWhite);
CreateScrollableChunk(artifact, *scroll_translation_a, c0(), *effect);
artifact.Chunk(*scroll_translation_b, c0(), *effect)
- .RectDrawing(FloatRect(1, 2, 3, 5), Color::kWhite);
+ .RectDrawing(IntRect(1, 2, 3, 5), Color::kWhite);
CreateScrollableChunk(artifact, *scroll_translation_b, c0(), *effect);
Update(artifact.Build());
@@ -1150,10 +1256,10 @@ TEST_P(PaintArtifactCompositorTest, ScrollHitTestLayerOrder) {
TestPaintArtifact artifact;
artifact.Chunk(*scroll_translation, *clip, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
CreateScrollableChunk(artifact, *scroll_translation, *clip, e0());
artifact.Chunk(*transform, *clip, e0())
- .RectDrawing(FloatRect(0, 0, 50, 50), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 50, 50), Color::kBlack);
Update(artifact.Build());
// The first content layer (background) should not have the scrolling element
@@ -1197,7 +1303,7 @@ TEST_P(PaintArtifactCompositorTest, NestedScrollableLayerOrder) {
CreateScrollableChunk(artifact, *scroll_translation_2, *clip_2->Parent(),
e0());
artifact.Chunk(*scroll_translation_2, *clip_2, e0())
- .RectDrawing(FloatRect(0, 0, 50, 50), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 50, 50), Color::kWhite);
Update(artifact.Build());
// Two scroll layers should be created for each scroll translation node.
@@ -1281,8 +1387,8 @@ TEST_P(PaintArtifactCompositorTest, AncestorScrollNodes) {
TEST_P(PaintArtifactCompositorTest, MergeSimpleChunks) {
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(2u, artifact->PaintChunks().size());
@@ -1306,10 +1412,10 @@ TEST_P(PaintArtifactCompositorTest, MergeClip) {
auto clip = CreateClip(c0(), t0(), FloatRoundedRect(10, 20, 50, 60));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), *clip, e0())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 300, 400), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 200, 300), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 300, 400), Color::kGray);
auto artifact = test_artifact.Build();
@@ -1338,10 +1444,10 @@ TEST_P(PaintArtifactCompositorTest, Merge2DTransform) {
FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1373,11 +1479,11 @@ TEST_P(PaintArtifactCompositorTest, Merge2DTransformDirectAncestor) {
TestPaintArtifact test_artifact;
test_artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
// The second chunk can merge into the first because it has a descendant
// state of the first's transform and no direct compositing reason.
test_artifact.Chunk(*transform2, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
auto artifact = test_artifact.Build();
ASSERT_EQ(2u, artifact->PaintChunks().size());
@@ -1402,10 +1508,10 @@ TEST_P(PaintArtifactCompositorTest, MergeTransformOrigin) {
FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1432,10 +1538,10 @@ TEST_P(PaintArtifactCompositorTest, MergeOpacity) {
auto effect = CreateOpacityEffect(e0(), opacity);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1464,10 +1570,10 @@ TEST_P(PaintArtifactCompositorTest, MergeOpacityWithAlias) {
auto effect = EffectPaintPropertyNode::CreateAlias(*real_effect);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1505,10 +1611,10 @@ TEST_P(PaintArtifactCompositorTest, MergeNestedWithAlias) {
auto effect = EffectPaintPropertyNode::CreateAlias(*real_effect);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(*transform, *clip, *effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1544,10 +1650,10 @@ TEST_P(PaintArtifactCompositorTest, ClipPushedUp) {
auto clip = CreateClip(c0(), *transform2, FloatRoundedRect(10, 20, 50, 60));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), *clip, e0())
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 300, 400), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1570,10 +1676,7 @@ TEST_P(PaintArtifactCompositorTest, ClipPushedUp) {
}
}
-// TODO(crbug.com/696842): The effect refuses to "decomposite" because it's in
-// a deeper transform space than its chunk. We should allow decomposite if
-// the two transform nodes share the same direct compositing ancestor.
-TEST_P(PaintArtifactCompositorTest, DISABLED_EffectPushedUp) {
+TEST_P(PaintArtifactCompositorTest, EffectPushedUp) {
// Tests merging of an element which has an effect applied to it,
// but has an ancestor transform of them. This can happen for fixed-
// or absolute-position elements which escape scroll transforms.
@@ -1590,10 +1693,10 @@ TEST_P(PaintArtifactCompositorTest, DISABLED_EffectPushedUp) {
auto effect = CreateOpacityEffect(e0(), *transform2, &c0(), opacity);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 300, 400), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1615,10 +1718,7 @@ TEST_P(PaintArtifactCompositorTest, DISABLED_EffectPushedUp) {
}
}
-// TODO(crbug.com/696842): The effect refuses to "decomposite" because it's in
-// a deeper transform space than its chunk. We should allow decomposite if
-// the two transform nodes share the same direct compositing ancestor.
-TEST_P(PaintArtifactCompositorTest, DISABLED_EffectAndClipPushedUp) {
+TEST_P(PaintArtifactCompositorTest, EffectAndClipPushedUp) {
// Tests merging of an element which has an effect applied to it,
// but has an ancestor transform of them. This can happen for fixed-
// or absolute-position elements which escape scroll transforms.
@@ -1634,10 +1734,10 @@ TEST_P(PaintArtifactCompositorTest, DISABLED_EffectAndClipPushedUp) {
auto effect = CreateOpacityEffect(e0(), *transform2, clip.get(), opacity);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), *clip, *effect)
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 300, 400), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1669,10 +1769,10 @@ TEST_P(PaintArtifactCompositorTest, ClipAndEffectNoTransform) {
auto effect = CreateOpacityEffect(e0(), t0(), clip.get(), opacity);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), *clip, *effect)
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 300, 400), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1701,10 +1801,10 @@ TEST_P(PaintArtifactCompositorTest, TwoClips) {
auto clip2 = CreateClip(*clip, t0(), FloatRoundedRect(10, 20, 50, 60));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(t0(), *clip2, e0())
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 300, 400), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1735,10 +1835,10 @@ TEST_P(PaintArtifactCompositorTest, TwoTransformsClipBetween) {
CreateTransform(*transform, TransformationMatrix().Translate(20, 25),
FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(*transform2, *clip, e0())
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 300, 400), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1764,10 +1864,10 @@ TEST_P(PaintArtifactCompositorTest, OverlapTransform) {
CompositingReason::k3DTransform);
TestPaintArtifact test_artifact;
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
test_artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 200, 300), Color::kGray);
auto artifact = test_artifact.Build();
ASSERT_EQ(3u, artifact->PaintChunks().size());
@@ -1807,6 +1907,59 @@ TEST_P(PaintArtifactCompositorTest, MightOverlap) {
PendingLayer pending_layer2(paint_chunk2, 1, false);
EXPECT_FALSE(MightOverlap(pending_layer, pending_layer2));
}
+
+ auto transform3 =
+ CreateAnimatingTransform(t0(), TransformationMatrix().Translate(100, 0),
+ FloatPoint3D(100, 100, 0));
+ {
+ SetTransform(paint_chunk2, *transform3);
+ PendingLayer pending_layer2(paint_chunk2, 1, false);
+ EXPECT_TRUE(MightOverlap(pending_layer, pending_layer2));
+ }
+}
+
+TEST_P(PaintArtifactCompositorTest, UniteRectsKnownToBeOpaque) {
+ // X aligned and intersect: unite.
+ EXPECT_EQ(FloatRect(10, 20, 30, 60),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(10, 30, 30, 50)));
+ // X aligned and adjacent: unite.
+ EXPECT_EQ(FloatRect(10, 20, 30, 90),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(10, 60, 30, 50)));
+ // X aligned and separate: choose the bigger one.
+ EXPECT_EQ(FloatRect(10, 61, 30, 50),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(10, 61, 30, 50)));
+ // Y aligned and intersect: unite.
+ EXPECT_EQ(FloatRect(10, 20, 60, 40),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(30, 20, 40, 40)));
+ // Y aligned and adjacent: unite.
+ EXPECT_EQ(FloatRect(10, 20, 70, 40),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(40, 20, 40, 40)));
+ // Y aligned and separate: choose the bigger one.
+ EXPECT_EQ(FloatRect(41, 20, 40, 40),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(41, 20, 40, 40)));
+ // Get the biggest expanded intersection.
+ EXPECT_EQ(FloatRect(0, 0, 9, 19),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(0, 0, 10, 10),
+ FloatRect(0, 9, 9, 10)));
+ EXPECT_EQ(FloatRect(0, 0, 19, 9),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(0, 0, 10, 10),
+ FloatRect(9, 0, 10, 9)));
+ // Otherwise choose the bigger one.
+ EXPECT_EQ(FloatRect(20, 30, 40, 50),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 30, 40),
+ FloatRect(20, 30, 40, 50)));
+ EXPECT_EQ(FloatRect(10, 20, 40, 50),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 40, 50),
+ FloatRect(20, 30, 30, 40)));
+ EXPECT_EQ(FloatRect(10, 20, 40, 50),
+ PendingLayer::UniteRectsKnownToBeOpaque(FloatRect(10, 20, 40, 50),
+ FloatRect(20, 30, 40, 50)));
}
TEST_P(PaintArtifactCompositorTest, PendingLayer) {
@@ -1825,49 +1978,164 @@ TEST_P(PaintArtifactCompositorTest, PendingLayer) {
chunk2.properties = chunk1.properties;
chunk2.known_to_be_opaque = true;
chunk2.bounds = IntRect(10, 20, 30, 40);
- pending_layer.Merge(PendingLayer(chunk2, 1, false));
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
// Bounds not equal to one PaintChunk.
EXPECT_EQ(FloatRect(0, 0, 40, 60), pending_layer.bounds);
EXPECT_EQ((Vector<wtf_size_t>{0, 1}), pending_layer.paint_chunk_indices);
- EXPECT_NE(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.rect_known_to_be_opaque);
PaintChunk chunk3 = DefaultChunk();
chunk3.properties = chunk1.properties;
chunk3.known_to_be_opaque = true;
chunk3.bounds = IntRect(-5, -25, 20, 20);
- pending_layer.Merge(PendingLayer(chunk3, 2, false));
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk3, 2, false)));
EXPECT_EQ(FloatRect(-5, -25, 45, 85), pending_layer.bounds);
EXPECT_EQ((Vector<wtf_size_t>{0, 1, 2}), pending_layer.paint_chunk_indices);
- EXPECT_NE(pending_layer.bounds, pending_layer.rect_known_to_be_opaque);
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.rect_known_to_be_opaque);
}
-TEST_P(PaintArtifactCompositorTest, PendingLayerWithGeometry) {
- auto transform =
- CreateTransform(t0(), TransformationMatrix().Translate(20, 25),
- FloatPoint3D(100, 100, 0));
+TEST_P(PaintArtifactCompositorTest, PendingLayerMergeWithGuestTransform) {
+ auto transform = Create2DTranslation(t0(), 20, 25);
PaintChunk chunk1 = DefaultChunk();
chunk1.properties = PropertyTreeState::Root();
chunk1.bounds = IntRect(0, 0, 30, 40);
+ PaintChunk chunk2 = DefaultChunk();
+ chunk2.properties = chunk1.properties;
+ SetTransform(chunk2, *transform);
+ chunk2.bounds = IntRect(0, 0, 50, 60);
+
PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(0, 0, 70, 85), pending_layer.bounds);
+ EXPECT_EQ(PropertyTreeState::Root(), pending_layer.property_tree_state);
+}
- EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
+TEST_P(PaintArtifactCompositorTest, PendingLayerMergeWithHomeTransform) {
+ auto transform = Create2DTranslation(t0(), 20, 25);
+
+ PaintChunk chunk1 = DefaultChunk();
+ chunk1.properties = PropertyTreeState::Root();
+ SetTransform(chunk1, *transform);
+ chunk1.bounds = IntRect(0, 0, 30, 40);
+
+ PaintChunk chunk2 = DefaultChunk();
+ chunk2.properties = PropertyTreeState::Root();
+ chunk2.bounds = IntRect(0, 0, 50, 60);
+
+ PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(0, 0, 50, 65), pending_layer.bounds);
+ EXPECT_EQ(PropertyTreeState::Root(), pending_layer.property_tree_state);
+}
+
+TEST_P(PaintArtifactCompositorTest, PendingLayerMergeWithBothTransforms) {
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ auto t2 = Create2DTranslation(t0(), -20, -25);
+
+ PaintChunk chunk1 = DefaultChunk();
+ chunk1.properties = PropertyTreeState::Root();
+ SetTransform(chunk1, *t1);
+ chunk1.bounds = IntRect(0, 0, 30, 40);
+
+ PaintChunk chunk2 = DefaultChunk();
+ chunk2.properties = PropertyTreeState::Root();
+ SetTransform(chunk2, *t2);
+ chunk2.bounds = IntRect(0, 0, 50, 60);
+
+ PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(-20, -25, 70, 90), pending_layer.bounds);
+ EXPECT_EQ(PropertyTreeState::Root(), pending_layer.property_tree_state);
+}
+
+TEST_P(PaintArtifactCompositorTest, PendingLayerDontMergeSparse) {
+ PaintChunk chunk1 = DefaultChunk();
+ chunk1.properties = PropertyTreeState::Root(); // (t0(), c0(), *e1);
+ chunk1.known_to_be_opaque = true;
+ chunk1.bounds = IntRect(0, 0, 30, 40);
PaintChunk chunk2 = DefaultChunk();
chunk2.properties = chunk1.properties;
- SetTransform(chunk2, *transform);
+ chunk2.known_to_be_opaque = true;
+ chunk2.bounds = IntRect(200, 200, 30, 40);
+
+ PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
+ EXPECT_EQ(chunk1.properties, pending_layer.property_tree_state);
+ EXPECT_EQ(Vector<wtf_size_t>{0}, pending_layer.paint_chunk_indices);
+}
+
+TEST_P(PaintArtifactCompositorTest, PendingLayerDontMergeSparseWithTransforms) {
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ auto t2 = Create2DTranslation(t0(), 1000, 1000);
+
+ PaintChunk chunk1 = DefaultChunk();
+ chunk1.properties = PropertyTreeState::Root();
+ SetTransform(chunk1, *t1);
+ chunk1.bounds = IntRect(0, 0, 30, 40);
+
+ PaintChunk chunk2 = DefaultChunk();
+ chunk2.properties = PropertyTreeState::Root();
+ SetTransform(chunk2, *t2);
chunk2.bounds = IntRect(0, 0, 50, 60);
- pending_layer.Merge(PendingLayer(chunk2, 1, false));
- EXPECT_EQ(FloatRect(0, 0, 70, 85), pending_layer.bounds);
+ PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
+ EXPECT_EQ(chunk1.properties, pending_layer.property_tree_state);
+ EXPECT_EQ(Vector<wtf_size_t>{0}, pending_layer.paint_chunk_indices);
+}
+
+TEST_P(PaintArtifactCompositorTest,
+ PendingLayerDontMergeSparseInCompositedEffect) {
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ auto t2 = Create2DTranslation(t0(), 1000, 1000);
+ auto e1 =
+ CreateOpacityEffect(e0(), 1.0f, CompositingReason::kWillChangeOpacity);
+
+ PaintChunk chunk1 = DefaultChunk();
+ chunk1.properties = PropertyTreeState(*t1, c0(), *e1);
+ chunk1.bounds = IntRect(0, 0, 30, 40);
+
+ PaintChunk chunk2 = DefaultChunk();
+ chunk2.properties = PropertyTreeState(*t2, c0(), *e1);
+ chunk2.bounds = IntRect(0, 0, 50, 60);
+
+ PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_FALSE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(0, 0, 30, 40), pending_layer.bounds);
+ EXPECT_EQ(chunk1.properties, pending_layer.property_tree_state);
+ EXPECT_EQ(Vector<wtf_size_t>{0}, pending_layer.paint_chunk_indices);
+}
+
+TEST_P(PaintArtifactCompositorTest,
+ PendingLayerMergeSparseInNonCompositedEffect) {
+ auto t1 = Create2DTranslation(t0(), 20, 25);
+ auto t2 = Create2DTranslation(t0(), 1000, 1000);
+ auto e1 = CreateOpacityEffect(e0(), 1.0f, CompositingReason::kNone);
+
+ PaintChunk chunk1 = DefaultChunk();
+ chunk1.properties = PropertyTreeState(*t1, c0(), *e1);
+ chunk1.bounds = IntRect(0, 0, 30, 40);
+
+ PaintChunk chunk2 = DefaultChunk();
+ chunk2.properties = PropertyTreeState(*t2, c0(), *e1);
+ chunk2.bounds = IntRect(0, 0, 50, 60);
+
+ PendingLayer pending_layer(chunk1, 0, false);
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
+ EXPECT_EQ(FloatRect(20, 25, 1030, 1035), pending_layer.bounds);
+ EXPECT_EQ(PropertyTreeState(t0(), c0(), *e1),
+ pending_layer.property_tree_state);
+ EXPECT_EQ((Vector<wtf_size_t>{0, 1}), pending_layer.paint_chunk_indices);
}
-// TODO(crbug.com/701991):
-// The test is disabled because opaque rect mapping is not implemented yet.
-TEST_P(PaintArtifactCompositorTest, DISABLED_PendingLayerKnownOpaque) {
+TEST_P(PaintArtifactCompositorTest, PendingLayerKnownOpaque) {
PaintChunk chunk1 = DefaultChunk();
chunk1.properties = PropertyTreeState::Root();
chunk1.bounds = IntRect(0, 0, 30, 40);
@@ -1880,7 +2148,7 @@ TEST_P(PaintArtifactCompositorTest, DISABLED_PendingLayerKnownOpaque) {
chunk2.properties = chunk1.properties;
chunk2.bounds = IntRect(0, 0, 25, 35);
chunk2.known_to_be_opaque = true;
- pending_layer.Merge(PendingLayer(chunk2, 1, false));
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk2, 1, false)));
// Chunk 2 doesn't cover the entire layer, so not opaque.
EXPECT_EQ(FloatRect(chunk2.bounds), pending_layer.rect_known_to_be_opaque);
@@ -1890,7 +2158,7 @@ TEST_P(PaintArtifactCompositorTest, DISABLED_PendingLayerKnownOpaque) {
chunk3.properties = chunk1.properties;
chunk3.bounds = IntRect(0, 0, 50, 60);
chunk3.known_to_be_opaque = true;
- pending_layer.Merge(PendingLayer(chunk3, 2, false));
+ ASSERT_TRUE(pending_layer.Merge(PendingLayer(chunk3, 2, false)));
// Chunk 3 covers the entire layer, so now it's opaque.
EXPECT_EQ(FloatRect(chunk3.bounds), pending_layer.bounds);
@@ -1921,7 +2189,7 @@ TEST_P(PaintArtifactCompositorTest, TransformWithElementId) {
auto transform = CreateSampleTransformNodeWithElementId();
TestPaintArtifact artifact;
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
EXPECT_EQ(2,
@@ -1932,7 +2200,7 @@ TEST_P(PaintArtifactCompositorTest, EffectWithElementId) {
auto effect = CreateSampleEffectNodeWithElementId();
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
EXPECT_EQ(2, ElementIdToEffectNodeIndex(effect->GetCompositorElementId()));
@@ -1943,7 +2211,7 @@ TEST_P(PaintArtifactCompositorTest, EffectWithElementIdWithAlias) {
auto effect = EffectPaintPropertyNode::CreateAlias(*real_effect);
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
EXPECT_EQ(2,
@@ -1963,9 +2231,9 @@ TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleLuminanceMask) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(t0(), c0(), *masking)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -1979,6 +2247,47 @@ TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleLuminanceMask) {
const cc::EffectNode* masked_group =
GetPropertyTrees().effect_tree.Node(layer->effect_tree_index());
EXPECT_FALSE(masked_group->HasRenderSurface());
+ EXPECT_EQ(SkBlendMode::kSrcOver, masked_group->blend_mode);
+ EXPECT_TRUE(masked_group->filters.IsEmpty());
+ // It's the last effect node. |masking| has been decomposited.
+ EXPECT_EQ(masked_group, GetPropertyTrees().effect_tree.back());
+}
+
+TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskOneChild) {
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ EffectPaintPropertyNode::State masking_state;
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
+ masking_state.color_filter = kColorFilterLuminanceToAlpha;
+ masking_state.blend_mode = SkBlendMode::kDstIn;
+ masking_state.direct_compositing_reasons = CompositingReason::kLayerForMask;
+ auto masking =
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *masked)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(t0(), c0(), *masking)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(2u, LayerCount());
+
+ const cc::Layer* masking_layer = LayerAt(1);
+ const cc::EffectNode* masking_group =
+ GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
+
+ // Render surface is not needed for one child.
+ EXPECT_FALSE(masking_group->HasRenderSurface());
+ ASSERT_EQ(1u, masking_group->filters.size());
+ EXPECT_EQ(cc::FilterOperation::REFERENCE,
+ masking_group->filters.at(0).type());
+ EXPECT_EQ(SkBlendMode::kDstIn, masking_group->blend_mode);
+
+ // The parent also has a render surface to define the scope of the backdrop
+ // of the kDstIn blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskTwoChildren) {
@@ -1997,11 +2306,11 @@ TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskTwoChildren) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(t0(), c0(), *child_of_masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(t0(), c0(), *masking)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -2014,6 +2323,82 @@ TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskTwoChildren) {
ASSERT_EQ(1u, masking_group->filters.size());
EXPECT_EQ(cc::FilterOperation::REFERENCE,
masking_group->filters.at(0).type());
+ EXPECT_EQ(SkBlendMode::kDstIn, masking_group->blend_mode);
+
+ // The parent also has a render surface to define the scope of the backdrop
+ // of the kDstIn blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
+}
+
+TEST_P(PaintArtifactCompositorTest, CompositedMaskOneChild) {
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ EffectPaintPropertyNode::State masking_state;
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
+ masking_state.blend_mode = SkBlendMode::kDstIn;
+ masking_state.direct_compositing_reasons = CompositingReason::kLayerForMask;
+ auto masking =
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *masked)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(t0(), c0(), *masking)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(2u, LayerCount());
+
+ const cc::Layer* masking_layer = LayerAt(1);
+ const cc::EffectNode* masking_group =
+ GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
+
+ // Render surface is not needed for one child.
+ EXPECT_FALSE(masking_group->HasRenderSurface());
+ EXPECT_EQ(SkBlendMode::kDstIn, masking_group->blend_mode);
+
+ // The parent also has a render surface to define the scope of the backdrop
+ // of the kDstIn blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
+}
+
+TEST_P(PaintArtifactCompositorTest, CompositedMaskTwoChildren) {
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ EffectPaintPropertyNode::State masking_state;
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
+ masking_state.blend_mode = SkBlendMode::kDstIn;
+ auto masking =
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
+
+ auto child_of_masked = CreateOpacityEffect(
+ *masking, 1.0, CompositingReason::kIsolateCompositedDescendants);
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *masked)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(t0(), c0(), *child_of_masked)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(t0(), c0(), *masking)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(3u, LayerCount());
+
+ const cc::Layer* masking_layer = LayerAt(2);
+ const cc::EffectNode* masking_group =
+ GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
+
+ // There is a render surface because there are two children.
+ EXPECT_TRUE(masking_group->HasRenderSurface());
+ EXPECT_EQ(SkBlendMode::kDstIn, masking_group->blend_mode);
+
+ // The parent also has a render surface to define the scope of the backdrop
+ // of the kDstIn blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleExoticBlendMode) {
@@ -2028,9 +2413,9 @@ TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleExoticBlendMode) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(t0(), c0(), *masking)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -2038,6 +2423,9 @@ TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleExoticBlendMode) {
const cc::EffectNode* group =
GetPropertyTrees().effect_tree.Node(layer->effect_tree_index());
EXPECT_FALSE(group->HasRenderSurface());
+ EXPECT_EQ(SkBlendMode::kSrcOver, group->blend_mode);
+ // It's the last effect node. |masking| has been decomposited.
+ EXPECT_EQ(group, GetPropertyTrees().effect_tree.back());
}
TEST_P(PaintArtifactCompositorTest, ForcedCompositedExoticBlendMode) {
@@ -2054,9 +2442,9 @@ TEST_P(PaintArtifactCompositorTest, ForcedCompositedExoticBlendMode) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(t0(), c0(), *masking)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -2065,8 +2453,12 @@ TEST_P(PaintArtifactCompositorTest, ForcedCompositedExoticBlendMode) {
GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
EXPECT_EQ(SkBlendMode::kXor, masking_group->blend_mode);
- /// This requires a render surface.
+ // This requires a render surface.
EXPECT_TRUE(masking_group->HasRenderSurface());
+ // The parent also requires a render surface to define the backdrop scope of
+ // the blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest,
@@ -2086,11 +2478,11 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *masked_child1)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(t0(), c0(), *masked_child2)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack);
artifact.Chunk(t0(), c0(), *masking)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -2099,8 +2491,12 @@ TEST_P(PaintArtifactCompositorTest,
GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
EXPECT_EQ(SkBlendMode::kXor, masking_group->blend_mode);
- /// This requires a render surface.
+ // This requires a render surface.
EXPECT_TRUE(masking_group->HasRenderSurface());
+ // The parent also requires a render surface to define the backdrop scope of
+ // the blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest,
@@ -2122,11 +2518,11 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(*transform1, c0(), *masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray);
artifact.Chunk(*transform2, c0(), *masked)
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack);
artifact.Chunk(t0(), c0(), *masking)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -2135,8 +2531,42 @@ TEST_P(PaintArtifactCompositorTest,
GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
EXPECT_EQ(SkBlendMode::kXor, masking_group->blend_mode);
- /// This requires a render surface.
+ // This requires a render surface.
EXPECT_TRUE(masking_group->HasRenderSurface());
+ // The parent also requires a render surface to define the backdrop scope of
+ // the blend mode.
+ EXPECT_TRUE(
+ GetPropertyTrees().effect_tree.parent(masking_group)->HasRenderSurface());
+}
+
+TEST_P(PaintArtifactCompositorTest, DecompositeExoticBlendModeWithoutBackdrop) {
+ auto parent_effect = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ EffectPaintPropertyNode::State blend_state1;
+ blend_state1.local_transform_space = &t0();
+ blend_state1.blend_mode = SkBlendMode::kScreen;
+ auto blend_effect1 =
+ EffectPaintPropertyNode::Create(*parent_effect, std::move(blend_state1));
+ EffectPaintPropertyNode::State blend_state2;
+ blend_state2.local_transform_space = &t0();
+ blend_state2.blend_mode = SkBlendMode::kScreen;
+ auto blend_effect2 =
+ EffectPaintPropertyNode::Create(*parent_effect, std::move(blend_state2));
+
+ Update(TestPaintArtifact()
+ .Chunk(t0(), c0(), *blend_effect1)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kGray)
+ .Chunk(t0(), c0(), *blend_effect2)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack)
+ .Build());
+
+ ASSERT_EQ(1u, LayerCount());
+ const auto* effect =
+ GetPropertyTrees().effect_tree.Node(LayerAt(0)->effect_tree_index());
+ EXPECT_EQ(1.0f, effect->opacity);
+ EXPECT_EQ(SkBlendMode::kSrcOver, effect->blend_mode);
+ // Don't need a render surface because all blend effects are decomposited.
+ EXPECT_FALSE(effect->HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
@@ -2149,8 +2579,8 @@ TEST_P(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
TestPaintArtifact test_artifact;
test_artifact.Chunk(*transform, *clip, *effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(IntRect(0, 0, 100, 100), Color::kGray);
auto artifact = test_artifact.Build();
Update(artifact);
@@ -2189,9 +2619,9 @@ TEST_P(PaintArtifactCompositorTest, DecompositeClip) {
auto clip = CreateClip(c0(), t0(), FloatRoundedRect(75, 75, 100, 100));
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(50, 50, 100, 100), Color::kGray);
artifact.Chunk(t0(), *clip, e0())
- .RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -2208,10 +2638,10 @@ TEST_P(PaintArtifactCompositorTest, DecompositeEffect) {
auto effect = CreateOpacityEffect(e0(), 0.5);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(50, 25, 100, 100), Color::kGray);
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact.Chunk().RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(25, 75, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -2226,10 +2656,10 @@ TEST_P(PaintArtifactCompositorTest, DirectlyCompositedEffect) {
auto effect = CreateOpacityEffect(e0(), 0.5f, CompositingReason::kAll);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(50, 25, 100, 100), Color::kGray);
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact.Chunk().RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(25, 75, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -2261,10 +2691,10 @@ TEST_P(PaintArtifactCompositorTest, DecompositeDeepEffect) {
auto effect3 = CreateOpacityEffect(*effect2, 0.3f);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(50, 25, 100, 100), Color::kGray);
artifact.Chunk(t0(), c0(), *effect3)
- .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact.Chunk().RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(25, 75, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -2298,11 +2728,11 @@ TEST_P(PaintArtifactCompositorTest, IndirectlyCompositedEffect) {
CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(50, 25, 100, 100), Color::kGray);
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(25, 75, 100, 100), Color::kGray);
artifact.Chunk(*transform, c0(), *effect)
- .RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -2333,20 +2763,20 @@ TEST_P(PaintArtifactCompositorTest, DecompositedEffectNotMergingDueToOverlap) {
auto transform = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(0, 0, 50, 50), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(0, 0, 50, 50), Color::kGray);
artifact.Chunk(t0(), c0(), *effect1)
- .RectDrawing(FloatRect(100, 0, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(100, 0, 50, 50), Color::kGray);
// This chunk has a transform that must be composited, thus causing effect1
// to be composited too.
artifact.Chunk(*transform, c0(), *effect1)
- .RectDrawing(FloatRect(200, 0, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(200, 0, 50, 50), Color::kGray);
artifact.Chunk(t0(), c0(), *effect2)
- .RectDrawing(FloatRect(200, 100, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(200, 100, 50, 50), Color::kGray);
// This chunk overlaps with the 2nd chunk, but is seemingly safe to merge.
// However because effect1 gets composited due to a composited transform,
// we can't merge with effect1 nor skip it to merge with the first chunk.
artifact.Chunk(t0(), c0(), *effect2)
- .RectDrawing(FloatRect(100, 0, 50, 50), Color::kGray);
+ .RectDrawing(IntRect(100, 0, 50, 50), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(4u, LayerCount());
@@ -2476,7 +2906,7 @@ TEST_P(PaintArtifactCompositorTest,
auto effect = CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kCanvas);
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
}
@@ -2489,7 +2919,7 @@ TEST_P(PaintArtifactCompositorTest,
CreateOpacityEffect(*tiny_effect, 0.5f, CompositingReason::kNone);
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *visible_effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
EXPECT_EQ(0u, LayerCount());
@@ -2505,7 +2935,7 @@ TEST_P(
auto visible_effect = CreateOpacityEffect(*tiny_effect, 0.5f);
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *visible_effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
}
@@ -2517,7 +2947,7 @@ TEST_P(PaintArtifactCompositorTest,
CreateOpacityEffect(*tiny_effect, 0.5f, CompositingReason::kCanvas);
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *visible_effect)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
EXPECT_EQ(0u, LayerCount());
@@ -2532,7 +2962,7 @@ TEST_P(PaintArtifactCompositorTest, UpdateManagesLayerElementIds) {
{
TestPaintArtifact artifact;
artifact.Chunk(*transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -2552,7 +2982,7 @@ TEST_P(PaintArtifactCompositorTest, UpdateManagesLayerElementIds) {
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipSimple) {
- // This tests the simplist case that a single layer needs to be clipped
+ // This tests the simplest case that a single layer needs to be clipped
// by a single composited rounded clip.
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
@@ -2561,55 +2991,20 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipSimple) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l0
- // [ mask_isolation_0 ]
- // [ e0 ]
- // One content layer.
- ASSERT_EQ(1u, LayerCount());
- // There is still a "synthesized layer" but it's null.
- ASSERT_EQ(1u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
-
- const cc::Layer* content0 = LayerAt(0);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
- return;
- }
-
// Expectation in effect stack diagram:
- // l1
- // l0 [ mask_effect_0 ]
+ // content0
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer.
- ASSERT_EQ(2u, LayerCount());
+ ASSERT_EQ(1u, LayerCount());
+ // There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* clip_mask0 = LayerAt(1);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
@@ -2620,20 +3015,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipSimple) {
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.HasRenderSurface());
-
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
-
- // The masks DrawsContent because it has content that it masks which also
- // DrawsContent.
- EXPECT_TRUE(clip_mask0->DrawsContent());
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipRotatedNotSupported) {
@@ -2650,14 +3035,14 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRotatedNotSupported) {
TestPaintArtifact artifact;
artifact.Chunk(*transform, *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
// Expectation in effect stack diagram:
- // l1
- // l0 [ mask_effect_0 ]
- // [ mask_isolation_0 ]
- // [ e0 ]
+ // clip_mask0
+ // content0 [ mask_effect_0 ]
+ // [ mask_isolation_0 ]
+ // [ e0 ]
// One content layer.
ASSERT_EQ(2u, LayerCount());
ASSERT_EQ(1u, SynthesizedClipLayerCount());
@@ -2665,9 +3050,6 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRotatedNotSupported) {
const cc::Layer* content0 = LayerAt(0);
const cc::Layer* clip_mask0 = LayerAt(1);
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
@@ -2687,6 +3069,8 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRotatedNotSupported) {
*GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ // Render surface is not needed for DstIn controlling only one layer.
+ EXPECT_FALSE(mask_effect_0.HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClip90DegRotationSupported) {
@@ -2703,55 +3087,20 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClip90DegRotationSupported) {
TestPaintArtifact artifact;
artifact.Chunk(*transform, *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l0
- // [ mask_isolation_0 ]
- // [ e0 ]
- // One content layer.
- ASSERT_EQ(1u, LayerCount());
- // There is still a "synthesized layer" but it's null.
- ASSERT_EQ(1u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
-
- const cc::Layer* content0 = LayerAt(0);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
- return;
- }
-
// Expectation in effect stack diagram:
- // l1
- // l0 [ mask_effect_0 ]
+ // content0
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer.
- ASSERT_EQ(2u, LayerCount());
+ ASSERT_EQ(1u, LayerCount());
+ // There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* clip_mask0 = LayerAt(1);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
@@ -2762,21 +3111,15 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClip90DegRotationSupported) {
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.HasRenderSurface());
-
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest,
- SynthesizedClipSimpleFastBorderNotSupported2) {
- // This tests the simplist case that a single layer needs to be clipped
+ SynthesizedClipShaderBasedBorderRadiusNotSupported2) {
+ // This tests the simplest case that a single layer needs to be clipped
// by a single composited rounded clip. Because the radius is unsymmetric,
// it falls back to a mask layer.
FloatSize corner(30, 40);
@@ -2786,14 +3129,14 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
// Expectation in effect stack diagram:
- // l1
- // l0 [ mask_effect_0 ]
- // [ mask_isolation_0 ]
- // [ e0 ]
+ // clip_mask0
+ // content0 [ mask_effect_0 ]
+ // [ mask_isolation_0 ]
+ // [ e0 ]
// One content layer.
ASSERT_EQ(2u, LayerCount());
ASSERT_EQ(1u, SynthesizedClipLayerCount());
@@ -2801,9 +3144,6 @@ TEST_P(PaintArtifactCompositorTest,
const cc::Layer* content0 = LayerAt(0);
const cc::Layer* clip_mask0 = LayerAt(1);
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
@@ -2829,8 +3169,9 @@ TEST_P(PaintArtifactCompositorTest,
EXPECT_TRUE(clip_mask0->DrawsContent());
}
-TEST_P(PaintArtifactCompositorTest,
- SynthesizedClipSimpleFastBorderNotSupportedMacNonEqualCorners) {
+TEST_P(
+ PaintArtifactCompositorTest,
+ SynthesizedClipSimpleShaderBasedBorderRadiusNotSupportedMacNonEqualCorners) {
// Tests that on Mac, we fall back to a mask layer if the corners are not all
// the same radii.
FloatSize corner(30, 30);
@@ -2840,25 +3181,19 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
#if defined(OS_MACOSX)
ASSERT_EQ(2u, LayerCount());
#else
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled())
- ASSERT_EQ(1u, LayerCount());
- else
- ASSERT_EQ(2u, LayerCount());
+ ASSERT_EQ(1u, LayerCount());
#endif
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipNested) {
- // This tests the simplist case that a single layer needs to be clipped
+ // This tests the simplest case that a single layer needs to be clipped
// by a single composited rounded clip.
- if (!RuntimeEnabledFeatures::FastBorderRadiusEnabled())
- return;
-
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
@@ -2873,18 +3208,18 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipNested) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, *filter)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(*t1, *c3, *filter)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
// Expectation in effect stack diagram:
- // l0
- // [ mask_isolation_2 ]
- // l1 [ mask_isolation_1 ]
- // [ filter ]
- // [ mask_isolation_0 ]
- // [ e0 ]
+ // content1
+ // [ mask_isolation_2 ]
+ // content0 [ mask_isolation_1 ]
+ // [ filter ]
+ // [ mask_isolation_0 ]
+ // [ e0 ]
// Two content layers.
///
// mask_isolation_1 will have a render surface. mask_isolation_2 will not
@@ -2902,9 +3237,7 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipNested) {
const cc::Layer* content0 = LayerAt(0);
const cc::Layer* content1 = LayerAt(1);
- constexpr int c0_id = 1;
constexpr int c1_id = 2;
- constexpr int e0_id = 1;
constexpr int e1_id = 2;
int c3_id = content1->clip_tree_index();
@@ -2965,11 +3298,11 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipIsNotDrawable) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 0, 0), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 0, 0), Color::kBlack);
Update(artifact.Build());
// Expectation in effect stack diagram:
- // l1
+ // content0
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer, no clip mask (because layer doesn't draw content).
@@ -2980,9 +3313,6 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipIsNotDrawable) {
const cc::Layer* content0 = LayerAt(0);
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
@@ -3005,7 +3335,7 @@ TEST_P(PaintArtifactCompositorTest, ReuseSyntheticClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 0, 0), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 0, 0), Color::kBlack);
Update(artifact.Build());
const cc::Layer* content0 = LayerAt(0);
@@ -3016,7 +3346,7 @@ TEST_P(PaintArtifactCompositorTest, ReuseSyntheticClip) {
TestPaintArtifact repeated_artifact;
repeated_artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 0, 0), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 0, 0), Color::kBlack);
Update(repeated_artifact.Build());
const cc::Layer* content1 = LayerAt(0);
@@ -3028,7 +3358,7 @@ TEST_P(PaintArtifactCompositorTest, ReuseSyntheticClip) {
TestPaintArtifact changed_artifact;
changed_artifact.Chunk(t0(), *c2, e0())
- .RectDrawing(FloatRect(0, 0, 0, 0), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 0, 0), Color::kBlack);
Update(changed_artifact.Build());
const cc::Layer* content2 = LayerAt(0);
@@ -3050,14 +3380,14 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, *e1)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
// Expectation in effect stack diagram:
- // l0 l1
- // [ e1 ][ mask_effect_0 ]
- // [ mask_isolation_0 ]
- // [ e0 ]
+ // content0 clip_mask0
+ // [ e1 ][ mask_effect_0 ]
+ // [ mask_isolation_0 ]
+ // [ e0 ]
// One content layer, one clip mask.
ASSERT_EQ(2u, LayerCount());
ASSERT_EQ(1u, SynthesizedClipLayerCount());
@@ -3065,9 +3395,6 @@ TEST_P(PaintArtifactCompositorTest,
const cc::Layer* content0 = LayerAt(0);
const cc::Layer* clip_mask0 = LayerAt(1);
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
@@ -3106,71 +3433,23 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipContiguous) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(*t1, *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l2
- // l0 l1
- // [ mask_isolation_0 ]
- // [ e0 ]
- // Two content layers, one clip mask.
- ASSERT_EQ(2u, LayerCount());
- // There is still a "synthesized layer" but it's null.
- ASSERT_EQ(1u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
-
- const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* content1 = LayerAt(1);
-
- constexpr int t0_id = 1;
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- EXPECT_EQ(t0_id, content0->transform_tree_index());
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
-
- int t1_id = content1->transform_tree_index();
- const cc::TransformNode& cc_t1 =
- *GetPropertyTrees().transform_tree.Node(t1_id);
- ASSERT_EQ(t0_id, cc_t1.parent_id);
- EXPECT_EQ(c1_id, content1->clip_tree_index());
- EXPECT_EQ(mask_isolation_0_id, content1->effect_tree_index());
-
- EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
- return;
- }
-
// Expectation in effect stack diagram:
- // l2
- // l0 l1 [ mask_effect_0 ]
- // [ mask_isolation_0 ]
- // [ e0 ]
+ // content0 content1
+ // [ mask_isolation_0 ]
+ // [ e0 ]
// Two content layers, one clip mask.
- ASSERT_EQ(3u, LayerCount());
+ ASSERT_EQ(2u, LayerCount());
+ // There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = LayerAt(0);
const cc::Layer* content1 = LayerAt(1);
- const cc::Layer* clip_mask0 = LayerAt(2);
-
- constexpr int t0_id = 1;
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
EXPECT_EQ(t0_id, content0->transform_tree_index());
int c1_id = content0->clip_tree_index();
@@ -3190,15 +3469,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipContiguous) {
EXPECT_EQ(c1_id, content1->clip_tree_index());
EXPECT_EQ(mask_isolation_0_id, content1->effect_tree_index());
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(t0_id, clip_mask0->transform_tree_index());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
@@ -3215,89 +3489,28 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(*t1, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l1 l4
- // l0 l3
- // [ mask_isolation_0 ] l2 [ mask_isolation_1 ]
- // [ e0 ]
- // Three content layers.
- ASSERT_EQ(3u, LayerCount());
- // There are still "synthesized layers" but they're null.
- ASSERT_EQ(2u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
- EXPECT_FALSE(SynthesizedClipLayerAt(1));
-
- const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* content1 = LayerAt(1);
- const cc::Layer* content2 = LayerAt(2);
-
- constexpr int t0_id = 1;
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- EXPECT_EQ(t0_id, content0->transform_tree_index());
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
-
- int t1_id = content1->transform_tree_index();
- const cc::TransformNode& cc_t1 =
- *GetPropertyTrees().transform_tree.Node(t1_id);
- ASSERT_EQ(t0_id, cc_t1.parent_id);
- EXPECT_EQ(c0_id, content1->clip_tree_index());
- EXPECT_EQ(e0_id, content1->effect_tree_index());
-
- EXPECT_EQ(t0_id, content2->transform_tree_index());
- EXPECT_EQ(c1_id, content2->clip_tree_index());
- int mask_isolation_1_id = content2->effect_tree_index();
- const cc::EffectNode& mask_isolation_1 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
- EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
- ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode);
- EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_1.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_1.HasRenderSurface());
- return;
- }
-
// Expectation in effect stack diagram:
- // l1 l4
- // l0 [ mask_effect_0 ] l3 [ mask_effect_1 ]
- // [ mask_isolation_0 ] l2 [ mask_isolation_1 ]
- // [ e0 ]
- // Three content layers, two clip mask.
- ASSERT_EQ(5u, LayerCount());
+ // content0 content2
+ // [ mask_isolation_0 ] content1 [ mask_isolation_1 ]
+ // [ e0 ]
+ // Three content layers.
+ ASSERT_EQ(3u, LayerCount());
+ // There are still "synthesized layers" but they're null because they use
+ // fast rounded corners.
ASSERT_EQ(2u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
+ EXPECT_FALSE(SynthesizedClipLayerAt(1));
const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* clip_mask0 = LayerAt(1);
- const cc::Layer* content1 = LayerAt(2);
- const cc::Layer* content2 = LayerAt(3);
- const cc::Layer* clip_mask1 = LayerAt(4);
-
- constexpr int t0_id = 1;
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
+ const cc::Layer* content1 = LayerAt(1);
+ const cc::Layer* content2 = LayerAt(2);
EXPECT_EQ(t0_id, content0->transform_tree_index());
int c1_id = content0->clip_tree_index();
@@ -3309,17 +3522,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.HasRenderSurface());
-
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(t0_id, clip_mask0->transform_tree_index());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
int t1_id = content1->transform_tree_index();
const cc::TransformNode& cc_t1 =
@@ -3336,17 +3542,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode);
- EXPECT_TRUE(mask_isolation_1.HasRenderSurface());
-
- EXPECT_EQ(SynthesizedClipLayerAt(1), clip_mask1);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask1->bounds());
- EXPECT_EQ(t0_id, clip_mask1->transform_tree_index());
- EXPECT_EQ(c1_id, clip_mask1->clip_tree_index());
- int mask_effect_1_id = clip_mask1->effect_tree_index();
- const cc::EffectNode& mask_effect_1 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_1_id);
- ASSERT_EQ(mask_isolation_1_id, mask_effect_1.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_1.blend_mode);
+ EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_1.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_1.HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
@@ -3361,75 +3560,27 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, *e1)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l1 l3
- // l0 [ e1 ] l2
- // [ mask_isolation_0 ]
- // [ e0 ]
- // Three content layers.
- ASSERT_EQ(3u, LayerCount());
- // There is still a "synthesized layer" but it's null.
- ASSERT_EQ(1u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
-
- const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* content1 = LayerAt(1);
- const cc::Layer* content2 = LayerAt(2);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
-
- EXPECT_EQ(c1_id, content1->clip_tree_index());
- int e1_id = content1->effect_tree_index();
- const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
- ASSERT_EQ(mask_isolation_0_id, cc_e1.parent_id);
-
- EXPECT_EQ(c1_id, content2->clip_tree_index());
- EXPECT_EQ(mask_isolation_0_id, content2->effect_tree_index());
-
- int e2_id = content2->effect_tree_index();
- const cc::EffectNode& cc_e2 = *GetPropertyTrees().effect_tree.Node(e2_id);
- EXPECT_TRUE(cc_e2.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
- return;
- }
-
// Expectation in effect stack diagram:
- // l1 l3
- // l0 [ e1 ] l2 [ mask_effect_0 ]
- // [ mask_isolation_0 ]
- // [ e0 ]
- // Three content layers, one clip mask.
- ASSERT_EQ(4u, LayerCount());
+ // content1
+ // content0 [ e1 ] content2
+ // [ mask_isolation_0 ]
+ // [ e0 ]
+ // Three content layers.
+ ASSERT_EQ(3u, LayerCount());
+ // There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = LayerAt(0);
const cc::Layer* content1 = LayerAt(1);
const cc::Layer* content2 = LayerAt(2);
- const cc::Layer* clip_mask0 = LayerAt(3);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
@@ -3440,7 +3591,7 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.HasRenderSurface());
+ EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
EXPECT_EQ(c1_id, content1->clip_tree_index());
int e1_id = content1->effect_tree_index();
@@ -3450,14 +3601,11 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
EXPECT_EQ(c1_id, content2->clip_tree_index());
EXPECT_EQ(mask_isolation_0_id, content2->effect_tree_index());
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ int e2_id = content2->effect_tree_index();
+ const cc::EffectNode& cc_e2 = *GetPropertyTrees().effect_tree.Node(e2_id);
+ EXPECT_TRUE(cc_e2.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
@@ -3476,97 +3624,30 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, *e1)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l3
- // l1 l2 l5
- // l0 [ mask_isolation_1 ] l4
- // [ mask_isolation_0 ][ e1 ][ mask_isolation_2 ]
- // [ e0 ]
- // Three content layers.
- ASSERT_EQ(3u, LayerCount());
- // There are still "synthesized layers" but they're null.
- ASSERT_EQ(3u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
- EXPECT_FALSE(SynthesizedClipLayerAt(1));
- EXPECT_FALSE(SynthesizedClipLayerAt(2));
-
- const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* content1 = LayerAt(1);
- const cc::Layer* content2 = LayerAt(2);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
-
- EXPECT_EQ(c1_id, content1->clip_tree_index());
- int mask_isolation_1_id = content1->effect_tree_index();
- const cc::EffectNode& mask_isolation_1 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
- EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode);
- int e1_id = mask_isolation_1.parent_id;
- const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
- ASSERT_EQ(e0_id, cc_e1.parent_id);
- EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_1.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_1.HasRenderSurface());
-
- EXPECT_EQ(c1_id, content2->clip_tree_index());
- int mask_isolation_2_id = content2->effect_tree_index();
- const cc::EffectNode& mask_isolation_2 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_2_id);
- EXPECT_NE(mask_isolation_0_id, mask_isolation_2_id);
- EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
- ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_2.blend_mode);
- EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_2.rounded_corner_bounds);
- EXPECT_FALSE(mask_isolation_2.HasRenderSurface());
- return;
- }
-
// Expectation in effect stack diagram:
- // l3
- // l1 l2 [ mask_effect_1 ] l5
- // l0 [ mask_effect_0 ][ mask_isolation_1 ] l4 [ mask_effect_2 ]
+ // content1
+ // content0 [ mask_isolation_1 ] content2
// [ mask_isolation_0 ][ e1 ][ mask_isolation_2 ]
// [ e0 ]
- // Three content layers, three clip mask.
- ASSERT_EQ(6u, LayerCount());
+ // Three content layers.
+ ASSERT_EQ(3u, LayerCount());
+ // There are still "synthesized layers" but they're null because they use
+ // fast rounded corners.
ASSERT_EQ(3u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
+ EXPECT_FALSE(SynthesizedClipLayerAt(1));
+ EXPECT_FALSE(SynthesizedClipLayerAt(2));
const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* clip_mask0 = LayerAt(1);
- const cc::Layer* content1 = LayerAt(2);
- const cc::Layer* clip_mask1 = LayerAt(3);
- const cc::Layer* content2 = LayerAt(4);
- const cc::Layer* clip_mask2 = LayerAt(5);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
+ const cc::Layer* content1 = LayerAt(1);
+ const cc::Layer* content2 = LayerAt(2);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
@@ -3577,15 +3658,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
-
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
EXPECT_EQ(c1_id, content1->clip_tree_index());
int mask_isolation_1_id = content1->effect_tree_index();
@@ -3596,15 +3672,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
int e1_id = mask_isolation_1.parent_id;
const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
ASSERT_EQ(e0_id, cc_e1.parent_id);
-
- EXPECT_EQ(SynthesizedClipLayerAt(1), clip_mask1);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask1->bounds());
- EXPECT_EQ(c1_id, clip_mask1->clip_tree_index());
- int mask_effect_1_id = clip_mask1->effect_tree_index();
- const cc::EffectNode& mask_effect_1 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_1_id);
- ASSERT_EQ(mask_isolation_1_id, mask_effect_1.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_1.blend_mode);
+ EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_1.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_1.HasRenderSurface());
EXPECT_EQ(c1_id, content2->clip_tree_index());
int mask_isolation_2_id = content2->effect_tree_index();
@@ -3614,15 +3685,10 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_2.blend_mode);
-
- EXPECT_EQ(SynthesizedClipLayerAt(2), clip_mask2);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask2->bounds());
- EXPECT_EQ(c1_id, clip_mask2->clip_tree_index());
- int mask_effect_2_id = clip_mask2->effect_tree_index();
- const cc::EffectNode& mask_effect_2 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_2_id);
- ASSERT_EQ(mask_isolation_2_id, mask_effect_2.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_2.blend_mode);
+ EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_2.rounded_corner_bounds);
+ EXPECT_FALSE(mask_isolation_2.HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
@@ -3643,94 +3709,30 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, *e1)
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
artifact.Chunk(t0(), *c1, e0())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
- if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
- // Expectation in effect stack diagram:
- // l1 l2 l3 l5
- // l0 [ e1 ] l4
- // [ mask_isolation_0 ][ mask_isolation_1 ][ mask_isolation_2 ]
- // [ e0 ]
- // Three content layers.
- ASSERT_EQ(3u, LayerCount());
- // There are still "synthesized layers" but they're null.
- ASSERT_EQ(3u, SynthesizedClipLayerCount());
- EXPECT_FALSE(SynthesizedClipLayerAt(0));
- EXPECT_FALSE(SynthesizedClipLayerAt(1));
- EXPECT_FALSE(SynthesizedClipLayerAt(2));
-
- const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* content1 = LayerAt(1);
- const cc::Layer* content2 = LayerAt(2);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
-
- int c1_id = content0->clip_tree_index();
- const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
- EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
- ASSERT_EQ(c0_id, cc_c1.parent_id);
- int mask_isolation_0_id = content0->effect_tree_index();
- const cc::EffectNode& mask_isolation_0 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
- ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_0.rounded_corner_bounds);
-
- EXPECT_EQ(c1_id, content1->clip_tree_index());
- int e1_id = content1->effect_tree_index();
- const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, cc_e1.blend_mode);
- int mask_isolation_1_id = cc_e1.parent_id;
- const cc::EffectNode& mask_isolation_1 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
- EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
- ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
- EXPECT_EQ(SkBlendMode::kMultiply, mask_isolation_1.blend_mode);
- EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_1.rounded_corner_bounds);
-
- EXPECT_EQ(c1_id, content2->clip_tree_index());
- int mask_isolation_2_id = content2->effect_tree_index();
- const cc::EffectNode& mask_isolation_2 =
- *GetPropertyTrees().effect_tree.Node(mask_isolation_2_id);
- EXPECT_NE(mask_isolation_0_id, mask_isolation_2_id);
- EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
- ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
- EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
- EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
- EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
- mask_isolation_2.rounded_corner_bounds);
-
- return;
- }
-
// Expectation in effect stack diagram:
- // l1 l2 l3 l5
- // l0 [ mask_effect_0 ][ e1 ][ mask_effect_1 ] l4 [ mask_effect_2 ]
+ // content1
+ // content0 [ e1 ] content2
// [ mask_isolation_0 ][ mask_isolation_1 ][ mask_isolation_2 ]
// [ e0 ]
- // Three content layers, three clip mask.
- ASSERT_EQ(6u, LayerCount());
+ // Three content layers.
+ ASSERT_EQ(3u, LayerCount());
+ // There are still "synthesized layers" but they're null because they use
+ // fast rounded corners.
ASSERT_EQ(3u, SynthesizedClipLayerCount());
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
+ EXPECT_FALSE(SynthesizedClipLayerAt(1));
+ EXPECT_FALSE(SynthesizedClipLayerAt(2));
const cc::Layer* content0 = LayerAt(0);
- const cc::Layer* clip_mask0 = LayerAt(1);
- const cc::Layer* content1 = LayerAt(2);
- const cc::Layer* clip_mask1 = LayerAt(3);
- const cc::Layer* content2 = LayerAt(4);
- const cc::Layer* clip_mask2 = LayerAt(5);
-
- constexpr int c0_id = 1;
- constexpr int e0_id = 1;
+ const cc::Layer* content1 = LayerAt(1);
+ const cc::Layer* content2 = LayerAt(2);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
@@ -3741,15 +3743,9 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
-
- EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
- EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
- int mask_effect_0_id = clip_mask0->effect_tree_index();
- const cc::EffectNode& mask_effect_0 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
- ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
EXPECT_EQ(c1_id, content1->clip_tree_index());
int e1_id = content1->effect_tree_index();
@@ -3761,15 +3757,9 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
EXPECT_EQ(SkBlendMode::kMultiply, mask_isolation_1.blend_mode);
-
- EXPECT_EQ(SynthesizedClipLayerAt(1), clip_mask1);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask1->bounds());
- EXPECT_EQ(c1_id, clip_mask1->clip_tree_index());
- int mask_effect_1_id = clip_mask1->effect_tree_index();
- const cc::EffectNode& mask_effect_1 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_1_id);
- ASSERT_EQ(mask_isolation_1_id, mask_effect_1.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_1.blend_mode);
+ EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_1.rounded_corner_bounds);
EXPECT_EQ(c1_id, content2->clip_tree_index());
int mask_isolation_2_id = content2->effect_tree_index();
@@ -3779,22 +3769,123 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
+ EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_2.rounded_corner_bounds);
+}
+
+TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBackdropFilter) {
+ // This tests the case that an effect with backdrop filter cannot share
+ // the synthesized mask with its siblings because its backdrop filter has to
+ // be applied by the outermost mask in the correct transform space.
+ FloatSize corner(5, 5);
+ FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
+ corner);
+ auto c1 = CreateClip(c0(), t0(), rrect);
+
+ auto t1 = Create2DTranslation(t0(), 10, 20);
+ CompositorFilterOperations blur_filter;
+ blur_filter.AppendBlurFilter(5);
+ auto e1 = CreateBackdropFilterEffect(e0(), *t1, c1.get(), blur_filter,
+ FloatPoint());
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(*t1, *c1, e0())
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ artifact.Chunk(*t1, *c1, *e1)
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ artifact.Chunk(*t1, *c1, e0())
+ .RectDrawing(IntRect(0, 0, 100, 100), Color::kBlack);
+ Update(artifact.Build());
+
+ // Expectation in effect stack diagram:
+ // content1
+ // content0 [ e1 ] clip_mask1 content2
+ // [ mask_isolation_0 ][ mask_isolation_1 ][ mask_isolation_2 ]
+ // [ e0 ]
+ // Three content layers.
+ ASSERT_EQ(4u, LayerCount());
+ const cc::Layer* content0 = LayerAt(0);
+ const cc::Layer* content1 = LayerAt(1);
+ const cc::Layer* clip_mask1 = LayerAt(2);
+ const cc::Layer* content2 = LayerAt(3);
+
+ // Three synthesized layers, two of which are null because because they use
+ // fast rounded corners. One real synthesized layer is needed because the
+ // rounded clip and the backdrop filter are in different transform spaces.
+ EXPECT_FALSE(SynthesizedClipLayerAt(0));
+ EXPECT_EQ(clip_mask1, SynthesizedClipLayerAt(1));
+ EXPECT_FALSE(SynthesizedClipLayerAt(2));
+
+ int t1_id = content0->transform_tree_index();
+ EXPECT_EQ(t0_id, GetPropertyTrees().transform_tree.Node(t1_id)->parent_id);
+ int c1_id = content0->clip_tree_index();
+ const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
+ EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
+ ASSERT_EQ(c0_id, cc_c1.parent_id);
+ EXPECT_EQ(t0_id, cc_c1.transform_id);
+ int mask_isolation_0_id = content0->effect_tree_index();
+ const cc::EffectNode& mask_isolation_0 =
+ *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
+ ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
+ EXPECT_EQ(t0_id, mask_isolation_0.transform_id);
+ EXPECT_TRUE(mask_isolation_0.backdrop_filters.IsEmpty());
+ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_0.rounded_corner_bounds);
+
+ EXPECT_EQ(t1_id, content1->transform_tree_index());
+ EXPECT_EQ(c1_id, content1->clip_tree_index());
+ int e1_id = content1->effect_tree_index();
+ const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
+ EXPECT_TRUE(cc_e1.backdrop_filters.IsEmpty());
+ EXPECT_EQ(t1_id, cc_e1.transform_id);
+ EXPECT_EQ(c1_id, cc_e1.clip_id);
+ EXPECT_FALSE(cc_e1.backdrop_mask_element_id);
+
+ int mask_isolation_1_id = cc_e1.parent_id;
+ const cc::EffectNode& mask_isolation_1 =
+ *GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
+ EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
+ ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
+ EXPECT_EQ(t1_id, mask_isolation_1.transform_id);
+ EXPECT_EQ(c1_id, mask_isolation_1.clip_id);
+ EXPECT_FALSE(mask_isolation_1.backdrop_filters.IsEmpty());
+ EXPECT_FALSE(mask_isolation_1.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(), mask_isolation_1.rounded_corner_bounds);
- EXPECT_EQ(SynthesizedClipLayerAt(2), clip_mask2);
- EXPECT_EQ(gfx::Size(300, 200), clip_mask2->bounds());
- EXPECT_EQ(c1_id, clip_mask2->clip_tree_index());
- int mask_effect_2_id = clip_mask2->effect_tree_index();
- const cc::EffectNode& mask_effect_2 =
- *GetPropertyTrees().effect_tree.Node(mask_effect_2_id);
- ASSERT_EQ(mask_isolation_2_id, mask_effect_2.parent_id);
- EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_2.blend_mode);
+ EXPECT_EQ(t0_id, clip_mask1->transform_tree_index());
+ EXPECT_EQ(c1_id, clip_mask1->clip_tree_index());
+ const cc::EffectNode& mask =
+ *GetPropertyTrees().effect_tree.Node(clip_mask1->effect_tree_index());
+ ASSERT_EQ(mask_isolation_1_id, mask.parent_id);
+ EXPECT_EQ(SkBlendMode::kDstIn, mask.blend_mode);
+ EXPECT_TRUE(static_cast<const cc::PictureLayer*>(clip_mask1)
+ ->is_backdrop_filter_mask());
+ EXPECT_TRUE(clip_mask1->element_id());
+ EXPECT_EQ(clip_mask1->element_id(),
+ mask_isolation_1.backdrop_mask_element_id);
+
+ EXPECT_EQ(t1_id, content2->transform_tree_index());
+ EXPECT_EQ(c1_id, content2->clip_tree_index());
+ int mask_isolation_2_id = content2->effect_tree_index();
+ const cc::EffectNode& mask_isolation_2 =
+ *GetPropertyTrees().effect_tree.Node(mask_isolation_2_id);
+ EXPECT_NE(mask_isolation_0_id, mask_isolation_2_id);
+ EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
+ ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
+ EXPECT_EQ(t0_id, mask_isolation_2.transform_id);
+ EXPECT_TRUE(mask_isolation_2.backdrop_filters.IsEmpty());
+ EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
+ EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
+ mask_isolation_2.rounded_corner_bounds);
}
TEST_P(PaintArtifactCompositorTest, WillBeRemovedFromFrame) {
auto effect = CreateSampleEffectNodeWithElementId();
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *effect)
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -3806,7 +3897,7 @@ TEST_P(PaintArtifactCompositorTest, WillBeRemovedFromFrame) {
TEST_P(PaintArtifactCompositorTest, ContentsNonOpaque) {
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
+ artifact.Chunk().RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_FALSE(LayerAt(0)->contents_opaque());
@@ -3815,7 +3906,7 @@ TEST_P(PaintArtifactCompositorTest, ContentsNonOpaque) {
TEST_P(PaintArtifactCompositorTest, ContentsOpaque) {
TestPaintArtifact artifact;
artifact.Chunk()
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -3825,10 +3916,10 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaque) {
TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedNonOpaque) {
TestPaintArtifact artifact;
artifact.Chunk()
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 210, 210), Color::kBlack)
.KnownToBeOpaque()
.Chunk()
- .RectDrawing(FloatRect(200, 200, 200, 200), Color::kBlack)
+ .RectDrawing(IntRect(200, 200, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -3836,13 +3927,30 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedNonOpaque) {
EXPECT_FALSE(LayerAt(0)->contents_opaque());
}
+TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedClippedToOpaque) {
+ // Almost the same as ContentsOpaqueUnitedNonOpaque, but with a clip which
+ // removes the non-opaque part of the layer, making the layer opaque.
+ auto clip1 = CreateClip(c0(), t0(), FloatRoundedRect(175, 175, 100, 100));
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *clip1, e0())
+ .RectDrawing(IntRect(100, 100, 210, 210), Color::kBlack)
+ .KnownToBeOpaque()
+ .Chunk(t0(), *clip1, e0())
+ .RectDrawing(IntRect(200, 200, 200, 200), Color::kBlack)
+ .KnownToBeOpaque();
+ Update(artifact.Build());
+ ASSERT_EQ(1u, LayerCount());
+ EXPECT_EQ(gfx::Size(100, 100), LayerAt(0)->bounds());
+ EXPECT_TRUE(LayerAt(0)->contents_opaque());
+}
+
TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque1) {
TestPaintArtifact artifact;
artifact.Chunk()
- .RectDrawing(FloatRect(100, 100, 300, 300), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 300, 300), Color::kBlack)
.KnownToBeOpaque()
.Chunk()
- .RectDrawing(FloatRect(200, 200, 200, 200), Color::kBlack)
+ .RectDrawing(IntRect(200, 200, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -3850,20 +3958,38 @@ TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque1) {
EXPECT_TRUE(LayerAt(0)->contents_opaque());
}
+TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedWithRoundedClip) {
+ // Almost the same as ContentsOpaqueUnitedOpaque1, but the first layer has a
+ // rounded clip.
+ FloatSize corner(5, 5);
+ auto clip1 = CreateClip(c0(), t0(),
+ FloatRoundedRect(FloatRect(175, 175, 100, 100),
+ corner, corner, corner, corner));
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *clip1, e0())
+ .RectDrawing(IntRect(100, 100, 210, 210), Color::kBlack)
+ .KnownToBeOpaque()
+ .Chunk(t0(), c0(), e0())
+ .RectDrawing(IntRect(200, 200, 100, 100), Color::kBlack)
+ .KnownToBeOpaque();
+ Update(artifact.Build());
+ ASSERT_EQ(1u, LayerCount());
+ EXPECT_EQ(gfx::Size(125, 125), LayerAt(0)->bounds());
+ EXPECT_FALSE(LayerAt(0)->contents_opaque());
+}
+
TEST_P(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque2) {
TestPaintArtifact artifact;
artifact.Chunk()
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 200), Color::kBlack)
.KnownToBeOpaque()
.Chunk()
- .RectDrawing(FloatRect(100, 100, 300, 300), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 300, 300), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_EQ(gfx::Size(300, 300), LayerAt(0)->bounds());
- // TODO(crbug.com/701991): Upgrade GeometryMapper to make this test pass with
- // the following EXPECT_FALSE changed to EXPECT_TRUE.
- EXPECT_FALSE(LayerAt(0)->contents_opaque());
+ EXPECT_TRUE(LayerAt(0)->contents_opaque());
}
TEST_P(PaintArtifactCompositorTest, DecompositeEffectWithNoOutputClip) {
@@ -3873,9 +3999,9 @@ TEST_P(PaintArtifactCompositorTest, DecompositeEffectWithNoOutputClip) {
auto effect1 = CreateOpacityEffect(e0(), t0(), nullptr, 0.5);
TestPaintArtifact artifact;
- artifact.Chunk().RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(IntRect(50, 50, 100, 100), Color::kGray);
artifact.Chunk(t0(), *clip1, *effect1)
- .RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -3895,9 +4021,9 @@ TEST_P(PaintArtifactCompositorTest, CompositedEffectWithNoOutputClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *effect1)
- .RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(50, 50, 100, 100), Color::kGray);
artifact.Chunk(t0(), *clip1, *effect1)
- .RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(100, 100, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -3918,7 +4044,7 @@ TEST_P(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
auto clip = CreateClip(c0(), t0(), FloatRoundedRect(10, 20, 300, 400));
TestPaintArtifact artifact1;
artifact1.Chunk(t0(), *clip, e0())
- .RectDrawing(FloatRect(50, 50, 200, 200), Color::kBlack);
+ .RectDrawing(IntRect(50, 50, 200, 200), Color::kBlack);
artifact1.Client(0).Validate();
artifact1.Client(1).Validate();
Update(artifact1.Build());
@@ -3936,7 +4062,7 @@ TEST_P(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
.Chunk(artifact1.Client(0))
.Properties(t0(), *clip, e0())
.RectDrawing(artifact1.Client(1),
- FloatRect(0, 0, 400, 200), Color::kBlack)
+ IntRect(0, 0, 400, 200), Color::kBlack)
.Build();
// Simluate commit to the compositor thread.
layer->PushPropertiesTo(
@@ -3958,7 +4084,7 @@ TEST_P(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
TestPaintArtifact()
.Chunk(artifact1.Client(0))
.Properties(t0(), *clip, e0())
- .RectDrawing(artifact1.Client(1), FloatRect(-100, -200, 500, 800),
+ .RectDrawing(artifact1.Client(1), IntRect(-100, -200, 500, 800),
Color::kBlack)
.Build();
// Simluate commit to the compositor thread.
@@ -4031,7 +4157,7 @@ TEST_P(PaintArtifactCompositorTest, InSubtreeOfPageScale) {
TestPaintArtifact artifact;
artifact.Chunk(*descendant_transform, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 10, 10), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 10, 10), Color::kBlack);
ViewportProperties viewport_properties;
viewport_properties.page_scale = page_scale_transform.get();
Update(artifact.Build(), viewport_properties);
@@ -4085,7 +4211,7 @@ TEST_P(PaintArtifactCompositorTest, ViewportPageScale) {
TestPaintArtifact artifact;
artifact.Chunk(*scroll_translation, c0(), e0())
- .RectDrawing(FloatRect(0, 0, 10, 10), Color::kBlack);
+ .RectDrawing(IntRect(0, 0, 10, 10), Color::kBlack);
ViewportProperties viewport_properties;
viewport_properties.page_scale = scale_transform_node.get();
Update(artifact.Build(), viewport_properties);
@@ -4135,7 +4261,7 @@ TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfaces) {
FloatPoint3D(), CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- FloatRect r(150, 150, 100, 100);
+ IntRect r(150, 150, 100, 100);
artifact.Chunk(t0(), c0(), *aa).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), c0(), *ab).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), c0(), *b).RectDrawing(r, Color::kWhite);
@@ -4184,7 +4310,7 @@ TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfacesWithFilterChildren) {
auto filter2 = CreateFilterEffect(*opacity, filter, FloatPoint(),
CompositingReason::kActiveFilterAnimation);
- FloatRect r(150, 150, 100, 100);
+ IntRect r(150, 150, 100, 100);
Update(TestPaintArtifact()
.Chunk(t0(), c0(), *filter1)
.RectDrawing(r, Color::kWhite)
@@ -4222,7 +4348,7 @@ TEST_P(PaintArtifactCompositorTest, OpacityAnimationRenderSurfaces) {
FloatPoint3D(), CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- FloatRect r(150, 150, 100, 100);
+ IntRect r(150, 150, 100, 100);
artifact.Chunk(t0(), c0(), *aa).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), c0(), *ab).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), c0(), *b).RectDrawing(r, Color::kWhite);
@@ -4273,12 +4399,10 @@ TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfacesWithBackdropChildren) {
auto a = CreateOpacityEffect(*e, 0.5f);
CompositorFilterOperations blur_filter;
blur_filter.AppendBlurFilter(5);
- auto bd = CreateBackdropFilterEffect(
- *a, blur_filter, FloatPoint(),
- CompositingReason::kActiveBackdropFilterAnimation);
+ auto bd = CreateBackdropFilterEffect(*a, blur_filter, FloatPoint());
TestPaintArtifact artifact;
- FloatRect r(150, 150, 100, 100);
+ IntRect r(150, 150, 100, 100);
artifact.Chunk(t0(), c0(), *a).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), c0(), *bd).RectDrawing(r, Color::kWhite);
Update(artifact.Build());
@@ -4292,12 +4416,11 @@ TEST_P(PaintArtifactCompositorTest,
DirectTransformAnimationCausesRenderSurfaceFor2dAxisMisalignedClip) {
// When a clip is affected by an animated transform, we should get a render
// surface for the effect node.
- auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
- CompositingReason::kActiveTransformAnimation);
+ auto t1 = CreateAnimatingTransform(t0());
auto e1 = CreateOpacityEffect(e0(), *t1, nullptr, 1.f);
auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(50, 50, 50, 50));
TestPaintArtifact artifact;
- FloatRect r(150, 150, 100, 100);
+ IntRect r(150, 150, 100, 100);
artifact.Chunk(t0(), c0(), e0()).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), *c1, *e1).RectDrawing(r, Color::kWhite);
Update(artifact.Build());
@@ -4312,13 +4435,12 @@ TEST_P(PaintArtifactCompositorTest,
IndirectTransformAnimationCausesRenderSurfaceFor2dAxisMisalignedClip) {
// When a clip is affected by an animated transform, we should get a render
// surface for the effect node.
- auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
- CompositingReason::kActiveTransformAnimation);
+ auto t1 = CreateAnimatingTransform(t0());
auto t2 = Create2DTranslation(*t1, 10, 20);
auto e1 = CreateOpacityEffect(e0(), *t2, nullptr, 1.f);
auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(50, 50, 50, 50));
TestPaintArtifact artifact;
- FloatRect r(150, 150, 100, 100);
+ IntRect r(150, 150, 100, 100);
artifact.Chunk(t0(), c0(), e0()).RectDrawing(r, Color::kWhite);
artifact.Chunk(t0(), *c1, *e1).RectDrawing(r, Color::kWhite);
Update(artifact.Build());
@@ -4338,9 +4460,9 @@ TEST_P(PaintArtifactCompositorTest, OpacityIndirectlyAffectingTwoLayers) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *child_composited_effect)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
artifact.Chunk(t0(), c0(), *grandchild_composited_effect)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -4364,9 +4486,9 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *child_composited_effect)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite);
artifact.Chunk(t0(), c0(), *grandchild_composited_effect)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kGray);
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(2u, LayerCount());
@@ -4399,7 +4521,7 @@ TEST_P(PaintArtifactCompositorTest,
Update(TestPaintArtifact()
.Chunk(t0(), c0(), *e1)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite)
.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_OPACITY(LayerAt(0)->effect_tree_index(), 1.f, kNoRenderSurface);
@@ -4412,7 +4534,7 @@ TEST_P(PaintArtifactCompositorTest, FilterCreatesRenderSurface) {
CompositingReason::kActiveFilterAnimation);
Update(TestPaintArtifact()
.Chunk(t0(), c0(), *e1)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite)
.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_OPACITY(LayerAt(0)->effect_tree_index(), 1.f, kHasRenderSurface);
@@ -4422,7 +4544,7 @@ TEST_P(PaintArtifactCompositorTest, FilterAnimationCreatesRenderSurface) {
auto e1 = CreateAnimatingFilterEffect(e0());
Update(TestPaintArtifact()
.Chunk(t0(), c0(), *e1)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite)
.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_OPACITY(LayerAt(0)->effect_tree_index(), 1.f, kHasRenderSurface);
@@ -4431,11 +4553,10 @@ TEST_P(PaintArtifactCompositorTest, FilterAnimationCreatesRenderSurface) {
TEST_P(PaintArtifactCompositorTest, BackdropFilterCreatesRenderSurface) {
CompositorFilterOperations filter;
filter.AppendBlurFilter(5);
- auto e1 = CreateBackdropFilterEffect(e0(), filter, FloatPoint(),
- CompositingReason::kBackdropFilter);
+ auto e1 = CreateBackdropFilterEffect(e0(), filter, FloatPoint());
Update(TestPaintArtifact()
.Chunk(t0(), c0(), *e1)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite)
.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_OPACITY(LayerAt(0)->effect_tree_index(), 1.f, kHasRenderSurface);
@@ -4446,7 +4567,7 @@ TEST_P(PaintArtifactCompositorTest,
auto e1 = CreateAnimatingBackdropFilterEffect(e0());
Update(TestPaintArtifact()
.Chunk(t0(), c0(), *e1)
- .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite)
+ .RectDrawing(IntRect(150, 150, 100, 100), Color::kWhite)
.Build());
ASSERT_EQ(1u, LayerCount());
EXPECT_OPACITY(LayerAt(0)->effect_tree_index(), 1.f, kHasRenderSurface);
@@ -4460,7 +4581,7 @@ TEST_P(PaintArtifactCompositorTest, Non2dAxisAlignedClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip, *opacity)
- .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ .RectDrawing(IntRect(50, 50, 50, 50), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4485,7 +4606,7 @@ TEST_P(PaintArtifactCompositorTest, Non2dAxisAlignedRoundedRectClip) {
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip, *opacity)
- .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ .RectDrawing(IntRect(50, 50, 50, 50), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4520,11 +4641,11 @@ TEST_P(PaintArtifactCompositorTest,
TestPaintArtifact artifact;
artifact.Chunk(t0(), c0(), *opacity)
- .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ .RectDrawing(IntRect(50, 50, 50, 50), Color::kWhite);
artifact.Chunk(*rotate1, c0(), *opacity)
- .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ .RectDrawing(IntRect(50, 50, 50, 50), Color::kWhite);
artifact.Chunk(*rotate2, *clip, *opacity)
- .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ .RectDrawing(IntRect(50, 50, 50, 50), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(3u, LayerCount());
@@ -4549,7 +4670,7 @@ TEST_P(PaintArtifactCompositorTest, TransformChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(*t2, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
cc::Layer* layer = LayerAt(0);
@@ -4564,7 +4685,7 @@ TEST_P(PaintArtifactCompositorTest, TransformChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(*t2, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4589,7 +4710,7 @@ TEST_P(PaintArtifactCompositorTest, TransformChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(*t2, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4611,7 +4732,7 @@ TEST_P(PaintArtifactCompositorTest, TransformChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(*t2, c0(), e0())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4631,7 +4752,7 @@ TEST_P(PaintArtifactCompositorTest, EffectChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(t0(), c0(), *e2)
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
cc::Layer* layer = LayerAt(0);
@@ -4650,7 +4771,7 @@ TEST_P(PaintArtifactCompositorTest, EffectChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(t0(), c0(), *e2)
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4678,7 +4799,7 @@ TEST_P(PaintArtifactCompositorTest, EffectChange) {
Update(TestPaintArtifact()
.Chunk(1)
.Properties(t0(), c0(), *e2)
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack)
+ .RectDrawing(IntRect(100, 100, 200, 100), Color::kBlack)
.Build());
ASSERT_EQ(1u, LayerCount());
@@ -4691,4 +4812,44 @@ TEST_P(PaintArtifactCompositorTest, EffectChange) {
->effect_changed);
}
+TEST_P(PaintArtifactCompositorTest, DirectlySetScrollOffset) {
+ CompositorElementId scroll_element_id = ScrollElementId(123);
+ auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
+ kNotScrollingOnMain, scroll_element_id);
+ auto scroll_translation = CreateScrollTranslation(
+ t0(), 7, 9, *scroll, CompositingReason::kWillChangeTransform);
+
+ TestPaintArtifact artifact;
+ CreateScrollableChunk(artifact, *scroll_translation, c0(), e0());
+ Update(artifact.Build());
+
+ auto& scroll_tree = GetPropertyTrees().scroll_tree;
+ auto* scroll_layer = ScrollableLayerAt(0);
+ auto* scroll_node = scroll_tree.FindNodeFromElementId(scroll_element_id);
+ auto& transform_tree = GetPropertyTrees().transform_tree;
+ auto* transform_node = transform_tree.Node(scroll_node->transform_id);
+ EXPECT_EQ(scroll_element_id, scroll_node->element_id);
+ EXPECT_EQ(scroll_element_id, scroll_layer->element_id());
+ EXPECT_EQ(scroll_node->id, scroll_layer->scroll_tree_index());
+ EXPECT_EQ(gfx::ScrollOffset(-7, -9),
+ scroll_tree.current_scroll_offset(scroll_element_id));
+ EXPECT_EQ(gfx::ScrollOffset(-7, -9), transform_node->scroll_offset);
+
+ auto& host = GetLayerTreeHost();
+ host.Composite(base::TimeTicks::Now(), true);
+ ASSERT_FALSE(host.LayersThatShouldPushProperties().contains(scroll_layer));
+ ASSERT_FALSE(host.proxy()->CommitRequested());
+ ASSERT_FALSE(transform_tree.needs_update());
+
+ ASSERT_TRUE(GetPaintArtifactCompositor().DirectlySetScrollOffset(
+ scroll_element_id, FloatPoint(-10, -20)));
+ EXPECT_TRUE(host.LayersThatShouldPushProperties().contains(scroll_layer));
+ EXPECT_TRUE(host.proxy()->CommitRequested());
+ EXPECT_EQ(gfx::ScrollOffset(-10, -20),
+ scroll_tree.current_scroll_offset(scroll_element_id));
+ // DirectlySetScrollOffset doesn't update transform node.
+ EXPECT_EQ(gfx::ScrollOffset(-7, -9), transform_node->scroll_offset);
+ EXPECT_FALSE(transform_tree.needs_update());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index 1bc279443be..7ea7c8ab662 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -158,7 +158,7 @@ class ConversionContext {
*current_transform_);
}
- void AppendRestore(size_t n) {
+ void AppendRestore(wtf_size_t n) {
cc_list_.StartPaint();
while (n--)
cc_list_.push<cc::RestoreOp>();
@@ -172,8 +172,7 @@ class ConversionContext {
// Ends the effect on the top of the state stack if the stack is not empty,
// and update the bounds of the SaveLayer[Alpha]Op of the effect.
void EndEffect();
- void UpdateEffectBounds(const base::Optional<FloatRect>&,
- const TransformPaintPropertyNode&);
+ void UpdateEffectBounds(const FloatRect&, const TransformPaintPropertyNode&);
// Starts a clip state by adjusting the transform state, applying
// |combined_clip_rect| which is combined from one or more consecutive clips,
@@ -244,7 +243,7 @@ class ConversionContext {
// Records the bounds of the effect which initiated the entry. Note that
// the effect is not |this->effect| (which is the previous effect), but the
// |current_effect_| when this entry is the top of the stack.
- base::Optional<FloatRect> bounds;
+ FloatRect bounds;
};
Vector<EffectBoundsInfo> effect_bounds_stack_;
@@ -278,6 +277,7 @@ void ConversionContext::TranslateForLayerOffsetOnce() {
}
void ConversionContext::SwitchToChunkState(const PaintChunk& chunk) {
+ TranslateForLayerOffsetOnce();
chunk_to_layer_mapper_.SwitchToChunk(chunk);
const auto& chunk_state = chunk.properties;
@@ -304,18 +304,21 @@ static bool CombineClip(const ClipPaintPropertyNode& clip,
return false;
// Don't combine two rounded clip rects.
- bool clip_is_rounded = clip.ClipRect().IsRounded();
+ bool clip_is_rounded = clip.PixelSnappedClipRect().IsRounded();
bool combined_is_rounded = combined_clip_rect.IsRounded();
if (clip_is_rounded && combined_is_rounded)
return false;
// If one is rounded and the other contains the rounded bounds, use the
// rounded as the combined.
- if (combined_is_rounded)
- return clip.ClipRect().Rect().Contains(combined_clip_rect.Rect());
+ if (combined_is_rounded) {
+ return clip.PixelSnappedClipRect().Rect().Contains(
+ combined_clip_rect.Rect());
+ }
if (clip_is_rounded) {
- if (combined_clip_rect.Rect().Contains(clip.ClipRect().Rect())) {
- combined_clip_rect = clip.ClipRect();
+ if (combined_clip_rect.Rect().Contains(
+ clip.PixelSnappedClipRect().Rect())) {
+ combined_clip_rect = clip.PixelSnappedClipRect();
return true;
}
return false;
@@ -323,8 +326,8 @@ static bool CombineClip(const ClipPaintPropertyNode& clip,
// The combined is the intersection if both are rectangular.
DCHECK(!combined_is_rounded && !clip_is_rounded);
- combined_clip_rect = FloatRoundedRect(
- Intersection(combined_clip_rect.Rect(), clip.ClipRect().Rect()));
+ combined_clip_rect = FloatRoundedRect(Intersection(
+ combined_clip_rect.Rect(), clip.PixelSnappedClipRect().Rect()));
return true;
}
@@ -380,9 +383,10 @@ void ConversionContext::SwitchToClip(
// Step 3: Now apply the list of clips in top-down order.
DCHECK(pending_clips.size());
- auto pending_combined_clip_rect = pending_clips.back()->ClipRect();
+ auto pending_combined_clip_rect =
+ pending_clips.back()->PixelSnappedClipRect();
const auto* lowest_combined_clip_node = pending_clips.back();
- for (size_t i = pending_clips.size() - 1; i--;) {
+ for (auto i = pending_clips.size() - 1; i--;) {
const auto* sub_clip = pending_clips[i];
if (CombineClip(*sub_clip, pending_combined_clip_rect)) {
// Continue to combine.
@@ -391,7 +395,7 @@ void ConversionContext::SwitchToClip(
// |sub_clip| can't be combined to previous clips. Output the current
// combined clip, and start new combination.
StartClip(pending_combined_clip_rect, *lowest_combined_clip_node);
- pending_combined_clip_rect = sub_clip->ClipRect();
+ pending_combined_clip_rect = sub_clip->PixelSnappedClipRect();
lowest_combined_clip_node = sub_clip;
}
}
@@ -493,7 +497,7 @@ void ConversionContext::SwitchToEffect(
}
// Step 3: Now apply the list of effects in top-down order.
- for (size_t i = pending_effects.size(); i--;) {
+ for (auto i = pending_effects.size(); i--;) {
const EffectPaintPropertyNode* sub_effect = pending_effects[i];
#if DCHECK_IS_ON()
if (!has_pre_cap_effect_hierarchy_issue)
@@ -538,9 +542,8 @@ void ConversionContext::StartEffect(const EffectPaintPropertyNode& effect) {
bool has_other_effects = effect.BlendMode() != SkBlendMode::kSrcOver ||
effect.GetColorFilter() != kColorFilterNone;
DCHECK(!has_filter || !(has_opacity || has_other_effects));
-
- // TODO(crbug.com/904592): Add support for non-composited backdrop-filter
- // here.
+ // We always composite backdrop filters.
+ DCHECK(effect.BackdropFilter().IsEmpty());
// Apply effects.
cc_list_.StartPaint();
@@ -590,25 +593,35 @@ void ConversionContext::StartEffect(const EffectPaintPropertyNode& effect) {
const ClipPaintPropertyNode* input_clip = current_clip_;
PushState(StateEntry::kEffect, saved_count);
effect_bounds_stack_.emplace_back(
- EffectBoundsInfo{save_layer_id, current_transform_, base::nullopt});
+ EffectBoundsInfo{save_layer_id, current_transform_});
current_clip_ = input_clip;
current_effect_ = &effect;
+
+ if (effect.Filter().HasReferenceFilter()) {
+ auto reference_box = effect.Filter().ReferenceBox();
+ reference_box.MoveBy(effect.FiltersOrigin());
+ effect_bounds_stack_.back().bounds = reference_box;
+ if (current_effect_->Filter().HasReferenceFilter()) {
+ // Emit an empty paint operation to add the filter's source bounds (mapped
+ // to layer space) to the visual rect of the filter's SaveLayerOp.
+ cc_list_.StartPaint();
+ cc_list_.EndPaintOfUnpaired(chunk_to_layer_mapper_.MapVisualRect(
+ EnclosingIntRect(reference_box)));
+ }
+ }
}
void ConversionContext::UpdateEffectBounds(
- const base::Optional<FloatRect>& bounds,
+ const FloatRect& bounds,
const TransformPaintPropertyNode& transform) {
- if (effect_bounds_stack_.IsEmpty() || !bounds)
+ if (effect_bounds_stack_.IsEmpty() || bounds.IsEmpty())
return;
auto& effect_bounds_info = effect_bounds_stack_.back();
- FloatRect mapped_bounds = *bounds;
+ FloatRect mapped_bounds = bounds;
GeometryMapper::SourceToDestinationRect(
transform, *effect_bounds_info.transform, mapped_bounds);
- if (effect_bounds_info.bounds)
- effect_bounds_info.bounds->Unite(mapped_bounds);
- else
- effect_bounds_info.bounds = mapped_bounds;
+ effect_bounds_info.bounds.Unite(mapped_bounds);
}
void ConversionContext::EndEffect() {
@@ -622,21 +635,21 @@ void ConversionContext::EndEffect() {
DCHECK(effect_bounds_stack_.size());
const auto& bounds_info = effect_bounds_stack_.back();
- base::Optional<FloatRect> bounds = bounds_info.bounds;
- if (bounds) {
- if (current_effect_->Filter().IsEmpty()) {
- cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id, *bounds);
- } else {
- // The bounds for the SaveLayer[Alpha]Op should be the source bounds
- // before the filter is applied, in the space of the TranslateOp which was
- // emitted before the SaveLayer[Alpha]Op.
- auto save_layer_bounds = *bounds;
+ FloatRect bounds = bounds_info.bounds;
+ if (current_effect_->Filter().IsEmpty()) {
+ if (!bounds.IsEmpty())
+ cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id, bounds);
+ } else {
+ // The bounds for the SaveLayer[Alpha]Op should be the source bounds
+ // before the filter is applied, in the space of the TranslateOp which was
+ // emitted before the SaveLayer[Alpha]Op.
+ auto save_layer_bounds = bounds;
+ if (!save_layer_bounds.IsEmpty())
save_layer_bounds.MoveBy(-current_effect_->FiltersOrigin());
- cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id,
- save_layer_bounds);
- // We need to propagate the filtered bounds to the parent.
- bounds = current_effect_->MapRect(*bounds);
- }
+ cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id,
+ save_layer_bounds);
+ // We need to propagate the filtered bounds to the parent.
+ bounds = current_effect_->MapRect(bounds);
}
effect_bounds_stack_.pop_back();
@@ -732,17 +745,16 @@ void ConversionContext::Convert(const PaintChunkSubset& paint_chunks,
else
continue;
- // If we have an empty paint record, then we would prefer not to draw it.
- // However, if we also have a non-root effect, it means that the filter
- // applied might draw something even if the record is empty. We need to
- // "draw" this record in order to ensure that the effect has correct
- // visual rects.
+ // If we have an empty paint record, then we would prefer ignoring it.
+ // However, if we also have a non-root effect, the empty paint record
+ // might be for a mask with empty content which should make the masked
+ // content fully invisible. We need to "draw" this record to ensure that
+ // the effect has correct visual rect.
if ((!record || record->size() == 0) &&
&chunk_state.Effect() == &EffectPaintPropertyNode::Root()) {
continue;
}
- TranslateForLayerOffsetOnce();
if (!switched_to_chunk_state) {
SwitchToChunkState(chunk);
switched_to_chunk_state = true;
@@ -755,16 +767,17 @@ void ConversionContext::Convert(const PaintChunkSubset& paint_chunks,
chunk_to_layer_mapper_.MapVisualRect(item.VisualRect()));
}
- // Chunk bounds are only important when we are actually drawing. There may
- // also be cases when we only generate a paint record and do not draw,
- // for example, to implement an SVG clip. In such cases, we can safely
- // ignore effect bounds.
- base::Optional<FloatRect> chunk_bounds;
- if (cc_list_.GetUsageHint() ==
- cc::DisplayItemList::kTopLevelDisplayItemList) {
- chunk_bounds = FloatRect(chunk.bounds);
- }
- UpdateEffectBounds(chunk_bounds, chunk_state.Transform());
+ // If we have an empty paint chunk, then we would prefer ignoring it.
+ // However, a reference filter can generate visible effect from invisible
+ // source, and we need to emit paint operations for it.
+ if (!switched_to_chunk_state && &chunk_state.Effect() != current_effect_)
+ SwitchToChunkState(chunk);
+
+ // Most effects apply to drawable contents only. Reference filters are
+ // exceptions, for which we have already added the reference box to the
+ // bounds of the effect in StartEffect().
+ UpdateEffectBounds(FloatRect(chunk.drawable_bounds),
+ chunk_state.Transform());
}
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
index 7953f485235..1291b765dde 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -7,6 +7,7 @@
#include <initializer_list>
#include "cc/paint/display_item_list.h"
+#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_op_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -101,7 +102,7 @@ class PaintRecordMatcher
Vector<cc::PaintOpType> expected_ops_;
};
-#define EXPECT_EFFECT_BOUNDS(rect, op_buffer, index) \
+#define EXPECT_EFFECT_BOUNDS(x, y, width, height, op_buffer, index) \
do { \
FloatRect bounds; \
if (const auto* save_layer_alpha = \
@@ -113,7 +114,7 @@ class PaintRecordMatcher
} else { \
FAIL() << "No SaveLayer[Alpha]Op at " << index; \
} \
- EXPECT_EQ(rect, bounds); \
+ EXPECT_EQ(FloatRect(x, y, width, height), bounds); \
} while (false)
#define EXPECT_TRANSFORM_MATRIX(transform, op_buffer, index) \
@@ -160,32 +161,45 @@ struct TestChunks {
DisplayItemList items = DisplayItemList(0);
// Add a paint chunk with a non-empty paint record and given property nodes.
- void AddChunk(const TransformPaintPropertyNode& t,
- const ClipPaintPropertyNode& c,
- const EffectPaintPropertyNode& e,
- const IntRect& bounds = IntRect(0, 0, 100, 100)) {
+ void AddChunk(
+ const TransformPaintPropertyNode& t,
+ const ClipPaintPropertyNode& c,
+ const EffectPaintPropertyNode& e,
+ const IntRect& bounds = IntRect(0, 0, 100, 100),
+ const base::Optional<IntRect>& drawable_bounds = base::nullopt) {
auto record = sk_make_sp<PaintRecord>();
- record->push<cc::DrawRectOp>(bounds, cc::PaintFlags());
- AddChunk(std::move(record), t, c, e, bounds);
+ record->push<cc::DrawRectOp>(drawable_bounds ? *drawable_bounds : bounds,
+ cc::PaintFlags());
+ AddChunk(std::move(record), t, c, e, bounds, drawable_bounds);
}
// Add a paint chunk with a given paint record and property nodes.
- void AddChunk(sk_sp<PaintRecord> record,
- const TransformPaintPropertyNode& t,
- const ClipPaintPropertyNode& c,
- const EffectPaintPropertyNode& e,
- const IntRect& bounds = IntRect(0, 0, 100, 100)) {
- size_t i = items.size();
+ void AddChunk(
+ sk_sp<PaintRecord> record,
+ const TransformPaintPropertyNode& t,
+ const ClipPaintPropertyNode& c,
+ const EffectPaintPropertyNode& e,
+ const IntRect& bounds = IntRect(0, 0, 100, 100),
+ const base::Optional<IntRect>& drawable_bounds = base::nullopt) {
+ auto i = items.size();
items.AllocateAndConstruct<DrawingDisplayItem>(
DefaultId().client, DefaultId().type, std::move(record));
+ if (drawable_bounds)
+ items.Last().SetVisualRectForTesting(*drawable_bounds);
chunks.emplace_back(i, i + 1, DefaultId(), PropertyTreeState(t, c, e));
chunks.back().bounds = bounds;
+ chunks.back().drawable_bounds = drawable_bounds ? *drawable_bounds : bounds;
}
-};
-const cc::DisplayItemList::UsageHint kUsageHints[] = {
- cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer,
- cc::DisplayItemList::kTopLevelDisplayItemList};
+ void AddEmptyChunk(const TransformPaintPropertyNode& t,
+ const ClipPaintPropertyNode& c,
+ const EffectPaintPropertyNode& e,
+ const IntRect& bounds = IntRect(0, 0, 100, 100)) {
+ auto i = items.size();
+ chunks.emplace_back(i, i, DefaultId(), PropertyTreeState(t, c, e));
+ chunks.back().bounds = bounds;
+ }
+};
TEST_P(PaintChunksToCcLayerTest, EffectGroupingSimple) {
// This test verifies effects are applied as a group.
@@ -194,23 +208,18 @@ TEST_P(PaintChunksToCcLayerTest, EffectGroupingSimple) {
chunks.AddChunk(t0(), c0(), *e1, IntRect(0, 0, 50, 50));
chunks.AddChunk(t0(), c0(), *e1, IntRect(20, 20, 70, 70));
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 90, 90)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::DrawRecord, // <p1/>
- cc::PaintOpType::Restore})); // </e1>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 0);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::DrawRecord, // <p1/>
+ cc::PaintOpType::Restore})); // </e1>
+ EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, *output, 0);
}
TEST_P(PaintChunksToCcLayerTest, EffectGroupingNested) {
@@ -222,39 +231,30 @@ TEST_P(PaintChunksToCcLayerTest, EffectGroupingNested) {
chunks.AddChunk(t0(), c0(), *e2);
chunks.AddChunk(t0(), c0(), *e3, IntRect(111, 222, 333, 444));
- const FloatRect kExpectedBounds1[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 444, 666)};
- const FloatRect kExpectedBounds2[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
- const FloatRect kExpectedBounds3[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(111, 222, 333, 444)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::SaveLayerAlpha, // <e2>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore, // </e2>
- cc::PaintOpType::SaveLayerAlpha, // <e3>
- cc::PaintOpType::DrawRecord, // <p1/>
- cc::PaintOpType::Restore, // </e3>
- cc::PaintOpType::Restore})); // </e1>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds1[hint], *output, 0);
- EXPECT_EFFECT_BOUNDS(kExpectedBounds2[hint], *output, 1);
- EXPECT_EFFECT_BOUNDS(kExpectedBounds3[hint], *output, 4);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::SaveLayerAlpha, // <e2>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore, // </e2>
+ cc::PaintOpType::SaveLayerAlpha, // <e3>
+ cc::PaintOpType::DrawRecord, // <p1/>
+ cc::PaintOpType::Restore, // </e3>
+ cc::PaintOpType::Restore})); // </e1>
+ EXPECT_EFFECT_BOUNDS(0, 0, 444, 666, *output, 0);
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 1);
+ EXPECT_EFFECT_BOUNDS(111, 222, 333, 444, *output, 4);
}
TEST_P(PaintChunksToCcLayerTest, EffectFilterGroupingNestedWithTransforms) {
// This test verifies nested effects with transforms are grouped properly.
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto t2 = CreateTransform(*t1, TransformationMatrix().Translate(-50, -50));
+ auto t2 = Create2DTranslation(*t1, -50, -50);
auto e1 = CreateOpacityEffect(e0(), *t2, &c0(), 0.5);
CompositorFilterOperations filter;
@@ -264,47 +264,40 @@ TEST_P(PaintChunksToCcLayerTest, EffectFilterGroupingNestedWithTransforms) {
chunks.AddChunk(*t2, c0(), *e1, IntRect(0, 0, 50, 50));
chunks.AddChunk(*t1, c0(), *e2, IntRect(20, 20, 70, 70));
- const FloatRect kExpectedBounds1[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 155, 155)};
- const FloatRect kExpectedBounds2[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(10, 10, 70, 70)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make(
- {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1*t2>
- cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::DrawRecord, // <p1/>
- cc::PaintOpType::Save, cc::PaintOpType::Translate, // <e2_offset>
- cc::PaintOpType::SaveLayer, // <e2>
- cc::PaintOpType::Translate, // <e2_offset^-1/>
- cc::PaintOpType::Save, cc::PaintOpType::Translate, // <t2^-1>
- cc::PaintOpType::DrawRecord, // <p2/>
- cc::PaintOpType::Restore, // </t2^-1>
- cc::PaintOpType::Restore, // </e2>
- cc::PaintOpType::Restore, // </e2_offset>
- cc::PaintOpType::Restore, // </e1>
- cc::PaintOpType::Restore})); // </t1*t2>
- EXPECT_TRANSFORM_MATRIX(t1->Matrix() * t2->SlowMatrix(), *output, 1);
- // chunk1.bounds + e2(t2^-1(chunk2.bounds))
- EXPECT_EFFECT_BOUNDS(kExpectedBounds1[hint], *output, 2);
- // e2_offset
- EXPECT_TRANSLATE(60, 60, *output, 5);
- // t2^-1(chunk2.bounds) - e2_offset
- EXPECT_EFFECT_BOUNDS(kExpectedBounds2[hint], *output, 6);
- // -e2_offset
- EXPECT_TRANSLATE(-e2->FiltersOrigin().X(), -e2->FiltersOrigin().Y(),
- *output, 7);
- // t2^1
- EXPECT_TRANSLATE(-t2->Translation2D().Width(),
- -t2->Translation2D().Height(), *output, 9);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make(
+ {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1*t2>
+ cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::DrawRecord, // <p1/>
+ cc::PaintOpType::Save, cc::PaintOpType::Translate, // <e2_offset>
+ cc::PaintOpType::SaveLayer, // <e2>
+ cc::PaintOpType::Translate, // <e2_offset^-1/>
+ cc::PaintOpType::Save, cc::PaintOpType::Translate, // <t2^-1>
+ cc::PaintOpType::DrawRecord, // <p2/>
+ cc::PaintOpType::Restore, // </t2^-1>
+ cc::PaintOpType::Restore, // </e2>
+ cc::PaintOpType::Restore, // </e2_offset>
+ cc::PaintOpType::Restore, // </e1>
+ cc::PaintOpType::Restore})); // </t1*t2>
+ EXPECT_TRANSFORM_MATRIX(t1->Matrix() * t2->SlowMatrix(), *output, 1);
+ // chunk1.bounds + e2(t2^-1(chunk2.bounds))
+ EXPECT_EFFECT_BOUNDS(0, 0, 155, 155, *output, 2);
+ // e2_offset
+ EXPECT_TRANSLATE(60, 60, *output, 5);
+ // t2^-1(chunk2.bounds) - e2_offset
+ EXPECT_EFFECT_BOUNDS(10, 10, 70, 70, *output, 6);
+ // -e2_offset
+ EXPECT_TRANSLATE(-e2->FiltersOrigin().X(), -e2->FiltersOrigin().Y(), *output,
+ 7);
+ // t2^1
+ EXPECT_TRANSLATE(-t2->Translation2D().Width(), -t2->Translation2D().Height(),
+ *output, 9);
}
TEST_P(PaintChunksToCcLayerTest, InterleavedClipEffect) {
@@ -326,45 +319,38 @@ TEST_P(PaintChunksToCcLayerTest, InterleavedClipEffect) {
chunks.AddChunk(t0(), *c3, *e1, IntRect(20, 20, 70, 70));
chunks.AddChunk(t0(), *c4, e0());
- const FloatRect kExpectedBounds1[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 90, 90)};
- const FloatRect kExpectedBounds2[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 50, 50)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(*output, PaintRecordMatcher::Make(
- {cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c1+c2>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c3>
- cc::PaintOpType::DrawRecord, // <p1/>
- cc::PaintOpType::Restore, // </c3>
- cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c3+c4>
- cc::PaintOpType::SaveLayerAlpha, // <e2>
- cc::PaintOpType::DrawRecord, // <p2/>
- cc::PaintOpType::Restore, // </e2>
- cc::PaintOpType::Restore, // </c3+c4>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c3>
- cc::PaintOpType::DrawRecord, // <p3/>
- cc::PaintOpType::Restore, // </c3>
- cc::PaintOpType::Restore, // </e1>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c3+c4>
- cc::PaintOpType::DrawRecord, // <p4/>
- cc::PaintOpType::Restore, // </c3+c4>
- cc::PaintOpType::Restore})); // </c1+c2>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds1[hint], *output, 7);
- EXPECT_EFFECT_BOUNDS(kExpectedBounds2[hint], *output, 10);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(*output, PaintRecordMatcher::Make(
+ {cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c1+c2>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c3>
+ cc::PaintOpType::DrawRecord, // <p1/>
+ cc::PaintOpType::Restore, // </c3>
+ cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c3+c4>
+ cc::PaintOpType::SaveLayerAlpha, // <e2>
+ cc::PaintOpType::DrawRecord, // <p2/>
+ cc::PaintOpType::Restore, // </e2>
+ cc::PaintOpType::Restore, // </c3+c4>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c3>
+ cc::PaintOpType::DrawRecord, // <p3/>
+ cc::PaintOpType::Restore, // </c3>
+ cc::PaintOpType::Restore, // </e1>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c3+c4>
+ cc::PaintOpType::DrawRecord, // <p4/>
+ cc::PaintOpType::Restore, // </c3+c4>
+ cc::PaintOpType::Restore})); // </c1+c2>
+ EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, *output, 7);
+ EXPECT_EFFECT_BOUNDS(0, 0, 50, 50, *output, 10);
}
TEST_P(PaintChunksToCcLayerTest, ClipSpaceInversion) {
@@ -407,29 +393,24 @@ TEST_P(PaintChunksToCcLayerTest, OpacityEffectSpaceInversion) {
chunks.AddChunk(t0(), c0(), *e1);
chunks.AddChunk(*t1, c0(), *e1);
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(*output,
- PaintRecordMatcher::Make(
- {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1>
- cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1^-1>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore, // </t1^-1>
- cc::PaintOpType::DrawRecord, // <p1/>
- cc::PaintOpType::Restore, // </e1>
- cc::PaintOpType::Restore})); // </t1>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 2);
- EXPECT_TRANSFORM_MATRIX(t1->Matrix(), *output, 1);
- EXPECT_TRANSFORM_MATRIX(t1->Matrix().Inverse(), *output, 4);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(*output,
+ PaintRecordMatcher::Make(
+ {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1>
+ cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1^-1>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore, // </t1^-1>
+ cc::PaintOpType::DrawRecord, // <p1/>
+ cc::PaintOpType::Restore, // </e1>
+ cc::PaintOpType::Restore})); // </t1>
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 2);
+ EXPECT_TRANSFORM_MATRIX(t1->Matrix(), *output, 1);
+ EXPECT_TRANSFORM_MATRIX(t1->Matrix().Inverse(), *output, 4);
}
TEST_P(PaintChunksToCcLayerTest, FilterEffectSpaceInversion) {
@@ -447,33 +428,29 @@ TEST_P(PaintChunksToCcLayerTest, FilterEffectSpaceInversion) {
TestChunks chunks;
chunks.AddChunk(t0(), c0(), *e1);
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(-66, -88, 50, 50)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- auto output = PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items, kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make(
- {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1>
- cc::PaintOpType::Save, cc::PaintOpType::Translate, // <e1_offset>
- cc::PaintOpType::SaveLayer, // <e1>
- cc::PaintOpType::Translate, // <e1_offset^-1/>
- cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1^-1>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore, // </t1^-1>
- cc::PaintOpType::Restore, // </e1>
- cc::PaintOpType::Restore, // </e1_offset>
- cc::PaintOpType::Restore})); // </t1>
- EXPECT_TRANSFORM_MATRIX(t1->Matrix(), *output, 1);
- EXPECT_TRANSLATE(66, 88, *output, 3);
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 4);
- EXPECT_TRANSLATE(-66, -88, *output, 5);
- EXPECT_TRANSFORM_MATRIX(t1->Matrix().Inverse(), *output, 7);
- }
+ auto output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make(
+ {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1>
+ cc::PaintOpType::Save, cc::PaintOpType::Translate, // <e1_offset>
+ cc::PaintOpType::SaveLayer, // <e1>
+ cc::PaintOpType::Translate, // <e1_offset^-1/>
+ cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1^-1>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore, // </t1^-1>
+ cc::PaintOpType::Restore, // </e1>
+ cc::PaintOpType::Restore, // </e1_offset>
+ cc::PaintOpType::Restore})); // </t1>
+ EXPECT_TRANSFORM_MATRIX(t1->Matrix(), *output, 1);
+ EXPECT_TRANSLATE(66, 88, *output, 3);
+ EXPECT_EFFECT_BOUNDS(-66, -88, 50, 50, *output, 4);
+ EXPECT_TRANSLATE(-66, -88, *output, 5);
+ EXPECT_TRANSFORM_MATRIX(t1->Matrix().Inverse(), *output, 7);
}
TEST_P(PaintChunksToCcLayerTest, NonRootLayerSimple) {
@@ -523,25 +500,20 @@ TEST_P(PaintChunksToCcLayerTest, EffectWithNoOutputClip) {
TestChunks chunks;
chunks.AddChunk(t0(), *c2, *e1);
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), *c1, e0()), gfx::Vector2dF(),
- chunks.items, kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c2>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore, // </c2>
- cc::PaintOpType::Restore})); // </e1>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 0);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState(t0(), *c1, e0()), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c2>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore, // </c2>
+ cc::PaintOpType::Restore})); // </e1>
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
}
TEST_P(PaintChunksToCcLayerTest,
@@ -553,30 +525,23 @@ TEST_P(PaintChunksToCcLayerTest,
TestChunks chunks;
chunks.AddChunk(t0(), *c1, *e2);
- const FloatRect kExpectedBounds1[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
- const FloatRect kExpectedBounds2[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::SaveLayerAlpha, // <e2>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c1>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore, // </c1>
- cc::PaintOpType::Restore, // </e2>
- cc::PaintOpType::Restore})); // </e1>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds1[hint], *output, 0);
- EXPECT_EFFECT_BOUNDS(kExpectedBounds2[hint], *output, 1);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::SaveLayerAlpha, // <e2>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c1>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore, // </c1>
+ cc::PaintOpType::Restore, // </e2>
+ cc::PaintOpType::Restore})); // </e1>
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 1);
}
TEST_P(PaintChunksToCcLayerTest,
@@ -588,25 +553,20 @@ TEST_P(PaintChunksToCcLayerTest,
TestChunks chunks;
chunks.AddChunk(t0(), *c1, *e2);
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), *e1), gfx::Vector2dF(),
- chunks.items, kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e2>
- cc::PaintOpType::Save,
- cc::PaintOpType::ClipRect, // <c1>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore, // </c1>
- cc::PaintOpType::Restore})); // </e2>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 0);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState(t0(), c0(), *e1), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e2>
+ cc::PaintOpType::Save,
+ cc::PaintOpType::ClipRect, // <c1>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore, // </c1>
+ cc::PaintOpType::Restore})); // </e2>
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
}
TEST_P(PaintChunksToCcLayerTest,
@@ -618,29 +578,23 @@ TEST_P(PaintChunksToCcLayerTest,
TestChunks chunks;
chunks.AddChunk(t0(), *c1, *e2);
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), *c1, *e1), gfx::Vector2dF(),
- chunks.items, kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(
- *output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e2>
- cc::PaintOpType::DrawRecord, // <p0/>
- cc::PaintOpType::Restore})); // </e2>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 0);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState(t0(), *c1, *e1), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(
+ *output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha, // <e2>
+ cc::PaintOpType::DrawRecord, // <p0/>
+ cc::PaintOpType::Restore})); // </e2>
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
}
TEST_P(PaintChunksToCcLayerTest, VisualRect) {
auto layer_transform =
CreateTransform(t0(), TransformationMatrix().Scale(20));
- auto chunk_transform = CreateTransform(
- *layer_transform, TransformationMatrix().Translate(50, 100));
+ auto chunk_transform = Create2DTranslation(*layer_transform, 50, 100);
TestChunks chunks;
chunks.AddChunk(*chunk_transform, c0(), e0());
@@ -751,22 +705,17 @@ TEST_P(PaintChunksToCcLayerTest, EmptyEffectsAreStored) {
chunks.AddChunk(nullptr, t0(), c0(), e0());
chunks.AddChunk(nullptr, t0(), c0(), *e1);
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 100, 100)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- sk_sp<PaintRecord> output =
- PaintChunksToCcLayer::Convert(chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items,
- kUsageHints[hint])
- ->ReleaseAsRecord();
-
- EXPECT_THAT(*output, PaintRecordMatcher::Make({
- cc::PaintOpType::SaveLayerAlpha, // <e1>
- cc::PaintOpType::Restore, // </e1>
- }));
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 0);
- }
+ sk_sp<PaintRecord> output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+
+ EXPECT_THAT(*output, PaintRecordMatcher::Make({
+ cc::PaintOpType::SaveLayerAlpha, // <e1>
+ cc::PaintOpType::Restore, // </e1>
+ }));
+ EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
}
TEST_P(PaintChunksToCcLayerTest, CombineClips) {
@@ -808,7 +757,7 @@ TEST_P(PaintChunksToCcLayerTest, CombineClips) {
TEST_P(PaintChunksToCcLayerTest, CombineClipsAcrossTransform) {
FloatRoundedRect clip_rect(0, 0, 100, 100);
- auto identity = CreateTransform(t0(), TransformationMatrix());
+ auto identity = Create2DTranslation(t0(), 0, 0);
auto non_identity =
CreateTransform(*identity, TransformationMatrix().Scale(2));
auto non_invertible =
@@ -935,9 +884,9 @@ TEST_P(PaintChunksToCcLayerTest, ChunksSamePropertyTreeState) {
}
TEST_P(PaintChunksToCcLayerTest, NoOpForIdentityTransforms) {
- auto t1 = CreateTransform(t0(), TransformationMatrix());
- auto t2 = CreateTransform(*t1, TransformationMatrix());
- auto t3 = CreateTransform(*t2, TransformationMatrix());
+ auto t1 = Create2DTranslation(t0(), 0, 0);
+ auto t2 = Create2DTranslation(*t1, 0, 0);
+ auto t3 = Create2DTranslation(*t2, 0, 0);
auto c1 = CreateClip(c0(), *t2, FloatRoundedRect(0, 0, 100, 100));
auto c2 = CreateClip(*c1, *t3, FloatRoundedRect(0, 0, 200, 50));
@@ -1381,27 +1330,105 @@ TEST_P(PaintChunksToCcLayerTest, AllowChunkEscapeLayerNoopEffects) {
}));
}
-// https://crbug.com/918240
-TEST_P(PaintChunksToCcLayerTest, EmptyChunkRectDoesntTurnToUnsetOne) {
+TEST_P(PaintChunksToCcLayerTest, EmptyChunkRect) {
CompositorFilterOperations filter;
filter.AppendBlurFilter(5);
auto e1 = CreateFilterEffect(e0(), t0(), &c0(), filter, FloatPoint(0, 0));
TestChunks chunks;
chunks.AddChunk(nullptr, t0(), c0(), *e1, {0, 0, 0, 0});
- const FloatRect kExpectedBounds[] = {FloatRect(cc::PaintOp::kUnsetRect),
- FloatRect(0, 0, 0, 0)};
-
- for (size_t hint = 0; hint < base::size(kUsageHints); ++hint) {
- auto output = PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState::Root(),
- gfx::Vector2dF(), chunks.items, kUsageHints[hint])
- ->ReleaseAsRecord();
- EXPECT_THAT(*output,
- PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer, // <e1>
- cc::PaintOpType::Restore})); // </e1>
- EXPECT_EFFECT_BOUNDS(kExpectedBounds[hint], *output, 0);
+ auto output =
+ PaintChunksToCcLayer::Convert(
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
+ chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
+ EXPECT_THAT(*output,
+ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer, // <e1>
+ cc::PaintOpType::Restore})); // </e1>
+ EXPECT_EFFECT_BOUNDS(0, 0, 0, 0, *output, 0);
+}
+
+TEST_P(PaintChunksToCcLayerTest, ReferenceFilterOnEmptyChunk) {
+ CompositorFilterOperations filter;
+ filter.AppendReferenceFilter(sk_make_sp<cc::RecordPaintFilter>(
+ sk_make_sp<cc::PaintOpBuffer>(), SkRect::MakeIWH(100, 100)));
+ filter.SetReferenceBox(FloatRect(11, 22, 33, 44));
+ ASSERT_TRUE(filter.HasReferenceFilter());
+ auto e1 = CreateFilterEffect(e0(), t0(), &c0(), filter, FloatPoint(10, 20));
+ TestChunks chunks;
+ chunks.AddEmptyChunk(t0(), c0(), *e1, IntRect(0, 0, 200, 300));
+
+ auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
+ cc::DisplayItemList::kTopLevelDisplayItemList);
+ PaintChunksToCcLayer::ConvertInto(chunks.chunks, PropertyTreeState::Root(),
+ gfx::Vector2dF(5, 10), FloatSize(),
+ chunks.items, *cc_list);
+ ASSERT_EQ(9u, cc_list->TotalOpCount());
+ // (16 32) is (11, 22) + filter_offset - layer_offset.
+ gfx::Rect expected_visual_rect(16, 32, 33, 44);
+ for (size_t i = 0; i < cc_list->TotalOpCount(); i++) {
+ SCOPED_TRACE(testing::Message() << "Visual rect of op " << i);
+ EXPECT_EQ(expected_visual_rect, cc_list->VisualRectForTesting(i));
+ }
+
+ auto output = cc_list->ReleaseAsRecord();
+ EXPECT_THAT(*output,
+ PaintRecordMatcher::Make(
+ {cc::PaintOpType::Save,
+ cc::PaintOpType::Translate, // layer offset
+ cc::PaintOpType::Save, // <e1>
+ cc::PaintOpType::Translate, cc::PaintOpType::SaveLayer,
+ cc::PaintOpType::Translate, cc::PaintOpType::Restore,
+ cc::PaintOpType::Restore, // </e1>
+ cc::PaintOpType::Restore}));
+ EXPECT_EFFECT_BOUNDS(11, 22, 33, 44, *output, 4);
+}
+
+TEST_P(PaintChunksToCcLayerTest, ReferenceFilterOnChunkWithDrawingDisplayItem) {
+ CompositorFilterOperations filter;
+ filter.AppendReferenceFilter(sk_make_sp<cc::RecordPaintFilter>(
+ sk_make_sp<cc::PaintOpBuffer>(), SkRect::MakeIWH(100, 100)));
+ filter.SetReferenceBox(FloatRect(11, 22, 33, 44));
+ ASSERT_TRUE(filter.HasReferenceFilter());
+ auto e1 = CreateFilterEffect(e0(), t0(), &c0(), filter, FloatPoint(10, 20));
+ TestChunks chunks;
+ chunks.AddChunk(t0(), c0(), *e1, IntRect(5, 10, 200, 300),
+ IntRect(10, 15, 20, 30));
+
+ auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
+ cc::DisplayItemList::kTopLevelDisplayItemList);
+ PaintChunksToCcLayer::ConvertInto(chunks.chunks, PropertyTreeState::Root(),
+ gfx::Vector2dF(5, 10), FloatSize(),
+ chunks.items, *cc_list);
+ ASSERT_EQ(11u, cc_list->TotalOpCount());
+ // This is the visual rect for all filter related paint operations, which is
+ // the union of the draw record and reference box of the filter in the layer's
+ // space.
+ gfx::Rect expected_filter_visual_rect(5, 5, 44, 71);
+ // This is the visual rect of the DrawingDisplayItem in the layer's space.
+ gfx::Rect expected_draw_visual_rect(5, 5, 20, 30);
+ // TotalOpCount() - 1 because the DrawRecord op has a sub operation.
+ for (size_t i = 0; i < cc_list->TotalOpCount() - 1; i++) {
+ SCOPED_TRACE(testing::Message() << "Visual rect of op " << i);
+ EXPECT_EQ(i == 6 ? expected_draw_visual_rect : expected_filter_visual_rect,
+ cc_list->VisualRectForTesting(i));
}
+
+ auto output = cc_list->ReleaseAsRecord();
+ EXPECT_THAT(*output,
+ PaintRecordMatcher::Make(
+ {cc::PaintOpType::Save,
+ cc::PaintOpType::Translate, // layer offset
+ cc::PaintOpType::Save, //
+ cc::PaintOpType::Translate, // e1->FilterOrigin()
+ cc::PaintOpType::SaveLayer, // <e1>
+ cc::PaintOpType::Translate, // -e1->FilterOrigin()
+ cc::PaintOpType::DrawRecord, // the DrawingDisplayItem
+ cc::PaintOpType::Restore, // </e1>
+ cc::PaintOpType::Restore, cc::PaintOpType::Restore}));
+ // The effect bounds are the union of the chunk's drawable_bounds and the
+ // reference box in the filter's space.
+ EXPECT_EFFECT_BOUNDS(0, -5, 44, 71, *output, 4);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
index 757e737fa3b..07ded512b38 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -34,12 +34,6 @@ static constexpr int kSecondaryRootNodeId = 1;
} // namespace
-inline const TransformPaintPropertyNode&
-PropertyTreeManager::EffectState::Transform() const {
- return effect_type == CcEffectType::kEffect ? effect->LocalTransformSpace()
- : clip->LocalTransformSpace();
-}
-
PropertyTreeManager::PropertyTreeManager(
PropertyTreeManagerClient& client,
cc::PropertyTrees& property_trees,
@@ -113,9 +107,9 @@ static void SetTransformTreePageScaleFactor(
}
bool PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
- cc::PropertyTrees* property_trees,
cc::LayerTreeHost& host,
const EffectPaintPropertyNode& effect) {
+ auto* property_trees = host.property_trees();
auto* cc_effect = property_trees->effect_tree.Node(
effect.CcNodeId(property_trees->sequence_number));
if (!cc_effect)
@@ -134,7 +128,6 @@ bool PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
}
bool PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
- cc::PropertyTrees* property_trees,
cc::LayerTreeHost& host,
const TransformPaintPropertyNode& transform) {
auto* scroll_node = transform.ScrollNode();
@@ -142,6 +135,7 @@ bool PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
if (!scroll_node)
return false;
+ auto* property_trees = host.property_trees();
auto* cc_scroll_node = property_trees->scroll_tree.Node(
scroll_node->CcNodeId(property_trees->sequence_number));
if (!cc_scroll_node)
@@ -155,24 +149,22 @@ bool PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
DCHECK(!cc_transform->is_currently_animating);
UpdateCcTransformLocalMatrix(*cc_transform, transform);
- property_trees->scroll_tree.SetScrollOffset(
- scroll_node->GetCompositorElementId(), cc_transform->scroll_offset);
-
+ DirectlySetScrollOffset(host, scroll_node->GetCompositorElementId(),
+ cc_transform->scroll_offset);
cc_transform->transform_changed = true;
property_trees->transform_tree.set_needs_update(true);
- property_trees->scroll_tree.set_needs_update(true);
host.SetNeedsCommit();
return true;
}
bool PropertyTreeManager::DirectlyUpdateTransform(
- cc::PropertyTrees* property_trees,
cc::LayerTreeHost& host,
const TransformPaintPropertyNode& transform) {
// If we have a ScrollNode, we should be using
// DirectlyUpdateScrollOffsetTransform().
DCHECK(!transform.ScrollNode());
+ auto* property_trees = host.property_trees();
auto* cc_transform = property_trees->transform_tree.Node(
transform.CcNodeId(property_trees->sequence_number));
if (!cc_transform)
@@ -192,11 +184,11 @@ bool PropertyTreeManager::DirectlyUpdateTransform(
}
bool PropertyTreeManager::DirectlyUpdatePageScaleTransform(
- cc::PropertyTrees* property_trees,
cc::LayerTreeHost& host,
const TransformPaintPropertyNode& transform) {
DCHECK(!transform.ScrollNode());
+ auto* property_trees = host.property_trees();
auto* cc_transform = property_trees->transform_tree.Node(
transform.CcNodeId(property_trees->sequence_number));
if (!cc_transform)
@@ -211,6 +203,19 @@ bool PropertyTreeManager::DirectlyUpdatePageScaleTransform(
return true;
}
+// static
+void PropertyTreeManager::DirectlySetScrollOffset(
+ cc::LayerTreeHost& host,
+ CompositorElementId element_id,
+ const gfx::ScrollOffset& scroll_offset) {
+ auto* property_trees = host.property_trees();
+ if (property_trees->scroll_tree.SetScrollOffset(element_id, scroll_offset)) {
+ if (auto* layer = host.LayerByElementId(element_id))
+ layer->SetNeedsPushProperties();
+ host.SetNeedsCommit();
+ }
+}
+
cc::TransformTree& PropertyTreeManager::GetTransformTree() {
return property_trees_.transform_tree;
}
@@ -298,9 +303,9 @@ void PropertyTreeManager::SetupRootEffectNode() {
EffectPaintPropertyNode::Root().SetCcNodeId(new_sequence_number_,
effect_node.id);
- SetCurrentEffectState(effect_node, CcEffectType::kEffect,
- EffectPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root());
+ SetCurrentEffectState(
+ effect_node, CcEffectType::kEffect, EffectPaintPropertyNode::Root(),
+ ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root());
}
void PropertyTreeManager::SetupRootScrollNode() {
@@ -351,15 +356,17 @@ void PropertyTreeManager::SetCurrentEffectState(
const cc::EffectNode& cc_effect_node,
CcEffectType effect_type,
const EffectPaintPropertyNode& effect,
- const ClipPaintPropertyNode& clip) {
+ const ClipPaintPropertyNode& clip,
+ const TransformPaintPropertyNode& transform) {
const auto* previous_transform =
- effect.IsRoot() ? nullptr : &current_.Transform();
+ effect.IsRoot() ? nullptr : current_.transform;
current_.effect_id = cc_effect_node.id;
current_.effect_type = effect_type;
DCHECK(!effect.IsParentAlias() || !effect.Parent());
current_.effect = &effect;
DCHECK(!clip.IsParentAlias() || !clip.Parent());
current_.clip = &clip;
+ current_.transform = &transform;
if (cc_effect_node.HasRenderSurface()) {
current_.may_be_2d_axis_misaligned_to_render_surface =
@@ -368,7 +375,7 @@ void PropertyTreeManager::SetCurrentEffectState(
} else {
if (current_.may_be_2d_axis_misaligned_to_render_surface ==
EffectState::kAligned &&
- previous_transform != &current_.Transform()) {
+ previous_transform != current_.transform) {
current_.may_be_2d_axis_misaligned_to_render_surface =
EffectState::kUnknown;
}
@@ -422,7 +429,9 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
// cache a lookup of transform node to scroll translation transform node.
const auto& scroll_ancestor = transform_node.NearestScrollTranslationNode();
sticky_data.scroll_ancestor = EnsureCompositorScrollNode(scroll_ancestor);
- if (scroll_ancestor.ScrollNode()->ScrollsOuterViewport())
+ const auto& scroll_ancestor_compositor_node =
+ *GetScrollTree().Node(sticky_data.scroll_ancestor);
+ if (scroll_ancestor_compositor_node.scrolls_outer_viewport)
GetTransformTree().AddNodeAffectedByOuterViewportBoundsDelta(id);
if (auto shifting_sticky_box_element_id =
sticky_data.constraints.nearest_element_shifting_sticky_box) {
@@ -466,8 +475,8 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
transform_node.FlattensInheritedTransform() && transform_node.Parent() &&
transform_node.Parent()->RenderingContextId() &&
!transform_node.Parent()->FlattensInheritedTransform()) {
- SetCurrentEffectRenderSurfaceReason(
- cc::RenderSurfaceReason::k3dTransformFlattening);
+ current_cc_effect->render_surface_reason =
+ cc::RenderSurfaceReason::k3dTransformFlattening;
}
transform_node.SetCcNodeId(new_sequence_number_, id);
@@ -502,7 +511,7 @@ int PropertyTreeManager::EnsureCompositorClipNode(
cc::ClipNode& compositor_node = *GetClipTree().Node(id);
- compositor_node.clip = clip_node.ClipRect().Rect();
+ compositor_node.clip = clip_node.PixelSnappedClipRect().Rect();
compositor_node.transform_id =
EnsureCompositorTransformNode(clip_node.LocalTransformSpace());
compositor_node.clip_type = cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP;
@@ -534,15 +543,9 @@ void PropertyTreeManager::CreateCompositorScrollNode(
scroll_node.UserScrollableHorizontal();
compositor_node.user_scrollable_vertical =
scroll_node.UserScrollableVertical();
- compositor_node.scrolls_inner_viewport = scroll_node.ScrollsInnerViewport();
- compositor_node.scrolls_outer_viewport = scroll_node.ScrollsOuterViewport();
compositor_node.prevent_viewport_scrolling_from_inner =
scroll_node.PreventViewportScrollingFromInner();
- // |scrolls_using_viewport| should only ever be set on the inner scroll node.
- DCHECK(!compositor_node.prevent_viewport_scrolling_from_inner ||
- compositor_node.scrolls_inner_viewport);
-
compositor_node.max_scroll_offset_affected_by_page_scale =
scroll_node.MaxScrollOffsetAffectedByPageScale();
compositor_node.main_thread_scrolling_reasons =
@@ -562,13 +565,10 @@ void PropertyTreeManager::CreateCompositorScrollNode(
compositor_node.transform_id = scroll_offset_translation.id;
- // TODO(pdr): Set the scroll node's non_fast_scrolling_region value.
-
scroll_node.SetCcNodeId(new_sequence_number_, id);
GetScrollTree().SetScrollOffset(compositor_element_id,
scroll_offset_translation.scroll_offset);
- GetScrollTree().set_needs_update(true);
}
int PropertyTreeManager::EnsureCompositorScrollNode(
@@ -581,24 +581,38 @@ int PropertyTreeManager::EnsureCompositorScrollNode(
return id;
}
-void PropertyTreeManager::EmitClipMaskLayer() {
- cc::EffectNode& mask_isolation = *GetEffectTree().Node(current_.effect_id);
+int PropertyTreeManager::EnsureCompositorInnerScrollNode(
+ const TransformPaintPropertyNode& scroll_offset_translation) {
+ int node_id = EnsureCompositorScrollNode(scroll_offset_translation);
+ GetScrollTree().Node(node_id)->scrolls_inner_viewport = true;
+ return node_id;
+}
+int PropertyTreeManager::EnsureCompositorOuterScrollNode(
+ const TransformPaintPropertyNode& scroll_offset_translation) {
+ int node_id = EnsureCompositorScrollNode(scroll_offset_translation);
+ GetScrollTree().Node(node_id)->scrolls_outer_viewport = true;
+ return node_id;
+}
+
+void PropertyTreeManager::EmitClipMaskLayer() {
+ cc::EffectNode* mask_isolation = GetEffectTree().Node(current_.effect_id);
+ DCHECK(mask_isolation);
bool needs_layer =
- !pending_synthetic_mask_layers_.Contains(mask_isolation.id) &&
- mask_isolation.rounded_corner_bounds.IsEmpty();
+ !pending_synthetic_mask_layers_.Contains(mask_isolation->id) &&
+ mask_isolation->rounded_corner_bounds.IsEmpty();
int clip_id = EnsureCompositorClipNode(*current_.clip);
CompositorElementId mask_isolation_id, mask_effect_id;
SynthesizedClip& clip = client_.CreateOrReuseSynthesizedClipLayer(
- *current_.clip, needs_layer, mask_isolation_id, mask_effect_id);
+ *current_.clip, *current_.transform, needs_layer, mask_isolation_id,
+ mask_effect_id);
// Assignment of mask_isolation.stable_id was delayed until now.
// See PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded().
DCHECK_EQ(static_cast<uint64_t>(cc::EffectNode::INVALID_STABLE_ID),
- mask_isolation.stable_id);
-
- mask_isolation.stable_id = mask_isolation_id.GetStableId();
+ mask_isolation->stable_id);
+ mask_isolation->stable_id = mask_isolation_id.GetStableId();
if (!needs_layer)
return;
@@ -609,7 +623,11 @@ void PropertyTreeManager::EmitClipMaskLayer() {
mask_effect.clip_id = clip_id;
mask_effect.blend_mode = SkBlendMode::kDstIn;
- cc::Layer* mask_layer = clip.Layer();
+ // The address of mask_isolation may have changed when we insert
+ // |mask_effect| into the tree.
+ mask_isolation = GetEffectTree().Node(current_.effect_id);
+
+ cc::PictureLayer* mask_layer = clip.Layer();
const auto& clip_space = current_.clip->LocalTransformSpace();
layer_list_builder_.Add(mask_layer);
@@ -624,21 +642,29 @@ void PropertyTreeManager::EmitClipMaskLayer() {
mask_layer->SetScrollTreeIndex(scroll_id);
mask_layer->SetClipTreeIndex(clip_id);
mask_layer->SetEffectTreeIndex(mask_effect.id);
+
+ if (!mask_isolation->backdrop_filters.IsEmpty()) {
+ mask_layer->SetIsBackdropFilterMask(true);
+ auto element_id = CompositorElementIdFromUniqueObjectId(
+ mask_effect.stable_id, CompositorElementIdNamespace::kEffectMask);
+ mask_layer->SetElementId(element_id);
+ mask_isolation->backdrop_mask_element_id = element_id;
+ }
}
void PropertyTreeManager::CloseCcEffect() {
DCHECK(effect_stack_.size());
const auto& previous_state = effect_stack_.back();
- // An effect with exotic blending or backdrop-filter that is masked by a
- // synthesized clip must have its blending to the outermost synthesized clip.
+ // A backdrop effect (exotic blending or backdrop filter) that is masked by a
+ // synthesized clip must have its effect to the outermost synthesized clip.
// These operations need access to the backdrop of the enclosing effect. With
// the isolation for a synthesized clip, a blank backdrop will be seen.
- // Therefore the blending is delegated to the outermost synthesized clip, thus
- // the clip can't be shared with sibling layers, and must be closed now.
+ // Therefore the backdrop effect is delegated to the outermost synthesized
+ // clip, thus the clip can't be shared with sibling layers, and must be
+ // closed now.
bool clear_synthetic_effects =
- !IsCurrentCcEffectSynthetic() &&
- current_.effect->BlendMode() != SkBlendMode::kSrcOver;
+ !IsCurrentCcEffectSynthetic() && current_.effect->HasBackdropEffect();
// We are about to close an effect that was synthesized for isolating
// a clip mask. Now emit the actual clip mask that will be composited on
@@ -715,7 +741,7 @@ int PropertyTreeManager::SwitchToEffectNodeWithSynthesizedClip(
CloseCcEffect();
BuildEffectNodesRecursively(next_effect);
- SynthesizeCcEffectsForClipsIfNeeded(next_clip, SkBlendMode::kSrcOver);
+ SynthesizeCcEffectsForClipsIfNeeded(next_clip, /*next_effect*/ nullptr);
if (layer_draws_content)
pending_synthetic_mask_layers_.clear();
@@ -741,7 +767,7 @@ static bool IsNodeOnAncestorChain(const ClipPaintPropertyNode& find,
bool PropertyTreeManager::EffectStateMayBe2dAxisMisalignedToRenderSurface(
EffectState& state,
- size_t index) {
+ wtf_size_t index) {
if (state.may_be_2d_axis_misaligned_to_render_surface ==
EffectState::kUnknown) {
// The root effect has render surface, so it's always kAligned.
@@ -752,8 +778,8 @@ bool PropertyTreeManager::EffectStateMayBe2dAxisMisalignedToRenderSurface(
EffectState::kMisaligned;
} else {
state.may_be_2d_axis_misaligned_to_render_surface =
- TransformsMayBe2dAxisMisaligned(effect_stack_[index - 1].Transform(),
- current_.Transform())
+ TransformsMayBe2dAxisMisaligned(*effect_stack_[index - 1].transform,
+ *current_.transform)
? EffectState::kMisaligned
: EffectState::kAligned;
}
@@ -771,14 +797,14 @@ bool PropertyTreeManager::CurrentEffectMayBe2dAxisMisalignedToRenderSurface() {
PropertyTreeManager::CcEffectType PropertyTreeManager::SyntheticEffectType(
const ClipPaintPropertyNode& clip) {
unsigned effect_type = CcEffectType::kEffect;
- if (clip.ClipRect().IsRounded() || clip.ClipPath())
+ if (clip.PixelSnappedClipRect().IsRounded() || clip.ClipPath())
effect_type |= CcEffectType::kSyntheticForNonTrivialClip;
// Cc requires that a rectangluar clip is 2d-axis-aligned with the render
// surface to correctly apply the clip.
if (CurrentEffectMayBe2dAxisMisalignedToRenderSurface() ||
TransformsMayBe2dAxisMisaligned(clip.LocalTransformSpace(),
- current_.Transform()))
+ *current_.transform))
effect_type |= CcEffectType::kSyntheticFor2dAxisAlignment;
return static_cast<CcEffectType>(effect_type);
}
@@ -793,21 +819,26 @@ void PropertyTreeManager::ForceRenderSurfaceIfSyntheticRoundedCornerClip(
bool PropertyTreeManager::SupportsShaderBasedRoundedCorner(
const ClipPaintPropertyNode& clip,
- PropertyTreeManager::CcEffectType type) {
- if (!RuntimeEnabledFeatures::FastBorderRadiusEnabled())
- return false;
-
+ PropertyTreeManager::CcEffectType type,
+ const EffectPaintPropertyNode* next_effect) {
if (type & CcEffectType::kSyntheticFor2dAxisAlignment)
return false;
if (clip.ClipPath())
return false;
+ // Don't use shader based rounded corner if the next effect has backdrop
+ // filter and the clip is in different transform space, because we will use
+ // the effect's transform space for the mask isolation effect node.
+ if (next_effect && !next_effect->BackdropFilter().IsEmpty() &&
+ &next_effect->LocalTransformSpace() != &clip.LocalTransformSpace())
+ return false;
+
auto WidthAndHeightAreTheSame = [](const FloatSize& size) {
return size.Width() == size.Height();
};
- const FloatRoundedRect::Radii& radii = clip.ClipRect().GetRadii();
+ const FloatRoundedRect::Radii& radii = clip.PixelSnappedClipRect().GetRadii();
if (!WidthAndHeightAreTheSame(radii.TopLeft()) ||
!WidthAndHeightAreTheSame(radii.TopRight()) ||
!WidthAndHeightAreTheSame(radii.BottomRight()) ||
@@ -815,11 +846,10 @@ bool PropertyTreeManager::SupportsShaderBasedRoundedCorner(
return false;
}
- // Rounded corners that differ are not supported by the
- // CALayerOverlay system on Mac. Instead of letting it fall back
- // to the (worse for memory and battery) non-CALayerOverlay system
- // for such cases, fall back to a non-fast border-radius mask for
- // the effect node.
+ // Rounded corners that differ are not supported by the CALayerOverlay system
+ // on Mac. Instead of letting it fall back to the (worse for memory and
+ // battery) non-CALayerOverlay system for such cases, fall back to a
+ // non-shader border-radius mask for the effect node.
#if defined(OS_MACOSX)
if (radii.TopLeft() != radii.TopRight() ||
radii.TopLeft() != radii.BottomRight() ||
@@ -831,20 +861,55 @@ bool PropertyTreeManager::SupportsShaderBasedRoundedCorner(
return true;
}
-SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
+static cc::RenderSurfaceReason RenderSurfaceReasonForBackdropEffect(
+ const EffectPaintPropertyNode& backdrop_effect) {
+ DCHECK(backdrop_effect.HasBackdropEffect());
+ if (!backdrop_effect.BackdropFilter().IsEmpty())
+ return cc::RenderSurfaceReason::kBackdropFilter;
+ if (backdrop_effect.HasActiveBackdropFilterAnimation())
+ return cc::RenderSurfaceReason::kBackdropFilterAnimation;
+ DCHECK_NE(backdrop_effect.BlendMode(), SkBlendMode::kSrcOver);
+ // For optimization, we will set render surface reason for DstIn later in
+ // PaintArtifactCompositor::UpdateRenderSurfaceForEffects() only if needed.
+ if (backdrop_effect.BlendMode() == SkBlendMode::kDstIn)
+ return cc::RenderSurfaceReason::kNone;
+ return cc::RenderSurfaceReason::kBlendMode;
+}
+
+void PropertyTreeManager::PopulateCcEffectNodeBackdropEffect(
+ cc::EffectNode& effect_node,
+ const EffectPaintPropertyNode& backdrop_effect) {
+ DCHECK(backdrop_effect.HasBackdropEffect());
+
+ effect_node.backdrop_filters =
+ backdrop_effect.BackdropFilter().AsCcFilterOperations();
+ effect_node.backdrop_filter_bounds = backdrop_effect.BackdropFilterBounds();
+ effect_node.filters_origin = backdrop_effect.FiltersOrigin();
+ effect_node.blend_mode = backdrop_effect.BlendMode();
+ if (effect_node.render_surface_reason == cc::RenderSurfaceReason::kNone) {
+ effect_node.render_surface_reason =
+ RenderSurfaceReasonForBackdropEffect(backdrop_effect);
+ }
+}
+
+PropertyTreeManager::BackdropEffectState
+PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
const ClipPaintPropertyNode& target_clip_arg,
- SkBlendMode delegated_blend) {
+ const EffectPaintPropertyNode* next_effect) {
const auto* target_clip = &target_clip_arg.Unalias();
- if (delegated_blend != SkBlendMode::kSrcOver) {
- // Exit all synthetic effect node if the next child has exotic blending mode
- // because it has to access the backdrop of enclosing effect.
+ auto backdrop_effect_state = kNoBackdropEffect;
+ if (next_effect && next_effect->HasBackdropEffect()) {
+ // Exit all synthetic effect node if the next child has backdrop effect
+ // (exotic blending mode or backdrop filter) because it has to access the
+ // backdrop of enclosing effect.
while (IsCurrentCcEffectSynthetic())
CloseCcEffect();
- // An effect node can't omit render surface if it has child with exotic
- // blending mode. See comments below for more detail.
- // TODO(crbug.com/504464): Remove premature optimization here.
- SetCurrentEffectRenderSurfaceReason(cc::RenderSurfaceReason::kBlendMode);
+ // An effect node can't omit render surface if it has child with backdrop
+ // effect, in order to define the scope of the backdrop.
+ SetCurrentEffectRenderSurfaceReason(
+ cc::RenderSurfaceReason::kBackdropScope);
+ backdrop_effect_state = kBackdropEffectToBeSetOnCcEffectNode;
} else {
// Exit synthetic effects until there are no more synthesized clips below
// our lowest common ancestor.
@@ -857,7 +922,7 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
// In CompositeAfterPaint this should never happen.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
NOTREACHED();
- return delegated_blend;
+ return backdrop_effect_state;
}
const auto* pre_exit_clip = current_.clip;
CloseCcEffect();
@@ -886,10 +951,13 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
// In CompositeAfterPaint this should never happen.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
NOTREACHED();
- return delegated_blend;
+ return backdrop_effect_state;
}
- for (size_t i = pending_clips.size(); i--;) {
+ if (pending_clips.IsEmpty())
+ return backdrop_effect_state;
+
+ for (auto i = pending_clips.size(); i--;) {
const auto& pending_clip = pending_clips[i];
// For a non-trivial clip, the synthetic effect is an isolation to enclose
@@ -898,29 +966,16 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
// surface which is axis-aligned with the clip.
cc::EffectNode& synthetic_effect = *GetEffectTree().Node(
GetEffectTree().Insert(cc::EffectNode(), current_.effect_id));
+
if (pending_clip.type & CcEffectType::kSyntheticForNonTrivialClip) {
synthetic_effect.clip_id = EnsureCompositorClipNode(*pending_clip.clip);
// For non-trivial clip, isolation_effect.stable_id will be assigned later
// when the effect is closed. For now the default value INVALID_STABLE_ID
// is used. See PropertyTreeManager::EmitClipMaskLayer().
- } else {
- synthetic_effect.stable_id =
- CompositorElementIdFromUniqueObjectId(NewUniqueObjectId())
- .GetStableId();
- // The clip of the synthetic effect is the parent of the clip, so that
- // the clip itself will be applied in the render surface.
- DCHECK(pending_clip.clip->Parent());
- synthetic_effect.clip_id =
- EnsureCompositorClipNode(*pending_clip.clip->Parent());
- }
- const auto& transform = pending_clip.clip->LocalTransformSpace();
- synthetic_effect.transform_id = EnsureCompositorTransformNode(transform);
- synthetic_effect.double_sided = !transform.IsBackfaceHidden();
- if (pending_clip.type & CcEffectType::kSyntheticForNonTrivialClip) {
if (SupportsShaderBasedRoundedCorner(*pending_clip.clip,
- pending_clip.type)) {
+ pending_clip.type, next_effect)) {
synthetic_effect.rounded_corner_bounds =
- gfx::RRectF(pending_clip.clip->ClipRect());
+ gfx::RRectF(pending_clip.clip->PixelSnappedClipRect());
synthetic_effect.is_fast_rounded_corner = true;
// Nested rounded corner clips need to force render surfaces for
@@ -938,31 +993,50 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
}
} else {
synthetic_effect.render_surface_reason =
- pending_clip.clip->ClipRect().IsRounded()
+ pending_clip.clip->PixelSnappedClipRect().IsRounded()
? cc::RenderSurfaceReason::kRoundedCorner
: cc::RenderSurfaceReason::kClipPath;
}
pending_synthetic_mask_layers_.insert(synthetic_effect.id);
+ } else {
+ DCHECK(pending_clip.type & CcEffectType::kSyntheticFor2dAxisAlignment);
+ synthetic_effect.stable_id =
+ CompositorElementIdFromUniqueObjectId(NewUniqueObjectId())
+ .GetStableId();
+ // The clip of the synthetic effect is the parent of the clip, so that
+ // the clip itself will be applied in the render surface.
+ DCHECK(pending_clip.clip->Parent());
+ synthetic_effect.clip_id =
+ EnsureCompositorClipNode(*pending_clip.clip->Parent());
}
+
if (pending_clip.type & CcEffectType::kSyntheticFor2dAxisAlignment) {
synthetic_effect.render_surface_reason =
cc::RenderSurfaceReason::kClipAxisAlignment;
}
- // Clip and kDstIn do not commute. This shall never be reached because
- // kDstIn is only used internally to implement CSS clip-path and mask,
- // and there is never a difference between the output clip of the effect
- // and the mask content.
- DCHECK(delegated_blend != SkBlendMode::kDstIn);
- synthetic_effect.blend_mode = delegated_blend;
- delegated_blend = SkBlendMode::kSrcOver;
+ const TransformPaintPropertyNode* transform = nullptr;
+ if (backdrop_effect_state == kBackdropEffectToBeSetOnCcEffectNode) {
+ // Move the backdrop effect from the original effect up to the outermost
+ // synthetic effect to ensure the backdrop effect can access the correct
+ // backdrop.
+ DCHECK(next_effect);
+ transform = &next_effect->LocalTransformSpace();
+ PopulateCcEffectNodeBackdropEffect(synthetic_effect, *next_effect);
+ backdrop_effect_state = kBackdropEffectHasSetOnSyntheticEffect;
+ } else {
+ transform = &pending_clip.clip->LocalTransformSpace();
+ }
+
+ synthetic_effect.transform_id = EnsureCompositorTransformNode(*transform);
+ synthetic_effect.double_sided = !transform->IsBackfaceHidden();
effect_stack_.emplace_back(current_);
SetCurrentEffectState(synthetic_effect, pending_clip.type, *current_.effect,
- *pending_clip.clip);
+ *pending_clip.clip, *transform);
}
- return delegated_blend;
+ return backdrop_effect_state;
}
void PropertyTreeManager::BuildEffectNodesRecursively(
@@ -981,26 +1055,35 @@ void PropertyTreeManager::BuildEffectNodesRecursively(
"be contiguous.";
#endif
- // If we don't have an output clip, then we'll use the clip of the last
- // non-synthetic effect. This means we should close all synthetic effects on
- // the stack first.
- if (!next_effect.OutputClip()) {
+ auto backdrop_effect_state = kNoBackdropEffect;
+ int output_clip_id = 0;
+ const auto* output_clip = SafeUnalias(next_effect.OutputClip());
+ if (output_clip) {
+ backdrop_effect_state =
+ SynthesizeCcEffectsForClipsIfNeeded(*output_clip, &next_effect);
+ output_clip_id = EnsureCompositorClipNode(*output_clip);
+ } else {
+ // If we don't have an output clip, then we'll use the clip of the last
+ // non-synthetic effect. This means we should close all synthetic effects
+ // on the stack first.
while (IsCurrentCcEffectSynthetic())
CloseCcEffect();
- }
- SkBlendMode blend_mode;
- const ClipPaintPropertyNode* output_clip;
- int output_clip_id;
- std::tie(blend_mode, output_clip, output_clip_id) =
- GetBlendModeAndOutputClipForEffect(next_effect);
+ if (next_effect.HasBackdropEffect())
+ backdrop_effect_state = kBackdropEffectToBeSetOnCcEffectNode;
+ output_clip = current_.clip;
+ DCHECK(output_clip);
+ output_clip_id = GetEffectTree().Node(current_.effect_id)->clip_id;
+ DCHECK_EQ(output_clip_id, EnsureCompositorClipNode(*output_clip));
+ }
int effect_node_id =
GetEffectTree().Insert(cc::EffectNode(), current_.effect_id);
auto& effect_node = *GetEffectTree().Node(effect_node_id);
next_effect.SetCcNodeId(new_sequence_number_, effect_node_id);
- PopulateCcEffectNode(effect_node, next_effect, output_clip_id, blend_mode);
+ PopulateCcEffectNode(effect_node, next_effect, output_clip_id,
+ backdrop_effect_state);
CompositorElementId compositor_element_id =
next_effect.GetCompositorElementId();
@@ -1013,45 +1096,18 @@ void PropertyTreeManager::BuildEffectNodesRecursively(
effect_stack_.emplace_back(current_);
SetCurrentEffectState(effect_node, CcEffectType::kEffect, next_effect,
- *output_clip);
-}
-
-std::tuple<SkBlendMode, const ClipPaintPropertyNode*, int>
-PropertyTreeManager::GetBlendModeAndOutputClipForEffect(
- const EffectPaintPropertyNode& effect) {
- SkBlendMode blend_mode;
- int output_clip_id;
- const auto* output_clip = SafeUnalias(effect.OutputClip());
- if (output_clip) {
- blend_mode =
- SynthesizeCcEffectsForClipsIfNeeded(*output_clip, effect.BlendMode());
- output_clip_id = EnsureCompositorClipNode(*output_clip);
- } else {
- DCHECK(!IsCurrentCcEffectSynthetic());
- // An effect node can't omit render surface if it has child with exotic
- // blending mode.
- // TODO(crbug.com/504464): Remove premature optimization here.
- if (effect.BlendMode() != SkBlendMode::kSrcOver)
- SetCurrentEffectRenderSurfaceReason(cc::RenderSurfaceReason::kBlendMode);
-
- blend_mode = effect.BlendMode();
- output_clip = current_.clip;
- DCHECK(output_clip);
- output_clip_id = GetEffectTree().Node(current_.effect_id)->clip_id;
- DCHECK_EQ(output_clip_id, EnsureCompositorClipNode(*output_clip));
- }
- return std::make_tuple(blend_mode, output_clip, output_clip_id);
+ *output_clip, next_effect.LocalTransformSpace());
}
void PropertyTreeManager::PopulateCcEffectNode(
cc::EffectNode& effect_node,
const EffectPaintPropertyNode& effect,
int output_clip_id,
- SkBlendMode blend_mode) {
+ BackdropEffectState backdrop_effect_state) {
effect_node.stable_id = effect.GetCompositorElementId().GetStableId();
effect_node.clip_id = output_clip_id;
- // An effect with filters or backdrop filters needs a render surface.
+ // An effect with filters or backdrop effect needs a render surface.
// Also, kDstIn and kSrcOver blend modes have fast paths if only one layer
// is under the blend mode. This value is adjusted in PaintArtifactCompositor
// ::UpdateRenderSurfaceForEffects() to account for more than one layer.
@@ -1060,38 +1116,34 @@ void PropertyTreeManager::PopulateCcEffectNode(
} else if (effect.HasActiveFilterAnimation()) {
effect_node.render_surface_reason =
cc::RenderSurfaceReason::kFilterAnimation;
- } else if (!effect.BackdropFilter().IsEmpty()) {
- effect_node.render_surface_reason =
- cc::RenderSurfaceReason::kBackdropFilter;
- } else if (effect.HasActiveBackdropFilterAnimation()) {
- effect_node.render_surface_reason =
- cc::RenderSurfaceReason::kBackdropFilterAnimation;
- } else if (blend_mode != SkBlendMode::kSrcOver &&
- blend_mode != SkBlendMode::kDstIn) {
- effect_node.render_surface_reason = cc::RenderSurfaceReason::kBlendMode;
}
+ // If needed, render surface reason for backdrop effect will be set in
+ // PopuluateCcEffectNodeBackdropEffect() below.
effect_node.opacity = effect.Opacity();
if (effect.GetColorFilter() != kColorFilterNone) {
// Currently color filter is only used by SVG masks.
// We are cutting corner here by support only specific configuration.
- DCHECK(effect.GetColorFilter() == kColorFilterLuminanceToAlpha);
- DCHECK(blend_mode == SkBlendMode::kDstIn);
+ DCHECK_EQ(effect.GetColorFilter(), kColorFilterLuminanceToAlpha);
+ DCHECK_EQ(effect.BlendMode(), SkBlendMode::kDstIn);
DCHECK(effect.Filter().IsEmpty());
effect_node.filters.Append(cc::FilterOperation::CreateReferenceFilter(
sk_make_sp<ColorFilterPaintFilter>(SkLumaColorFilter::Make(),
nullptr)));
+ effect_node.blend_mode = SkBlendMode::kDstIn;
} else {
- effect_node.filters = effect.Filter().AsCcFilterOperations();
- effect_node.backdrop_filters =
- effect.BackdropFilter().AsCcFilterOperations();
- effect_node.backdrop_filter_bounds = effect.BackdropFilterBounds();
- effect_node.backdrop_mask_element_id = effect.BackdropMaskElementId();
- effect_node.filters_origin = effect.FiltersOrigin();
effect_node.transform_id =
EnsureCompositorTransformNode(effect.LocalTransformSpace());
+ if (backdrop_effect_state == kBackdropEffectToBeSetOnCcEffectNode) {
+ // We never have backdrop effect and filter on the same effect node.
+ DCHECK(effect.Filter().IsEmpty());
+ PopulateCcEffectNodeBackdropEffect(effect_node, effect);
+ effect_node.backdrop_mask_element_id = effect.BackdropMaskElementId();
+ } else {
+ effect_node.filters = effect.Filter().AsCcFilterOperations();
+ effect_node.filters_origin = effect.FiltersOrigin();
+ }
}
- effect_node.blend_mode = blend_mode;
effect_node.double_sided = !effect.LocalTransformSpace().IsBackfaceHidden();
effect_node.effect_changed = effect.NodeChangeAffectsRaster();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
index 09b99c7d1f2..4c807b5c0f6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/include/core/SkBlendMode.h"
namespace cc {
class ClipTree;
@@ -26,6 +25,10 @@ struct TransformNode;
enum class RenderSurfaceReason : uint8_t;
}
+namespace gfx {
+class ScrollOffset;
+}
+
namespace blink {
class ClipPaintPropertyNode;
@@ -39,6 +42,7 @@ class PropertyTreeManagerClient {
public:
virtual SynthesizedClip& CreateOrReuseSynthesizedClipLayer(
const ClipPaintPropertyNode&,
+ const TransformPaintPropertyNode&,
bool needs_layer,
CompositorElementId& mask_isolation_id,
CompositorElementId& mask_effect_id) = 0;
@@ -99,6 +103,12 @@ class PropertyTreeManager {
int EnsureCompositorScrollNode(
const TransformPaintPropertyNode& scroll_offset_translation);
+ // Same as above but marks the scroll nodes as being the viewport.
+ int EnsureCompositorInnerScrollNode(
+ const TransformPaintPropertyNode& scroll_offset_translation);
+ int EnsureCompositorOuterScrollNode(
+ const TransformPaintPropertyNode& scroll_offset_translation);
+
int EnsureCompositorPageScaleTransformNode(const TransformPaintPropertyNode&);
// This function is expected to be invoked right before emitting each layer.
@@ -119,21 +129,21 @@ class PropertyTreeManager {
void Finalize();
static bool DirectlyUpdateCompositedOpacityValue(
- cc::PropertyTrees*,
cc::LayerTreeHost&,
const EffectPaintPropertyNode&);
static bool DirectlyUpdateScrollOffsetTransform(
- cc::PropertyTrees*,
cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
- static bool DirectlyUpdateTransform(cc::PropertyTrees*,
- cc::LayerTreeHost&,
+ static bool DirectlyUpdateTransform(cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
static bool DirectlyUpdatePageScaleTransform(
- cc::PropertyTrees*,
cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
+ static void DirectlySetScrollOffset(cc::LayerTreeHost&,
+ CompositorElementId,
+ const gfx::ScrollOffset&);
+
private:
void SetupRootTransformNode();
void SetupRootClipNode();
@@ -156,8 +166,10 @@ class PropertyTreeManager {
kSyntheticFor2dAxisAlignment = 1 << 1
};
- static bool SupportsShaderBasedRoundedCorner(const ClipPaintPropertyNode&,
- CcEffectType type);
+ static bool SupportsShaderBasedRoundedCorner(
+ const ClipPaintPropertyNode&,
+ CcEffectType type,
+ const EffectPaintPropertyNode* next_effect);
struct EffectState {
// The cc effect node that has the corresponding drawing state to the
@@ -177,6 +189,12 @@ class PropertyTreeManager {
// It's never nullptr.
const ClipPaintPropertyNode* clip;
+ // The transform space of this state. It's |&effect->LocalTransformSpace()|
+ // if this state is of kEffect type or synthetic with backdrop filters
+ // moved up from the original effect.
+ // Otherwise it's |&clip->LocalTransformSpace()|.
+ const TransformPaintPropertyNode* transform;
+
// Whether the transform space of this state may be 2d axis misaligned to
// the containing render surface. As there may be new render surfaces
// created between this state and the current known ancestor render surface
@@ -201,28 +219,35 @@ class PropertyTreeManager {
// self and the next render surface. This is used to force a render surface
// for all ancestor synthetic rounded clips if a descendant is found.
bool contained_by_non_render_surface_synthetic_rounded_clip;
-
- // The transform space of the state.
- const TransformPaintPropertyNode& Transform() const;
};
void CollectAnimationElementId(CompositorElementId);
void BuildEffectNodesRecursively(const EffectPaintPropertyNode& next_effect);
void ForceRenderSurfaceIfSyntheticRoundedCornerClip(EffectState& state);
- SkBlendMode SynthesizeCcEffectsForClipsIfNeeded(
+
+ // When we create a synthetic clip, if the next effect has backdrop effect
+ // (exotic blending or backdrop filter), the backdrop effect should be set
+ // on the synthetic mask isolation effect node instead of the cc effect node
+ // that is created for the original blink effect node, to ensure the backdrop
+ // effect will see the correct backdrop input.
+ enum BackdropEffectState {
+ kNoBackdropEffect,
+ kBackdropEffectHasSetOnSyntheticEffect,
+ kBackdropEffectToBeSetOnCcEffectNode,
+ };
+ BackdropEffectState SynthesizeCcEffectsForClipsIfNeeded(
const ClipPaintPropertyNode& target_clip,
- SkBlendMode delegated_blend);
+ const EffectPaintPropertyNode* next_effect);
+
void EmitClipMaskLayer();
void CloseCcEffect();
-
- // For a given effect node, this returns the blend mode, clip property node,
- // and an int indicating cc clip node's id.
- std::tuple<SkBlendMode, const ClipPaintPropertyNode*, int>
- GetBlendModeAndOutputClipForEffect(const EffectPaintPropertyNode&);
void PopulateCcEffectNode(cc::EffectNode&,
- const EffectPaintPropertyNode&,
+ const EffectPaintPropertyNode& effect,
int output_clip_id,
- SkBlendMode);
+ BackdropEffectState);
+ void PopulateCcEffectNodeBackdropEffect(
+ cc::EffectNode& effect_node,
+ const EffectPaintPropertyNode& backdrop_effect);
bool IsCurrentCcEffectSynthetic() const { return current_.effect_type; }
bool IsCurrentCcEffectSyntheticForNonTrivialClip() const {
@@ -230,14 +255,15 @@ class PropertyTreeManager {
}
bool EffectStateMayBe2dAxisMisalignedToRenderSurface(EffectState&,
- size_t index);
+ wtf_size_t index);
bool CurrentEffectMayBe2dAxisMisalignedToRenderSurface();
CcEffectType SyntheticEffectType(const ClipPaintPropertyNode&);
void SetCurrentEffectState(const cc::EffectNode&,
CcEffectType,
const EffectPaintPropertyNode&,
- const ClipPaintPropertyNode&);
+ const ClipPaintPropertyNode&,
+ const TransformPaintPropertyNode&);
void SetCurrentEffectRenderSurfaceReason(cc::RenderSurfaceReason);
cc::TransformTree& GetTransformTree();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
index 86bd4d15537..dfa0ae804e9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -36,7 +36,7 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = {
{CompositingReason::kActiveBackdropFilterAnimation,
"activeBackdropFilterAnimation",
"Has an active accelerated backdrop filter animation or transition"},
- {CompositingReason::kImmersiveArOverlay, "immersiveArOverlay",
+ {CompositingReason::kXrOverlay, "xrOverlay",
"Is DOM overlay for WebXR immersive-ar mode"},
{CompositingReason::kScrollDependentPosition, "scrollDependentPosition",
"Is fixed or sticky position"},
@@ -58,8 +58,6 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = {
"Has a backdrop filter"},
{CompositingReason::kRootScroller, "rootScroller",
"Is the document.rootScroller"},
- {CompositingReason::kCrossOriginIframe, "crossOriginIframe",
- "Is a cross-origin iframe"},
{CompositingReason::kAssumedOverlap, "assumedOverlap",
"Might overlap other composited content"},
{CompositingReason::kOverlap, "overlap",
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
index 5df7a4e83d1..144640a6ddc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -27,7 +27,6 @@ using CompositingReasons = uint64_t;
V(ActiveOpacityAnimation) \
V(ActiveFilterAnimation) \
V(ActiveBackdropFilterAnimation) \
- V(ImmersiveArOverlay) \
V(ScrollDependentPosition) \
V(OverflowScrolling) \
V(OverflowScrollingParent) \
@@ -40,7 +39,7 @@ using CompositingReasons = uint64_t;
V(WillChangeOther) \
V(BackdropFilter) \
V(RootScroller) \
- V(CrossOriginIframe) \
+ V(XrOverlay) \
\
/* Overlap reasons that require knowing what's behind you in paint-order \
before knowing the answer. */ \
@@ -124,8 +123,8 @@ class PLATFORM_EXPORT CompositingReason {
kComboAllDirectNonStyleDeterminedReasons =
kVideo | kCanvas | kPlugin | kIFrame | kOverflowScrollingParent |
- kOutOfFlowClipping | kVideoOverlay | kImmersiveArOverlay | kRoot |
- kRootScroller | kScrollDependentPosition | kCrossOriginIframe,
+ kOutOfFlowClipping | kVideoOverlay | kXrOverlay | kRoot |
+ kRootScroller | kScrollDependentPosition,
kComboAllDirectReasons = kComboAllDirectStyleDeterminedReasons |
kComboAllDirectNonStyleDeterminedReasons,
@@ -149,6 +148,9 @@ class PLATFORM_EXPORT CompositingReason {
kComboSquashableReasons =
kOverlap | kAssumedOverlap | kOverflowScrollingParent,
+ kDirectReasonsForPaintOffsetTranslationProperty =
+ kScrollDependentPosition | kVideo | kCanvas | kPlugin | kIFrame,
+
kDirectReasonsForTransformProperty =
k3DTransform | kWillChangeTransform | kWillChangeOther |
kPerspectiveWith3DDescendants | kPreserve3DWith3DDescendants |
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
index 957fbf2b7fe..25b0f8227d6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
@@ -25,8 +25,9 @@ enum class CompositorElementIdNamespace {
kEffectClipPath,
kVerticalScrollbar,
kHorizontalScrollbar,
+ kDOMNodeId,
// The following values are for internal usage only.
- kMax = kHorizontalScrollbar,
+ kMax = kDOMNodeId,
// A sentinel to indicate the maximum representable namespace id
// (the maximum is one less than this value).
kMaxRepresentable = 1 << kCompositorNamespaceBitCount
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
index 243b9a1c0e0..9eec39764c9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
@@ -110,6 +110,10 @@ bool CompositorFilterOperations::HasFilterThatMovesPixels() const {
return filter_operations_.HasFilterThatMovesPixels();
}
+bool CompositorFilterOperations::HasReferenceFilter() const {
+ return filter_operations_.HasReferenceFilter();
+}
+
bool CompositorFilterOperations::operator==(
const CompositorFilterOperations& o) const {
return reference_box_ == o.reference_box_ &&
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
index c943a2619f9..4c3a334f655 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
@@ -49,9 +49,10 @@ class PLATFORM_EXPORT CompositorFilterOperations {
FloatRect MapRect(const FloatRect& input_rect) const;
bool HasFilterThatMovesPixels() const;
+ bool HasReferenceFilter() const;
void SetReferenceBox(const FloatRect& r) { reference_box_ = r; }
- FloatRect ReferenceBox() const { return reference_box_; }
+ const FloatRect& ReferenceBox() const { return reference_box_; }
// For reference filters, this equality operator compares pointers of the
// image_filter fields instead of their values.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
index 19cb6f21032..9ea0c88d694 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
@@ -22,7 +22,7 @@ class ContiguousContainerBase::Buffer {
USING_FAST_MALLOC(Buffer);
public:
- Buffer(size_t buffer_size, const char* type_name) {
+ Buffer(wtf_size_t buffer_size, const char* type_name) {
capacity_ = WTF::Partitions::BufferActualSize(buffer_size);
begin_ = end_ =
static_cast<char*>(WTF::Partitions::BufferMalloc(capacity_, type_name));
@@ -34,12 +34,12 @@ class ContiguousContainerBase::Buffer {
WTF::Partitions::BufferFree(begin_);
}
- size_t Capacity() const { return capacity_; }
- size_t UsedCapacity() const { return end_ - begin_; }
- size_t UnusedCapacity() const { return Capacity() - UsedCapacity(); }
+ wtf_size_t Capacity() const { return capacity_; }
+ wtf_size_t UsedCapacity() const { return end_ - begin_; }
+ wtf_size_t UnusedCapacity() const { return Capacity() - UsedCapacity(); }
bool IsEmpty() const { return UsedCapacity() == 0; }
- void* Allocate(size_t object_size) {
+ void* Allocate(wtf_size_t object_size) {
DCHECK_GE(UnusedCapacity(), object_size);
ANNOTATE_CHANGE_SIZE(begin_, capacity_, UsedCapacity(),
UsedCapacity() + object_size);
@@ -60,12 +60,12 @@ class ContiguousContainerBase::Buffer {
// m_begin <= m_end <= m_begin + m_capacity
char* begin_;
char* end_;
- size_t capacity_;
+ wtf_size_t capacity_;
DISALLOW_COPY_AND_ASSIGN(Buffer);
};
-ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size)
+ContiguousContainerBase::ContiguousContainerBase(wtf_size_t max_object_size)
: end_index_(0), max_object_size_(max_object_size) {}
ContiguousContainerBase::ContiguousContainerBase(
@@ -82,31 +82,31 @@ ContiguousContainerBase& ContiguousContainerBase::operator=(
return *this;
}
-size_t ContiguousContainerBase::CapacityInBytes() const {
- size_t capacity = 0;
+wtf_size_t ContiguousContainerBase::CapacityInBytes() const {
+ wtf_size_t capacity = 0;
for (const auto& buffer : buffers_)
capacity += buffer->Capacity();
return capacity;
}
-size_t ContiguousContainerBase::UsedCapacityInBytes() const {
- size_t used_capacity = 0;
+wtf_size_t ContiguousContainerBase::UsedCapacityInBytes() const {
+ wtf_size_t used_capacity = 0;
for (const auto& buffer : buffers_)
used_capacity += buffer->UsedCapacity();
return used_capacity;
}
-size_t ContiguousContainerBase::MemoryUsageInBytes() const {
+wtf_size_t ContiguousContainerBase::MemoryUsageInBytes() const {
return sizeof(*this) + CapacityInBytes() +
elements_.capacity() * sizeof(elements_[0]);
}
-void ContiguousContainerBase::ReserveInitialCapacity(size_t buffer_size,
+void ContiguousContainerBase::ReserveInitialCapacity(wtf_size_t buffer_size,
const char* type_name) {
AllocateNewBufferForNextAllocation(buffer_size, type_name);
}
-void* ContiguousContainerBase::Allocate(size_t object_size,
+void* ContiguousContainerBase::Allocate(wtf_size_t object_size,
const char* type_name) {
DCHECK_LE(object_size, max_object_size_);
@@ -120,9 +120,9 @@ void* ContiguousContainerBase::Allocate(size_t object_size,
}
if (!buffer_for_alloc) {
- size_t new_buffer_size = buffers_.IsEmpty()
- ? kDefaultInitialBufferSize * max_object_size_
- : 2 * buffers_.back()->Capacity();
+ wtf_size_t new_buffer_size =
+ buffers_.IsEmpty() ? kDefaultInitialBufferSize * max_object_size_
+ : 2 * buffers_.back()->Capacity();
buffer_for_alloc =
AllocateNewBufferForNextAllocation(new_buffer_size, type_name);
}
@@ -169,7 +169,7 @@ void ContiguousContainerBase::ShrinkToFit() {
ContiguousContainerBase::Buffer*
ContiguousContainerBase::AllocateNewBufferForNextAllocation(
- size_t buffer_size,
+ wtf_size_t buffer_size,
const char* type_name) {
DCHECK(buffers_.IsEmpty() || end_index_ == buffers_.size() - 1);
std::unique_ptr<Buffer> new_buffer =
diff --git a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
index 3eee5589124..c81241eb708 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
@@ -41,21 +41,21 @@ class PLATFORM_EXPORT ContiguousContainerBase {
DISALLOW_NEW();
protected:
- explicit ContiguousContainerBase(size_t max_object_size);
+ explicit ContiguousContainerBase(wtf_size_t max_object_size);
ContiguousContainerBase(ContiguousContainerBase&&);
~ContiguousContainerBase();
ContiguousContainerBase& operator=(ContiguousContainerBase&&);
- size_t size() const { return elements_.size(); }
+ wtf_size_t size() const { return elements_.size(); }
bool IsEmpty() const { return !size(); }
- size_t CapacityInBytes() const;
- size_t UsedCapacityInBytes() const;
- size_t MemoryUsageInBytes() const;
+ wtf_size_t CapacityInBytes() const;
+ wtf_size_t UsedCapacityInBytes() const;
+ wtf_size_t MemoryUsageInBytes() const;
// These do not invoke constructors or destructors.
- void ReserveInitialCapacity(size_t, const char* type_name);
- void* Allocate(size_t object_size, const char* type_name);
+ void ReserveInitialCapacity(wtf_size_t, const char* type_name);
+ void* Allocate(wtf_size_t object_size, const char* type_name);
void RemoveLast();
void Clear();
void Swap(ContiguousContainerBase&);
@@ -69,11 +69,11 @@ class PLATFORM_EXPORT ContiguousContainerBase {
private:
class Buffer;
- Buffer* AllocateNewBufferForNextAllocation(size_t, const char* type_name);
+ Buffer* AllocateNewBufferForNextAllocation(wtf_size_t, const char* type_name);
Vector<std::unique_ptr<Buffer>> buffers_;
unsigned end_index_;
- size_t max_object_size_;
+ wtf_size_t max_object_size_;
DISALLOW_COPY_AND_ASSIGN(ContiguousContainerBase);
};
@@ -138,10 +138,10 @@ class ContiguousContainer : public ContiguousContainerBase {
using value_type = BaseElementType;
- explicit ContiguousContainer(size_t max_object_size)
+ explicit ContiguousContainer(wtf_size_t max_object_size)
: ContiguousContainerBase(Align(max_object_size)) {}
- ContiguousContainer(size_t max_object_size, size_t initial_size_bytes)
+ ContiguousContainer(wtf_size_t max_object_size, wtf_size_t initial_size_bytes)
: ContiguousContainer(max_object_size) {
ReserveInitialCapacity(std::max(max_object_size, initial_size_bytes),
WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType));
@@ -190,8 +190,8 @@ class ContiguousContainer : public ContiguousContainerBase {
const BaseElementType& First() const { return *begin(); }
BaseElementType& Last() { return *rbegin(); }
const BaseElementType& Last() const { return *rbegin(); }
- BaseElementType& operator[](size_t index) { return *(begin() + index); }
- const BaseElementType& operator[](size_t index) const {
+ BaseElementType& operator[](wtf_size_t index) { return *(begin() + index); }
+ const BaseElementType& operator[](wtf_size_t index) const {
return *(begin() + index);
}
@@ -226,7 +226,7 @@ class ContiguousContainer : public ContiguousContainerBase {
// Appends a new element using memcpy, then default-constructs a base
// element in its place. Use with care.
- BaseElementType& AppendByMoving(BaseElementType& item, size_t size) {
+ BaseElementType& AppendByMoving(BaseElementType& item, wtf_size_t size) {
DCHECK_GE(size, sizeof(BaseElementType));
void* new_item = AlignedAllocate(size);
memcpy(new_item, static_cast<void*>(&item), size);
@@ -235,15 +235,15 @@ class ContiguousContainer : public ContiguousContainerBase {
}
private:
- void* AlignedAllocate(size_t size) {
+ void* AlignedAllocate(wtf_size_t size) {
void* result = ContiguousContainerBase::Allocate(
Align(size), WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType));
DCHECK_EQ(reinterpret_cast<intptr_t>(result) & (alignment - 1), 0u);
return result;
}
- static size_t Align(size_t size) {
- size_t aligned_size = alignment * ((size + alignment - 1) / alignment);
+ static wtf_size_t Align(wtf_size_t size) {
+ wtf_size_t aligned_size = alignment * ((size + alignment - 1) / alignment);
DCHECK_EQ(aligned_size % alignment, 0u);
DCHECK_GE(aligned_size, size);
DCHECK_LT(aligned_size, size + alignment);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
index 59c68f69182..c1a01c9a1a3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
@@ -43,10 +43,12 @@ CrossfadeGeneratedImage::CrossfadeGeneratedImage(
percentage_(percentage),
crossfade_size_(crossfade_size) {}
-void CrossfadeGeneratedImage::DrawCrossfade(cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- ImageClampingMode clamp_mode,
- ImageDecodingMode decode_mode) {
+void CrossfadeGeneratedImage::DrawCrossfade(
+ cc::PaintCanvas* canvas,
+ const PaintFlags& flags,
+ RespectImageOrientationEnum respect_orientation,
+ ImageClampingMode clamp_mode,
+ ImageDecodingMode decode_mode) {
FloatRect from_image_rect(FloatPoint(), FloatSize(from_image_->Size()));
FloatRect to_image_rect(FloatPoint(), FloatSize(to_image_->Size()));
FloatRect dest_rect((FloatPoint()), crossfade_size_);
@@ -72,33 +74,32 @@ void CrossfadeGeneratedImage::DrawCrossfade(cc::PaintCanvas* canvas,
image_flags.setBlendMode(SkBlendMode::kPlus);
image_flags.setColor(ScaleAlpha(flags.getColor(), percentage_));
to_image_->Draw(canvas, image_flags, dest_rect, to_image_rect,
- kDoNotRespectImageOrientation, clamp_mode, decode_mode);
+ respect_orientation, clamp_mode, decode_mode);
}
-void CrossfadeGeneratedImage::Draw(cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- RespectImageOrientationEnum,
- ImageClampingMode clamp_mode,
- ImageDecodingMode decode_mode) {
+void CrossfadeGeneratedImage::Draw(
+ cc::PaintCanvas* canvas,
+ const PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum respect_orientation,
+ ImageClampingMode clamp_mode,
+ ImageDecodingMode decode_mode) {
// Draw nothing if either of the images hasn't loaded yet.
if (from_image_ == Image::NullImage() || to_image_ == Image::NullImage())
return;
PaintCanvasAutoRestore ar(canvas, true);
canvas->clipRect(dst_rect);
- canvas->translate(dst_rect.X(), dst_rect.Y());
- if (dst_rect.Size() != src_rect.Size())
- canvas->scale(dst_rect.Width() / src_rect.Width(),
- dst_rect.Height() / src_rect.Height());
- canvas->translate(-src_rect.X(), -src_rect.Y());
-
- DrawCrossfade(canvas, flags, clamp_mode, decode_mode);
+ canvas->concat(
+ SkMatrix::MakeRectToRect(src_rect, dst_rect, SkMatrix::kFill_ScaleToFit));
+ DrawCrossfade(canvas, flags, respect_orientation, clamp_mode, decode_mode);
}
-void CrossfadeGeneratedImage::DrawTile(GraphicsContext& context,
- const FloatRect& src_rect) {
+void CrossfadeGeneratedImage::DrawTile(
+ GraphicsContext& context,
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum respect_orientation) {
// Draw nothing if either of the images hasn't loaded yet.
if (from_image_ == Image::NullImage() || to_image_ == Image::NullImage())
return;
@@ -108,7 +109,8 @@ void CrossfadeGeneratedImage::DrawTile(GraphicsContext& context,
FloatRect dest_rect((FloatPoint()), crossfade_size_);
flags.setFilterQuality(
context.ComputeFilterQuality(this, dest_rect, src_rect));
- DrawCrossfade(context.Canvas(), flags, kClampImageToSourceRect, kSyncDecode);
+ DrawCrossfade(context.Canvas(), flags, respect_orientation,
+ kClampImageToSourceRect, kSyncDecode);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h
index 55c37030884..17fb61c5692 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h
@@ -59,7 +59,9 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
RespectImageOrientationEnum,
ImageClampingMode,
ImageDecodingMode) override;
- void DrawTile(GraphicsContext&, const FloatRect&) final;
+ void DrawTile(GraphicsContext&,
+ const FloatRect&,
+ RespectImageOrientationEnum) final;
CrossfadeGeneratedImage(scoped_refptr<Image> from_image,
scoped_refptr<Image> to_image,
@@ -70,6 +72,7 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
private:
void DrawCrossfade(cc::PaintCanvas*,
const cc::PaintFlags&,
+ RespectImageOrientationEnum,
ImageClampingMode,
ImageDecodingMode);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
index 0c2a478ca67..8b05ce0ff90 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/platform/graphics/dark_mode_generic_classifier.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_icon_classifier.h"
#include "third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/effects/SkColorMatrix.h"
@@ -129,7 +130,13 @@ void DarkModeFilter::UpdateSettings(const DarkModeSettings& new_settings) {
Color DarkModeFilter::InvertColorIfNeeded(const Color& color,
ElementRole role) {
- if (IsDarkModeActive() && ShouldApplyToColor(color, role))
+ if (!IsDarkModeActive())
+ return color;
+
+ if (role_override_.has_value())
+ role = role_override_.value();
+
+ if (ShouldApplyToColor(color, role))
return color_filter_->InvertColor(color);
return color;
}
@@ -150,6 +157,9 @@ base::Optional<cc::PaintFlags> DarkModeFilter::ApplyToFlagsIfNeeded(
if (!IsDarkModeActive())
return base::nullopt;
+ if (role_override_.has_value())
+ role = role_override_.value();
+
cc::PaintFlags dark_mode_flags = flags;
if (flags.HasShader()) {
dark_mode_flags.setColorFilter(color_filter_->ToSkColorFilter());
@@ -177,6 +187,13 @@ bool DarkModeFilter::ShouldApplyToColor(const Color& color, ElementRole role) {
DCHECK(text_classifier_);
return text_classifier_->ShouldInvertColor(color) ==
DarkModeClassification::kApplyFilter;
+ case ElementRole::kListSymbol:
+ // TODO(prashant.n): Rename text_classifier_ to foreground_classifier_,
+ // so that same classifier can be used for all roles which are supposed
+ // to be at foreground.
+ DCHECK(text_classifier_);
+ return text_classifier_->ShouldInvertColor(color) ==
+ DarkModeClassification::kApplyFilter;
case ElementRole::kBackground:
DCHECK(background_classifier_);
return background_classifier_->ShouldInvertColor(color) ==
@@ -195,4 +212,18 @@ bool DarkModeFilter::ShouldApplyToColor(const Color& color, ElementRole role) {
NOTREACHED();
}
+ScopedDarkModeElementRoleOverride::ScopedDarkModeElementRoleOverride(
+ GraphicsContext* graphics_context,
+ DarkModeFilter::ElementRole role)
+ : graphics_context_(graphics_context) {
+ DarkModeFilter& dark_mode_filter = graphics_context->dark_mode_filter_;
+ previous_role_override_ = dark_mode_filter.role_override_;
+ dark_mode_filter.role_override_ = role;
+}
+
+ScopedDarkModeElementRoleOverride::~ScopedDarkModeElementRoleOverride() {
+ DarkModeFilter& dark_mode_filter = graphics_context_->dark_mode_filter_;
+ dark_mode_filter.role_override_ = previous_role_override_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
index b46d2e35b75..56a926f5f0d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
@@ -21,6 +21,7 @@ namespace blink {
class DarkModeColorClassifier;
class DarkModeColorFilter;
+class ScopedDarkModeElementRoleOverride;
class PLATFORM_EXPORT DarkModeFilter {
public:
@@ -37,7 +38,7 @@ class PLATFORM_EXPORT DarkModeFilter {
// TODO(gilmanmh): Add a role for shadows. In general, we don't want to
// invert shadows, but we may need to do some other kind of processing for
// them.
- enum class ElementRole { kText, kBackground, kSVG };
+ enum class ElementRole { kText, kListSymbol, kBackground, kSVG };
Color InvertColorIfNeeded(const Color& color, ElementRole element_role);
base::Optional<cc::PaintFlags> ApplyToFlagsIfNeeded(
const cc::PaintFlags& flags,
@@ -52,6 +53,8 @@ class PLATFORM_EXPORT DarkModeFilter {
SkColorFilter* GetImageFilterForTesting() { return image_filter_.get(); }
private:
+ friend class ScopedDarkModeElementRoleOverride;
+
DarkModeSettings settings_;
bool ShouldApplyToColor(const Color& color, ElementRole role);
@@ -60,6 +63,20 @@ class PLATFORM_EXPORT DarkModeFilter {
std::unique_ptr<DarkModeColorClassifier> background_classifier_;
std::unique_ptr<DarkModeColorFilter> color_filter_;
sk_sp<SkColorFilter> image_filter_;
+ base::Optional<ElementRole> role_override_;
+};
+
+// Temporarily override the element role for the scope of this object's
+// lifetime - for example when drawing symbols that play the role of text.
+class PLATFORM_EXPORT ScopedDarkModeElementRoleOverride {
+ public:
+ ScopedDarkModeElementRoleOverride(GraphicsContext* graphics_context,
+ DarkModeFilter::ElementRole role);
+ ~ScopedDarkModeElementRoleOverride();
+
+ private:
+ GraphicsContext* graphics_context_;
+ base::Optional<DarkModeFilter::ElementRole> previous_role_override_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
index da6f2259314..b99ac19e445 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
@@ -175,15 +175,11 @@ String DeferredImageDecoder::FilenameExtension() const {
: filename_extension_;
}
-sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator(size_t index) {
+sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator() {
if (frame_generator_ && frame_generator_->DecodeFailed())
return nullptr;
- PrepareLazyDecodedFrames();
-
- // PrepareLazyDecodedFrames should populate the metadata for each frame in
- // this image and create the |frame_generator_|, if enough data is available.
- if (index >= frame_data_.size())
+ if (invalid_image_ || frame_data_.IsEmpty())
return nullptr;
DCHECK(frame_generator_);
@@ -196,10 +192,16 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator(size_t index) {
SegmentReader::CreateFromSkROBuffer(std::move(ro_buffer));
// ImageFrameGenerator has the latest known alpha state. There will be a
- // performance boost if this frame is opaque.
- SkAlphaType alpha_type = frame_generator_->HasAlpha(index)
- ? kPremul_SkAlphaType
- : kOpaque_SkAlphaType;
+ // performance boost if the image is opaque since we can avoid painting
+ // the background in this case.
+ // For multi-frame images, these maybe animated on the compositor thread.
+ // So we can not mark them as opaque unless all frames are opaque.
+ // TODO(khushalsagar): Check whether all frames being added to the
+ // generator are opaque when populating FrameMetadata below.
+ SkAlphaType alpha_type = kPremul_SkAlphaType;
+ if (frame_data_.size() == 1u && !frame_generator_->HasAlpha(0u))
+ alpha_type = kOpaque_SkAlphaType;
+
SkImageInfo info =
SkImageInfo::MakeN32(decoded_size.width(), decoded_size.height(),
alpha_type, color_space_for_sk_images_);
@@ -396,14 +398,19 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() {
if (!metadata_decoder_ || !metadata_decoder_->IsSizeAvailable())
return;
+ if (invalid_image_)
+ return;
+
if (!image_metadata_)
image_metadata_ = metadata_decoder_->MakeMetadataForDecodeAcceleration();
// If the image contains a coded size with zero in either or both size
// dimensions, the image is invalid.
if (image_metadata_->coded_size.has_value() &&
- image_metadata_->coded_size.value().IsEmpty())
+ image_metadata_->coded_size.value().IsEmpty()) {
+ invalid_image_ = true;
return;
+ }
ActivateLazyDecoding();
@@ -411,12 +418,16 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() {
frame_data_.resize(metadata_decoder_->FrameCount());
// The decoder may be invalidated during a FrameCount(). Simply bail if so.
- if (metadata_decoder_->Failed())
+ if (metadata_decoder_->Failed()) {
+ invalid_image_ = true;
return;
+ }
// We have encountered a broken image file. Simply bail.
- if (frame_data_.size() < previous_size)
+ if (frame_data_.size() < previous_size) {
+ invalid_image_ = true;
return;
+ }
for (size_t i = previous_size; i < frame_data_.size(); ++i) {
frame_data_[i].duration_ = metadata_decoder_->FrameDurationAtIndex(i);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h
index d7a069b0590..76a5fa15af1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h
@@ -62,7 +62,7 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
String FilenameExtension() const;
- sk_sp<PaintImageGenerator> CreateGenerator(size_t index);
+ sk_sp<PaintImageGenerator> CreateGenerator();
scoped_refptr<SharedBuffer> Data();
void SetData(scoped_refptr<SharedBuffer> data, bool all_data_received);
@@ -120,6 +120,10 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
const PaintImage::ContentId complete_frame_content_id_;
base::Optional<bool> incremental_decode_needed_;
+ // Set to true if the image is detected to be invalid after parsing the
+ // metadata.
+ bool invalid_image_ = false;
+
// Caches an image's metadata so it can outlive |metadata_decoder_| after all
// data is received in cases where multiple generators are created.
base::Optional<cc::ImageHeaderMetadata> image_metadata_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
index d515c956a31..7e81cb95bc4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
@@ -131,8 +131,7 @@ class DeferredImageDecoderTest : public testing::Test,
.set_id(paint_image_id_)
.set_animation_type(type)
.set_completion_state(state)
- .set_paint_image_generator(
- decoder->CreateGenerator(PaintImage::kDefaultFrameIndex))
+ .set_paint_image_generator(decoder->CreateGenerator())
.TakePaintImage();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc
index 2283a6378e3..a8cc839fa98 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc
@@ -19,7 +19,7 @@ namespace {
sk_sp<SkImage> CreateFrameAtIndex(DeferredImageDecoder* decoder, size_t index) {
return SkImage::MakeFromGenerator(std::make_unique<SkiaPaintImageGenerator>(
- decoder->CreateGenerator(index), index,
+ decoder->CreateGenerator(), index,
cc::PaintImage::kDefaultGeneratorClientId));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
index ce5709eb94f..aa24b6a28ab 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
@@ -34,8 +34,8 @@ static const unsigned kColorMatrixSize = 20;
FEColorMatrix::FEColorMatrix(Filter* filter,
ColorMatrixType type,
- const Vector<float>& values)
- : FilterEffect(filter), type_(type), values_(values) {}
+ Vector<float> values)
+ : FilterEffect(filter), type_(type), values_(std::move(values)) {}
ColorMatrixType FEColorMatrix::GetType() const {
return type_;
@@ -52,10 +52,10 @@ const Vector<float>& FEColorMatrix::Values() const {
return values_;
}
-bool FEColorMatrix::SetValues(const Vector<float>& values) {
+bool FEColorMatrix::SetValues(Vector<float> values) {
if (values_ == values)
return false;
- values_ = values;
+ values_ = std::move(values);
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h
index 1621b60ea8c..76c9ffc155b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h
@@ -38,22 +38,17 @@ enum ColorMatrixType {
class PLATFORM_EXPORT FEColorMatrix final : public FilterEffect {
public:
- FEColorMatrix(Filter*, ColorMatrixType, const Vector<float>&);
+ FEColorMatrix(Filter*, ColorMatrixType, Vector<float>);
ColorMatrixType GetType() const;
bool SetType(ColorMatrixType);
const Vector<float>& Values() const;
- bool SetValues(const Vector<float>&);
+ bool SetValues(Vector<float>);
WTF::TextStream& ExternalRepresentation(WTF::TextStream&,
int indention) const override;
- static inline void CalculateSaturateComponents(float* components,
- float value);
- static inline void CalculateHueRotateComponents(float* components,
- float value);
-
private:
sk_sp<PaintFilter> CreateImageFilter() override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc
index 8ea49549dc5..b2bff044da0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc
@@ -34,18 +34,21 @@ FloatRect FETile::MapInputs(const FloatRect& rect) const {
return AbsoluteBounds();
}
+FloatRect FETile::GetSourceRect() const {
+ const FilterEffect* input = InputEffect(0);
+ if (input->GetFilterEffectType() == kFilterEffectTypeSourceInput)
+ return GetFilter()->FilterRegion();
+ return input->FilterPrimitiveSubregion();
+}
+
sk_sp<PaintFilter> FETile::CreateImageFilter() {
sk_sp<PaintFilter> input(paint_filter_builder::Build(
InputEffect(0), OperatingInterpolationSpace()));
if (!input)
return nullptr;
-
- FloatRect src_rect;
- if (InputEffect(0)->GetFilterEffectType() == kFilterEffectTypeSourceInput)
- src_rect = GetFilter()->FilterRegion();
- else
- src_rect = InputEffect(0)->FilterPrimitiveSubregion();
- FloatRect dst_rect = FilterPrimitiveSubregion();
+ FloatRect src_rect = GetFilter()->MapLocalRectToAbsoluteRect(GetSourceRect());
+ FloatRect dst_rect =
+ GetFilter()->MapLocalRectToAbsoluteRect(FilterPrimitiveSubregion());
return sk_make_sp<TilePaintFilter>(src_rect, dst_rect, std::move(input));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.h b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.h
index b20b4bfb99e..95732d35988 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_tile.h
@@ -40,6 +40,7 @@ class PLATFORM_EXPORT FETile final : public FilterEffect {
}
FloatRect MapInputs(const FloatRect&) const final;
+ FloatRect GetSourceRect() const;
sk_sp<PaintFilter> CreateImageFilter() override;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
index df7735c1182..488aa17c8bb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
@@ -131,10 +131,14 @@ sk_sp<PaintFilter> FETurbulence::CreateImageFilter() {
// a frequency, not a period.
float base_frequency_x = base_frequency_x_ / GetFilter()->Scale();
float base_frequency_y = base_frequency_y_ / GetFilter()->Scale();
+
+ // Cap the number of octaves to the maximum detectable when rendered with
+ // 8 bits per pixel, plus one for higher bit depth.
+ int capped_num_octaves = std::min(NumOctaves(), 9);
return sk_make_sp<TurbulencePaintFilter>(
type, SkFloatToScalar(base_frequency_x),
- SkFloatToScalar(base_frequency_y), NumOctaves(), SkFloatToScalar(Seed()),
- StitchTiles() ? &size : nullptr, &rect);
+ SkFloatToScalar(base_frequency_y), capped_num_octaves,
+ SkFloatToScalar(Seed()), StitchTiles() ? &size : nullptr, &rect);
}
static WTF::TextStream& operator<<(WTF::TextStream& ts,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.cc
index 515d6d72cb2..c1ae00d3ba2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.cc
@@ -49,7 +49,7 @@ Filter::Filter(const FloatRect& reference_box,
unit_scaling_(unit_scaling),
source_graphic_(MakeGarbageCollected<SourceGraphic>(this)) {}
-void Filter::Trace(blink::Visitor* visitor) {
+void Filter::Trace(Visitor* visitor) {
visitor->Trace(source_graphic_);
visitor->Trace(last_effect_);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
index d5073d5c854..efd30aa6721 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
@@ -44,7 +44,7 @@ class PLATFORM_EXPORT Filter final : public GarbageCollected<Filter> {
float scale,
UnitScaling);
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
float Scale() const { return scale_; }
FloatRect MapLocalRectToAbsoluteRect(const FloatRect&) const;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc
index 513efef32de..1b8dd7a802e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.cc
@@ -39,7 +39,7 @@ FilterEffect::FilterEffect(Filter* filter)
FilterEffect::~FilterEffect() = default;
-void FilterEffect::Trace(blink::Visitor* visitor) {
+void FilterEffect::Trace(Visitor* visitor) {
visitor->Trace(input_effects_);
visitor->Trace(filter_);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h
index cec2f5c1208..1f3e99d19fe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h
@@ -51,7 +51,7 @@ enum FilterEffectType {
class PLATFORM_EXPORT FilterEffect : public GarbageCollected<FilterEffect> {
public:
virtual ~FilterEffect();
- virtual void Trace(blink::Visitor*);
+ virtual void Trace(Visitor*);
void DisposeImageFilters();
void DisposeImageFiltersRecursive();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc
index 6efb7a02915..666cc1d5925 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/generated_image.cc
@@ -38,13 +38,15 @@
namespace blink {
-void GeneratedImage::DrawPattern(GraphicsContext& dest_context,
- const FloatRect& src_rect,
- const FloatSize& scale,
- const FloatPoint& phase,
- SkBlendMode composite_op,
- const FloatRect& dest_rect,
- const FloatSize& repeat_spacing) {
+void GeneratedImage::DrawPattern(
+ GraphicsContext& dest_context,
+ const FloatRect& src_rect,
+ const FloatSize& scale,
+ const FloatPoint& phase,
+ SkBlendMode composite_op,
+ const FloatRect& dest_rect,
+ const FloatSize& repeat_spacing,
+ RespectImageOrientationEnum respect_orientation) {
FloatRect tile_rect = src_rect;
tile_rect.Expand(repeat_spacing);
@@ -53,7 +55,7 @@ void GeneratedImage::DrawPattern(GraphicsContext& dest_context,
pattern_matrix.preTranslate(tile_rect.X(), tile_rect.Y());
sk_sp<PaintShader> tile_shader =
- CreateShader(tile_rect, &pattern_matrix, src_rect);
+ CreateShader(tile_rect, &pattern_matrix, src_rect, respect_orientation);
PaintFlags fill_flags = dest_context.FillFlags();
fill_flags.setShader(std::move(tile_shader));
@@ -63,13 +65,15 @@ void GeneratedImage::DrawPattern(GraphicsContext& dest_context,
dest_context.DrawRect(dest_rect, fill_flags);
}
-sk_sp<PaintShader> GeneratedImage::CreateShader(const FloatRect& tile_rect,
- const SkMatrix* pattern_matrix,
- const FloatRect& src_rect) {
+sk_sp<PaintShader> GeneratedImage::CreateShader(
+ const FloatRect& tile_rect,
+ const SkMatrix* pattern_matrix,
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum respect_orientation) {
auto paint_controller = std::make_unique<PaintController>();
GraphicsContext context(*paint_controller);
context.BeginRecording(tile_rect);
- DrawTile(context, src_rect);
+ DrawTile(context, src_rect, respect_orientation);
sk_sp<PaintRecord> record = context.EndRecording();
return PaintShader::MakePaintRecord(std::move(record), tile_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/generated_image.h
index 21d225cf0cc..fd645ff5e07 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/generated_image.h
@@ -39,6 +39,9 @@ class PLATFORM_EXPORT GeneratedImage : public Image {
bool HasIntrinsicSize() const override { return false; }
IntSize Size() const override { return RoundedIntSize(size_); }
+ FloatSize SizeAsFloat(RespectImageOrientationEnum) const override {
+ return size_;
+ }
// Assume that generated content has no decoded data we need to worry about
void DestroyDecodedData() override {}
@@ -52,17 +55,21 @@ class PLATFORM_EXPORT GeneratedImage : public Image {
const FloatPoint&,
SkBlendMode,
const FloatRect&,
- const FloatSize& repeat_spacing) final;
+ const FloatSize& repeat_spacing,
+ RespectImageOrientationEnum) final;
virtual sk_sp<cc::PaintShader> CreateShader(const FloatRect& tile_rect,
const SkMatrix* pattern_matrix,
- const FloatRect& src_rect);
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum);
// FIXME: Implement this to be less conservative.
bool CurrentFrameKnownToBeOpaque() override { return false; }
GeneratedImage(const FloatSize& size) : size_(size) {}
- virtual void DrawTile(GraphicsContext&, const FloatRect&) = 0;
+ virtual void DrawTile(GraphicsContext&,
+ const FloatRect&,
+ RespectImageOrientationEnum) = 0;
FloatSize size_;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/DEPS b/chromium/third_party/blink/renderer/platform/graphics/gpu/DEPS
index aa252c3bb21..3238ca1d6d7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/DEPS
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/DEPS
@@ -1,6 +1,5 @@
include_rules = [
"+components/viz/test/test_context_provider.h",
- "+mojo/public/cpp/bindings/binding.h",
"+mojo/public/cpp/system/platform_handle.h",
"+device/vr/public/mojom/vr_service.mojom-blink.h",
"+gpu/command_buffer/client/gles2_interface.h",
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 261c1b0512d..ee8aba554c6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -41,8 +41,6 @@
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/resources/transferable_resource.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
@@ -54,6 +52,7 @@
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
@@ -64,7 +63,6 @@
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
-#include "ui/gl/gpu_preference.h"
#include "v8/include/v8.h"
namespace blink {
@@ -193,7 +191,8 @@ DrawingBuffer::DrawingBuffer(
opengl_flip_y_extension_(
ContextProvider()->GetCapabilities().mesa_framebuffer_flip_y),
initial_gpu_(gpu_preference),
- current_active_gpu_(gpu_preference) {
+ current_active_gpu_(gpu_preference),
+ weak_factory_(this) {
// Used by browser tests to detect the use of a DrawingBuffer.
TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
TRACE_EVENT_SCOPE_GLOBAL);
@@ -393,11 +392,12 @@ bool DrawingBuffer::FinishPrepareTransferableResourceSoftware(
// This holds a ref on the DrawingBuffer that will keep it alive until the
// mailbox is released (and while the release callback is running). It also
// owns the SharedBitmap.
- auto func = WTF::Bind(&DrawingBuffer::MailboxReleasedSoftware,
- scoped_refptr<DrawingBuffer>(this),
- WTF::Passed(std::move(registered)));
+ auto func = base::BindOnce(&DrawingBuffer::MailboxReleasedSoftware,
+ weak_factory_.GetWeakPtr(),
+ WTF::Passed(std::move(registered)));
*out_release_callback = viz::SingleReleaseCallback::Create(std::move(func));
+ contents_changed_ = false;
ResetBuffersToAutoClear();
return true;
}
@@ -504,9 +504,8 @@ bool DrawingBuffer::FinishPrepareTransferableResourceGpu(
// This holds a ref on the DrawingBuffer that will keep it alive until the
// mailbox is released (and while the release callback is running).
- auto func =
- WTF::Bind(&DrawingBuffer::MailboxReleasedGpu,
- scoped_refptr<DrawingBuffer>(this), color_buffer_for_mailbox);
+ auto func = base::BindOnce(&DrawingBuffer::NotifyMailboxReleasedGpu,
+ color_buffer_for_mailbox);
*out_release_callback = viz::SingleReleaseCallback::Create(std::move(func));
}
@@ -518,18 +517,29 @@ bool DrawingBuffer::FinishPrepareTransferableResourceGpu(
return true;
}
+// static
+void DrawingBuffer::NotifyMailboxReleasedGpu(
+ scoped_refptr<ColorBuffer> color_buffer,
+ const gpu::SyncToken& sync_token,
+ bool lost_resource) {
+ DCHECK(color_buffer->owning_thread_ref == base::PlatformThread::CurrentRef());
+
+ // Update the SyncToken to ensure that we will wait for it even if we
+ // immediately destroy this buffer.
+ color_buffer->receive_sync_token = sync_token;
+ if (color_buffer->drawing_buffer) {
+ color_buffer->drawing_buffer->MailboxReleasedGpu(color_buffer,
+ lost_resource);
+ }
+}
+
void DrawingBuffer::MailboxReleasedGpu(scoped_refptr<ColorBuffer> color_buffer,
- const gpu::SyncToken& sync_token,
bool lost_resource) {
// If the mailbox has been returned by the compositor then it is no
// longer being presented, and so is no longer the front buffer.
if (color_buffer == front_color_buffer_)
front_color_buffer_ = nullptr;
- // Update the SyncToken to ensure that we will wait for it even if we
- // immediately destroy this buffer.
- color_buffer->receive_sync_token = sync_token;
-
if (destruction_in_progress_ || color_buffer->size != size_ ||
gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR || lost_resource ||
is_hidden_) {
@@ -561,8 +571,7 @@ void DrawingBuffer::MailboxReleasedSoftware(RegisteredBitmap registered,
recycled_bitmaps_.push_back(std::move(registered));
}
-scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage(
- std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
+scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage() {
ScopedStateRestorer scoped_state_restorer(this);
viz::TransferableResource transferable_resource;
@@ -583,35 +592,10 @@ scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage(
SkImage::MakeFromBitmap(black_bitmap));
}
+ DCHECK(release_callback);
DCHECK_EQ(size_.Width(), transferable_resource.size.width());
DCHECK_EQ(size_.Height(), transferable_resource.size.height());
- // Make our own textureId that is a reference on the same texture backing
- // being used as the front buffer (which was returned from
- // PrepareTransferableResourceInternal()). We do not need to wait on the sync
- // token in |transferable_resource| since the mailbox was produced on the same
- // |m_gl| context that we are using here. Similarly, the |release_callback|
- // will run on the same context so we don't need to send a sync token for this
- // consume action back to it.
- // TODO(danakj): Instead of using PrepareTransferableResourceInternal(), we
- // could just use the actual texture id and avoid needing to produce/consume a
- // mailbox.
- GLuint texture_id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM(
- transferable_resource.mailbox_holder.mailbox.name);
-
- if (out_release_callback) {
- // Allow the consumer to release the resource when done using it, so it can
- // be recycled.
- *out_release_callback = std::move(release_callback);
- } else {
- // Return the mailbox but report that the resource is lost to prevent trying
- // to use the backing for future frames. We keep it alive with our own
- // reference to the backing via our |textureId|.
- gpu::SyncToken sync_token;
- gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
- release_callback->Run(sync_token, true /* lost_resource */);
- }
-
// We reuse the same mailbox name from above since our texture id was consumed
// from it.
const auto& sk_image_mailbox = transferable_resource.mailbox_holder.mailbox;
@@ -623,12 +607,18 @@ scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage(
const auto& sk_image_sync_token =
transferable_resource.mailbox_holder.sync_token;
+ const SkImageInfo sk_image_info =
+ SkImageInfo::MakeN32Premul(size_.Width(), size_.Height());
+
// TODO(xidachen): Create a small pool of recycled textures from
// ImageBitmapRenderingContext's transferFromImageBitmap, and try to use them
// in DrawingBuffer.
- return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
- sk_image_mailbox, sk_image_sync_token, texture_id,
- context_provider_->GetWeakPtr(), size_, opengl_flip_y_extension_);
+ return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
+ sk_image_mailbox, sk_image_sync_token, /* shared_image_texture_id = */ 0,
+ sk_image_info, transferable_resource.mailbox_holder.texture_target,
+ /* is_origin_top_left = */ opengl_flip_y_extension_,
+ context_provider_->GetWeakPtr(), base::PlatformThread::CurrentRef(),
+ Thread::Current()->GetTaskRunner(), std::move(release_callback));
}
scoped_refptr<DrawingBuffer::ColorBuffer>
@@ -678,18 +668,29 @@ scoped_refptr<CanvasResource> DrawingBuffer::AsCanvasResource(
}
DrawingBuffer::ColorBuffer::ColorBuffer(
- DrawingBuffer* drawing_buffer,
+ base::WeakPtr<DrawingBuffer> drawing_buffer,
const IntSize& size,
GLuint texture_id,
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer,
gpu::Mailbox mailbox)
- : drawing_buffer(drawing_buffer),
+ : owning_thread_ref(base::PlatformThread::CurrentRef()),
+ drawing_buffer(std::move(drawing_buffer)),
size(size),
texture_id(texture_id),
gpu_memory_buffer(std::move(gpu_memory_buffer)),
mailbox(mailbox) {}
DrawingBuffer::ColorBuffer::~ColorBuffer() {
+ if (base::PlatformThread::CurrentRef() != owning_thread_ref ||
+ !drawing_buffer) {
+ // If the context has been destroyed no cleanup is necessary since all
+ // resources below are automatically destroyed. Note that if a ColorBuffer
+ // is being destroyed on a different thread, it implies that the owning
+ // thread was destroyed which means the associated context was also
+ // destroyed.
+ return;
+ }
+
gpu::gles2::GLES2Interface* gl = drawing_buffer->gl_;
gpu::SharedImageInterface* sii =
drawing_buffer->ContextProvider()->SharedImageInterface();
@@ -777,7 +778,7 @@ bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
if (ShouldUseChromiumImage()) {
// A CHROMIUM_image backed texture requires a specialized set of parameters
// on OSX.
- texture_target_ = GC3D_TEXTURE_RECTANGLE_ARB;
+ texture_target_ = gpu::GetPlatformSpecificTextureTarget();
}
#endif
@@ -850,15 +851,10 @@ bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
return true;
}
-bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
- GLenum dst_texture_target,
- GLuint dst_texture,
- GLint dst_level,
- bool premultiply_alpha,
- bool flip_y,
- const IntPoint& dst_texture_offset,
- const IntRect& src_sub_rectangle,
- SourceDrawingBuffer src_buffer) {
+template <typename CopyFunction>
+bool DrawingBuffer::CopyToPlatformInternal(gpu::InterfaceBase* dst_interface,
+ SourceDrawingBuffer src_buffer,
+ const CopyFunction& copy_function) {
ScopedStateRestorer scoped_state_restorer(this);
gpu::gles2::GLES2Interface* src_gl = gl_;
@@ -868,9 +864,6 @@ bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
src_gl->Flush();
}
- if (!Extensions3DUtil::CanUseCopyTextureCHROMIUM(dst_texture_target))
- return false;
-
// Contexts may be in a different share group. We must transfer the texture
// through a mailbox first.
gpu::Mailbox mailbox;
@@ -899,31 +892,12 @@ bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
return false;
}
- dst_gl->WaitSyncTokenCHROMIUM(produce_sync_token.GetConstData());
-
- GLuint src_texture =
- dst_gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name);
-
- GLboolean unpack_premultiply_alpha_needed = GL_FALSE;
- GLboolean unpack_unpremultiply_alpha_needed = GL_FALSE;
- if (want_alpha_channel_ && premultiplied_alpha_ && !premultiply_alpha)
- unpack_unpremultiply_alpha_needed = GL_TRUE;
- else if (want_alpha_channel_ && !premultiplied_alpha_ && premultiply_alpha)
- unpack_premultiply_alpha_needed = GL_TRUE;
+ dst_interface->WaitSyncTokenCHROMIUM(produce_sync_token.GetConstData());
- dst_gl->BeginSharedImageAccessDirectCHROMIUM(
- src_texture, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
- dst_gl->CopySubTextureCHROMIUM(
- src_texture, 0, dst_texture_target, dst_texture, dst_level,
- dst_texture_offset.X(), dst_texture_offset.Y(), src_sub_rectangle.X(),
- src_sub_rectangle.Y(), src_sub_rectangle.Width(),
- src_sub_rectangle.Height(), flip_y, unpack_premultiply_alpha_needed,
- unpack_unpremultiply_alpha_needed);
- dst_gl->EndSharedImageAccessDirectCHROMIUM(src_texture);
- dst_gl->DeleteTextures(1, &src_texture);
+ copy_function(mailbox);
gpu::SyncToken sync_token;
- dst_gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ dst_interface->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
src_gl->WaitSyncTokenCHROMIUM(sync_token.GetData());
if (texture_id_to_restore_access) {
src_gl->BeginSharedImageAccessDirectCHROMIUM(
@@ -933,6 +907,66 @@ bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
return true;
}
+bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
+ GLenum dst_texture_target,
+ GLuint dst_texture,
+ GLint dst_level,
+ bool premultiply_alpha,
+ bool flip_y,
+ const IntPoint& dst_texture_offset,
+ const IntRect& src_sub_rectangle,
+ SourceDrawingBuffer src_buffer) {
+ if (!Extensions3DUtil::CanUseCopyTextureCHROMIUM(dst_texture_target))
+ return false;
+
+ GLboolean unpack_premultiply_alpha_needed = GL_FALSE;
+ GLboolean unpack_unpremultiply_alpha_needed = GL_FALSE;
+ if (want_alpha_channel_ && premultiplied_alpha_ && !premultiply_alpha)
+ unpack_unpremultiply_alpha_needed = GL_TRUE;
+ else if (want_alpha_channel_ && !premultiplied_alpha_ && premultiply_alpha)
+ unpack_premultiply_alpha_needed = GL_TRUE;
+
+ auto copy_function = [&](gpu::Mailbox src_mailbox) {
+ GLuint src_texture =
+ dst_gl->CreateAndTexStorage2DSharedImageCHROMIUM(src_mailbox.name);
+ dst_gl->BeginSharedImageAccessDirectCHROMIUM(
+ src_texture, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
+ dst_gl->CopySubTextureCHROMIUM(
+ src_texture, 0, dst_texture_target, dst_texture, dst_level,
+ dst_texture_offset.X(), dst_texture_offset.Y(), src_sub_rectangle.X(),
+ src_sub_rectangle.Y(), src_sub_rectangle.Width(),
+ src_sub_rectangle.Height(), flip_y, unpack_premultiply_alpha_needed,
+ unpack_unpremultiply_alpha_needed);
+ dst_gl->EndSharedImageAccessDirectCHROMIUM(src_texture);
+ dst_gl->DeleteTextures(1, &src_texture);
+ };
+ return CopyToPlatformInternal(dst_gl, src_buffer, copy_function);
+}
+
+bool DrawingBuffer::CopyToPlatformMailbox(
+ gpu::raster::RasterInterface* dst_raster_interface,
+ gpu::Mailbox dst_mailbox,
+ GLenum dst_texture_target,
+ bool flip_y,
+ const IntPoint& dst_texture_offset,
+ const IntRect& src_sub_rectangle,
+ SourceDrawingBuffer src_buffer) {
+ GLboolean unpack_premultiply_alpha_needed = GL_FALSE;
+ if (want_alpha_channel_ && !premultiplied_alpha_)
+ unpack_premultiply_alpha_needed = GL_TRUE;
+
+ auto copy_function = [&](gpu::Mailbox src_mailbox) {
+ dst_raster_interface->CopySubTexture(
+ src_mailbox, dst_mailbox, dst_texture_target, dst_texture_offset.X(),
+ dst_texture_offset.Y(), src_sub_rectangle.X(), src_sub_rectangle.Y(),
+ src_sub_rectangle.Width(), src_sub_rectangle.Height(), flip_y,
+ unpack_premultiply_alpha_needed);
+ };
+
+ return CopyToPlatformInternal(dst_raster_interface, src_buffer,
+ copy_function);
+}
+
cc::Layer* DrawingBuffer::CcLayer() {
if (!layer_) {
layer_ = cc::TextureLayer::CreateForMailbox(this);
@@ -957,8 +991,6 @@ cc::Layer* DrawingBuffer::CcLayer() {
if (opengl_flip_y_extension_)
layer_->SetFlipped(false);
-
- GraphicsLayer::RegisterContentsLayer(layer_.get());
}
return layer_.get();
@@ -1012,9 +1044,6 @@ void DrawingBuffer::BeginDestruction() {
multisample_fbo_ = 0;
fbo_ = 0;
- if (layer_)
- GraphicsLayer::UnregisterContentsLayer(layer_.get());
-
client_ = nullptr;
}
@@ -1052,7 +1081,8 @@ bool DrawingBuffer::ResizeDefaultFramebuffer(const IntSize& size) {
premultiplied_alpha_false_mailbox_ = sii->CreateSharedImage(
format, static_cast<gfx::Size>(size), storage_color_space_,
gpu::SHARED_IMAGE_USAGE_GLES2 |
- gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT);
+ gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT |
+ gpu::SHARED_IMAGE_USAGE_RASTER);
gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
premultiplied_alpha_false_texture_ =
@@ -1618,8 +1648,9 @@ scoped_refptr<DrawingBuffer::ColorBuffer> DrawingBuffer::CreateColorBuffer(
// Import frontbuffer of swap chain into GL.
texture_id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM(
front_buffer_mailbox.name);
- front_color_buffer_ = base::AdoptRef(
- new ColorBuffer(this, size, texture_id, nullptr, front_buffer_mailbox));
+ front_color_buffer_ = base::MakeRefCounted<ColorBuffer>(
+ weak_factory_.GetWeakPtr(), size, texture_id, nullptr,
+ front_buffer_mailbox);
}
// Import the backbuffer of swap chain or allocated SharedImage into GL.
texture_id =
@@ -1646,9 +1677,9 @@ scoped_refptr<DrawingBuffer::ColorBuffer> DrawingBuffer::CreateColorBuffer(
gl_->DeleteFramebuffers(1, &fbo);
}
- return base::AdoptRef(new ColorBuffer(this, size, texture_id,
- std::move(gpu_memory_buffer),
- back_buffer_mailbox));
+ return base::MakeRefCounted<ColorBuffer>(
+ weak_factory_.GetWeakPtr(), size, texture_id,
+ std::move(gpu_memory_buffer), back_buffer_mailbox);
}
void DrawingBuffer::AttachColorBufferToReadFramebuffer() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index c4f0e99a8a9..9ac03f51f68 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -37,6 +37,9 @@
#include "cc/layers/texture_layer_client.h"
#include "cc/resources/cross_thread_shared_bitmap.h"
#include "cc/resources/shared_bitmap_id_registrar.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/config/gpu_feature_info.h"
@@ -225,10 +228,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
// contents of the front buffer. This is done without any pixel copies. The
// texture in the ImageBitmap is from the active ContextProvider on the
// DrawingBuffer.
- // If out_release_callback is null, the image is discarded. If it is non-null
- // the image must be recycled or discarded by calling *out_release_callback.
- scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(
- std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
+ scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage();
bool CopyToPlatformTexture(gpu::gles2::GLES2Interface*,
GLenum dst_target,
@@ -240,6 +240,14 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
const IntRect& src_sub_rectangle,
SourceDrawingBuffer);
+ bool CopyToPlatformMailbox(gpu::raster::RasterInterface*,
+ gpu::Mailbox dst_mailbox,
+ GLenum dst_texture_target,
+ bool flip_y,
+ const IntPoint& dst_texture_offset,
+ const IntRect& src_sub_rectangle,
+ SourceDrawingBuffer src_buffer);
+
sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer);
int SampleCount() const { return sample_count_; }
@@ -345,18 +353,22 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
bool pixel_pack_buffer_binding_dirty_ = false;
};
- struct ColorBuffer : public RefCounted<ColorBuffer> {
- ColorBuffer(DrawingBuffer*,
+ struct ColorBuffer : public base::RefCountedThreadSafe<ColorBuffer> {
+ ColorBuffer(base::WeakPtr<DrawingBuffer> drawing_buffer,
const IntSize&,
GLuint texture_id,
std::unique_ptr<gfx::GpuMemoryBuffer>,
gpu::Mailbox mailbox);
~ColorBuffer();
+ // The thread on which the ColorBuffer is created and the DrawingBuffer is
+ // bound to.
+ const base::PlatformThreadRef owning_thread_ref;
+
// The owning DrawingBuffer. Note that DrawingBuffer is explicitly destroyed
// by the beginDestruction method, which will eventually drain all of its
// ColorBuffers.
- scoped_refptr<DrawingBuffer> drawing_buffer;
+ base::WeakPtr<DrawingBuffer> drawing_buffer;
const IntSize size;
const GLuint texture_id = 0;
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
@@ -385,6 +397,11 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
DISALLOW_COPY_AND_ASSIGN(ColorBuffer);
};
+ template <typename CopyFunction>
+ bool CopyToPlatformInternal(gpu::InterfaceBase* dst_interface,
+ SourceDrawingBuffer src_buffer,
+ const CopyFunction& copy_function);
+
enum ClearOption { ClearOnlyMultisampledFBO, ClearAllFBOs };
// Clears out newly-allocated framebuffers (really, renderbuffers / textures).
@@ -420,8 +437,10 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
// Callbacks for mailboxes given to the compositor from
// FinishPrepareTransferableResource{Gpu,Software}.
+ static void NotifyMailboxReleasedGpu(scoped_refptr<ColorBuffer>,
+ const gpu::SyncToken&,
+ bool lost_resource);
void MailboxReleasedGpu(scoped_refptr<ColorBuffer>,
- const gpu::SyncToken&,
bool lost_resource);
void MailboxReleasedSoftware(RegisteredBitmap,
const gpu::SyncToken&,
@@ -617,9 +636,11 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
bool opengl_flip_y_extension_;
- gl::GpuPreference initial_gpu_;
+ const gl::GpuPreference initial_gpu_;
gl::GpuPreference current_active_gpu_;
+ base::WeakPtrFactory<DrawingBuffer> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(DrawingBuffer);
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
index 19d15ce32c4..537c1af0001 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
@@ -203,9 +203,8 @@ TEST_F(DrawingBufferTest, VerifyResizingProperlyAffectsResources) {
drawing_buffer_->BeginDestruction();
}
-TEST_F(DrawingBufferTest, VerifyDestructionCompleteAfterAllResourceReleased) {
- bool live = true;
- drawing_buffer_->live_ = &live;
+TEST_F(DrawingBufferTest, VerifySharedImagesReleasedAfterReleaseCallback) {
+ auto* sii = drawing_buffer_->SharedImageInterfaceForTests();
viz::TransferableResource resource1;
std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
@@ -231,67 +230,20 @@ TEST_F(DrawingBufferTest, VerifyDestructionCompleteAfterAllResourceReleased) {
EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3,
&release_callback3));
- EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
- release_callback1->Run(gpu::SyncToken(), false /* lostResource */);
-
- drawing_buffer_->BeginDestruction();
- ASSERT_EQ(live, true);
-
- DrawingBufferForTests* raw_pointer = drawing_buffer_.get();
- drawing_buffer_ = nullptr;
- ASSERT_EQ(live, true);
-
- EXPECT_FALSE(raw_pointer->MarkContentsChanged());
- release_callback2->Run(gpu::SyncToken(), false /* lostResource */);
- ASSERT_EQ(live, true);
-
- EXPECT_FALSE(raw_pointer->MarkContentsChanged());
- release_callback3->Run(gpu::SyncToken(), false /* lostResource */);
- ASSERT_EQ(live, false);
-}
-
-TEST_F(DrawingBufferTest, verifyDrawingBufferStaysAliveIfResourcesAreLost) {
- bool live = true;
- drawing_buffer_->live_ = &live;
-
- viz::TransferableResource resource1;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
- viz::TransferableResource resource2;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
- viz::TransferableResource resource3;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback3;
-
- EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
- EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource1,
- &release_callback1));
- VerifyStateWasRestored();
- EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
- EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource2,
- &release_callback2));
- VerifyStateWasRestored();
- EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
- EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3,
- &release_callback3));
- VerifyStateWasRestored();
+ EXPECT_EQ(sii->shared_image_count(), 4u);
EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
release_callback1->Run(gpu::SyncToken(), true /* lostResource */);
- EXPECT_EQ(live, true);
+ EXPECT_EQ(sii->shared_image_count(), 3u);
- drawing_buffer_->BeginDestruction();
- EXPECT_EQ(live, true);
+ release_callback2->Run(gpu::SyncToken(), true /* lostResource */);
+ EXPECT_EQ(sii->shared_image_count(), 2u);
- EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
- release_callback2->Run(gpu::SyncToken(), false /* lostResource */);
- EXPECT_EQ(live, true);
-
- DrawingBufferForTests* raw_ptr = drawing_buffer_.get();
- drawing_buffer_ = nullptr;
- EXPECT_EQ(live, true);
+ // The resource is not marked lost so it's recycled after the callback.
+ release_callback3->Run(gpu::SyncToken(), false /* lostResource */);
+ EXPECT_EQ(sii->shared_image_count(), 2u);
- EXPECT_FALSE(raw_ptr->MarkContentsChanged());
- release_callback3->Run(gpu::SyncToken(), true /* lostResource */);
- EXPECT_EQ(live, false);
+ drawing_buffer_->BeginDestruction();
}
TEST_F(DrawingBufferTest, VerifyOnlyOneRecycledResourceMustBeKept) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
index 61445894ffc..bf4f933c401 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
@@ -60,8 +60,8 @@ class WebGraphicsContext3DProviderForTests
const WebglPreferences& GetWebglPreferences() const override {
return webgl_preferences_;
}
- viz::GLHelper* GetGLHelper() override { return nullptr; }
- void SetLostContextCallback(base::Closure) override {}
+ gpu::GLHelper* GetGLHelper() override { return nullptr; }
+ void SetLostContextCallback(base::RepeatingClosure) override {}
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t id)>) override {}
cc::ImageDecodeCache* ImageDecodeCache(SkColorType color_type) override {
@@ -279,9 +279,9 @@ class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub,
// ImplementationBase implementation
void GenSyncTokenCHROMIUM(GLbyte* sync_token) override {
- static uint64_t unique_id = 1;
- gpu::SyncToken source(
- gpu::GPU_IO, gpu::CommandBufferId::FromUnsafeValue(unique_id++), 2);
+ static gpu::CommandBufferId::Generator command_buffer_id_generator;
+ gpu::SyncToken source(gpu::GPU_IO,
+ command_buffer_id_generator.GenerateNextId(), 2);
memcpy(sync_token, &source, sizeof(source));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc
index 50308ffc6b2..388559e7630 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.cc
@@ -9,6 +9,7 @@
#include "base/memory/ptr_util.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/common/gles2_cmd_copy_texture_chromium_utils.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
namespace blink {
@@ -75,6 +76,12 @@ bool Extensions3DUtil::IsExtensionEnabled(const String& name) {
return enabled_extensions_.Contains(name);
}
+// static
+bool Extensions3DUtil::CopyTextureCHROMIUMNeedsESSL3(GLenum dest_format) {
+ return gpu::gles2::CopyTextureCHROMIUMNeedsESSL3(dest_format);
+}
+
+// static
bool Extensions3DUtil::CanUseCopyTextureCHROMIUM(GLenum dest_target) {
switch (dest_target) {
case GL_TEXTURE_2D:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h
index 062807c497f..6a214156502 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h
@@ -38,6 +38,7 @@ class PLATFORM_EXPORT Extensions3DUtil final {
bool EnsureExtensionEnabled(const String& name);
bool IsExtensionEnabled(const String& name);
+ static bool CopyTextureCHROMIUMNeedsESSL3(GLenum dest_format);
static bool CanUseCopyTextureCHROMIUM(GLenum dest_target);
private:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
index 68c1c5063ca..2d15555c764 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
@@ -12,94 +12,8 @@
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/gpu/GrContext.h"
-namespace {
-
-struct GrTextureMailboxReleaseProcData {
- GrTexture* gr_texture_;
- base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper_;
-};
-
-void GrTextureMailboxReleaseProc(void* data) {
- GrTextureMailboxReleaseProcData* release_proc_data =
- static_cast<GrTextureMailboxReleaseProcData*>(data);
-
- if (release_proc_data->context_provider_wrapper_) {
- release_proc_data->context_provider_wrapper_->Utils()->RemoveCachedMailbox(
- release_proc_data->gr_texture_);
- }
-
- delete release_proc_data;
-}
-
-} // unnamed namespace
-
namespace blink {
-bool GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
- GLenum& out_texture_target,
- const sk_sp<SkImage>& image,
- GLenum filter) {
- // This object is owned by context_provider_wrapper_, so that weak ref
- // should never be null.
- DCHECK(context_provider_wrapper_);
- DCHECK(image->isTextureBacked());
- GrContext* gr = context_provider_wrapper_->ContextProvider()->GetGrContext();
- gpu::gles2::GLES2Interface* gl =
- context_provider_wrapper_->ContextProvider()->ContextGL();
-
- DCHECK(gr);
- DCHECK(gl);
- GrTexture* gr_texture = image->getTexture();
- if (!gr_texture)
- return false;
-
- DCHECK(gr == gr_texture->getContext());
-
- GrBackendTexture backend_texture = image->getBackendTexture(true);
- DCHECK(backend_texture.isValid());
-
- GrGLTextureInfo info;
- bool result = backend_texture.getGLTextureInfo(&info);
- DCHECK(result);
-
- GLuint texture_id = info.fID;
- GLenum texture_target = info.fTarget;
- out_texture_target = texture_target;
-
- auto it = cached_mailboxes_.find(gr_texture);
- if (it != cached_mailboxes_.end()) {
- out_mailbox = it->value;
- } else {
- gl->ProduceTextureDirectCHROMIUM(texture_id, out_mailbox.name);
-
- GrTextureMailboxReleaseProcData* release_proc_data =
- new GrTextureMailboxReleaseProcData();
- release_proc_data->gr_texture_ = gr_texture;
- release_proc_data->context_provider_wrapper_ = context_provider_wrapper_;
- gr_texture->setRelease(GrTextureMailboxReleaseProc, release_proc_data);
- cached_mailboxes_.insert(gr_texture, out_mailbox);
- }
- gl->BindTexture(texture_target, texture_id);
- gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, filter);
- gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, filter);
- gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->BindTexture(texture_target, 0);
- gr_texture->textureParamsModified();
- return true;
-}
-
-void GraphicsContext3DUtils::RegisterMailbox(GrTexture* gr_texture,
- const gpu::Mailbox& mailbox) {
- DCHECK(cached_mailboxes_.find(gr_texture) == cached_mailboxes_.end());
- cached_mailboxes_.insert(gr_texture, mailbox);
-}
-
-void GraphicsContext3DUtils::RemoveCachedMailbox(GrTexture* gr_texture) {
- cached_mailboxes_.erase(gr_texture);
-}
-
bool GraphicsContext3DUtils::Accelerated2DCanvasFeatureEnabled() {
// Don't use accelerated canvas if compositor is in software mode.
if (!SharedGpuContext::IsGpuCompositingEnabled())
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
index 403becdd9f4..f18a0a18cd2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/gpu/GrTexture.h"
typedef unsigned int GLenum;
@@ -30,22 +29,10 @@ class PLATFORM_EXPORT GraphicsContext3DUtils {
context_provider_wrapper)
: context_provider_wrapper_(std::move(context_provider_wrapper)) {}
- // Use this service to create a new mailbox or possibly obtain a pre-existing
- // mailbox for a given texture. The caching of pre-existing mailboxes survives
- // when the texture gets recycled by skia for creating a new SkSurface or
- // SkImage with a pre-existing GrTexture backing.
- bool GetMailboxForSkImage(gpu::Mailbox&,
- GLenum&,
- const sk_sp<SkImage>&,
- GLenum filter);
- void RegisterMailbox(GrTexture*, const gpu::Mailbox&);
- void RemoveCachedMailbox(GrTexture*);
-
bool Accelerated2DCanvasFeatureEnabled();
private:
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
- WTF::HashMap<GrTexture*, gpu::Mailbox> cached_mailboxes_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
index 966ee2547d7..e8a21596af5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -11,10 +11,13 @@
#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
@@ -24,6 +27,29 @@
#include "ui/gfx/geometry/size.h"
namespace blink {
+namespace {
+
+scoped_refptr<StaticBitmapImage> MakeAccelerated(
+ const scoped_refptr<StaticBitmapImage>& source,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>
+ context_provider_wrapper) {
+ if (source->IsTextureBacked())
+ return source;
+
+ auto paint_image = source->PaintImageForCurrentFrame();
+ auto provider = CanvasResourceProvider::CreateSharedImageProvider(
+ source->Size(), context_provider_wrapper, kLow_SkFilterQuality,
+ CanvasColorParams(paint_image.GetSkImage()->imageInfo()),
+ source->IsOriginTopLeft(), CanvasResourceProvider::RasterMode::kGPU,
+ gpu::SHARED_IMAGE_USAGE_DISPLAY);
+ if (!provider || !provider->IsAccelerated())
+ return nullptr;
+
+ provider->Canvas()->drawImage(paint_image, 0, 0, nullptr);
+ return provider->Snapshot();
+}
+
+} // namespace
ImageLayerBridge::ImageLayerBridge(OpacityMode opacity_mode)
: opacity_mode_(opacity_mode) {
@@ -35,7 +61,6 @@ ImageLayerBridge::ImageLayerBridge(OpacityMode opacity_mode)
layer_->SetContentsOpaque(true);
layer_->SetBlendBackgroundColor(false);
}
- GraphicsLayer::RegisterContentsLayer(layer_.get());
}
ImageLayerBridge::~ImageLayerBridge() {
@@ -86,7 +111,6 @@ void ImageLayerBridge::SetUV(const FloatPoint& left_top,
void ImageLayerBridge::Dispose() {
if (layer_) {
- GraphicsLayer::UnregisterContentsLayer(layer_.get());
layer_->ClearClient();
layer_ = nullptr;
}
@@ -122,19 +146,22 @@ bool ImageLayerBridge::PrepareTransferableResource(
if (gpu_compositing) {
scoped_refptr<StaticBitmapImage> image_for_compositor =
- image_->MakeAccelerated(SharedGpuContext::ContextProviderWrapper());
- if (!image_for_compositor)
+ MakeAccelerated(image_, SharedGpuContext::ContextProviderWrapper());
+ if (!image_for_compositor || !image_for_compositor->ContextProvider())
return false;
const gfx::Size size(image_for_compositor->width(),
image_for_compositor->height());
uint32_t filter =
filter_quality_ == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
- image_for_compositor->EnsureMailbox(kUnverifiedSyncToken, filter);
+ auto mailbox_holder = image_for_compositor->GetMailboxHolder();
+ auto* sii = image_for_compositor->ContextProvider()->SharedImageInterface();
+ bool is_overlay_candidate = sii->UsageForMailbox(mailbox_holder.mailbox) &
+ gpu::SHARED_IMAGE_USAGE_SCANOUT;
+
*out_resource = viz::TransferableResource::MakeGL(
- image_for_compositor->GetMailbox(), filter, GL_TEXTURE_2D,
- image_for_compositor->GetSyncToken(), size,
- false /* is_overlay_candidate */);
+ mailbox_holder.mailbox, filter, mailbox_holder.texture_target,
+ mailbox_holder.sync_token, size, is_overlay_candidate);
auto func =
WTF::Bind(&ImageLayerBridge::ResourceReleasedGpu,
WrapWeakPersistent(this), std::move(image_for_compositor));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
index d550eb47af5..acfd1b59240 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
@@ -57,7 +57,7 @@ class PLATFORM_EXPORT ImageLayerBridge
bool IsAccelerated() { return image_ && image_->IsTextureBacked(); }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
// SharedMemory bitmap that was registered with SharedBitmapIdRegistrar. Used
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
index 1592804d496..82b5c4a5fd9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
@@ -9,6 +9,7 @@
#include "base/test/null_task_runner.h"
#include "components/viz/test/test_gles2_interface.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/common/capabilities.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h"
@@ -38,7 +39,12 @@ class SharedGpuContextTestBase : public Test {
-> std::unique_ptr<WebGraphicsContext3DProvider> {
*gpu_compositing_disabled = false;
gl->SetIsContextLost(false);
- return std::make_unique<FakeWebGraphicsContext3DProvider>(gl);
+ auto fake_context =
+ std::make_unique<FakeWebGraphicsContext3DProvider>(gl);
+ gpu::Capabilities capabilities;
+ capabilities.max_texture_size = 20;
+ fake_context->SetCapabilities(capabilities);
+ return fake_context;
};
SharedGpuContext::SetContextProviderFactoryForTesting(
WTF::BindRepeating(factory, WTF::Unretained(&gl_)));
@@ -120,6 +126,27 @@ class SoftwareCompositingTest : public Test {
FakeGLES2Interface gl_;
};
+class SharedGpuContextTestViz : public Test {
+ public:
+ void SetUp() override {
+ task_runner_ = base::MakeRefCounted<base::NullTaskRunner>();
+ handle_ = std::make_unique<base::ThreadTaskRunnerHandle>(task_runner_);
+ test_context_provider_ = viz::TestContextProvider::Create();
+ InitializeSharedGpuContext(test_context_provider_.get(),
+ /*cache = */ nullptr,
+ SetIsContextLost::kSetToFalse);
+ }
+
+ void TearDown() override {
+ handle_.reset();
+ task_runner_.reset();
+ SharedGpuContext::ResetForTesting();
+ }
+ scoped_refptr<base::NullTaskRunner> task_runner_;
+ std::unique_ptr<base::ThreadTaskRunnerHandle> handle_;
+ scoped_refptr<viz::TestContextProvider> test_context_provider_;
+};
+
TEST_F(SharedGpuContextTest, contextLossAutoRecovery) {
EXPECT_NE(SharedGpuContext::ContextProviderWrapper(), nullptr);
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context =
@@ -133,26 +160,6 @@ TEST_F(SharedGpuContextTest, contextLossAutoRecovery) {
EXPECT_FALSE(!!context);
}
-TEST_F(SharedGpuContextTest, AccelerateImageBufferSurfaceAutoRecovery) {
- // Verifies that after a context loss, attempting to allocate an
- // AcceleratedImageBufferSurface will restore the context and succeed
- gl_.SetIsContextLost(true);
- EXPECT_FALSE(SharedGpuContext::IsValidWithoutRestoring());
- IntSize size(10, 10);
- std::unique_ptr<CanvasResourceProvider> resource_provider =
- CanvasResourceProvider::Create(
- size,
- CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(),
- 0, // msaa_sample_count
- kLow_SkFilterQuality, CanvasColorParams(),
- CanvasResourceProvider::kDefaultPresentationMode,
- nullptr // canvas_resource_dispatcher
- );
- EXPECT_TRUE(resource_provider && resource_provider->IsValid());
- EXPECT_TRUE(SharedGpuContext::IsValidWithoutRestoring());
-}
-
TEST_F(SharedGpuContextTest, Canvas2DLayerBridgeAutoRecovery) {
// Verifies that after a context loss, attempting to allocate a
// Canvas2DLayerBridge will restore the context and succeed.
@@ -181,20 +188,16 @@ TEST_F(BadSharedGpuContextTest, AllowSoftwareToAcceleratedCanvasUpgrade) {
}
TEST_F(BadSharedGpuContextTest, AccelerateImageBufferSurfaceCreationFails) {
- // With a bad shared context, AccelerateImageBufferSurface creation should
- // fail gracefully
+ // With a bad shared context, AccelerateImageBufferSurface should fail and
+ // return a nullptr provider
IntSize size(10, 10);
std::unique_ptr<CanvasResourceProvider> resource_provider =
- CanvasResourceProvider::Create(
- size,
- CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(),
- 0, // msaa_sample_count
+ CanvasResourceProvider::CreateSharedImageProvider(
+ size, SharedGpuContext::ContextProviderWrapper(),
kLow_SkFilterQuality, CanvasColorParams(),
- CanvasResourceProvider::kDefaultPresentationMode,
- nullptr // canvas_resource_dispatcher
- );
- EXPECT_FALSE(!resource_provider);
+ true /*is_origin_top_left*/, CanvasResourceProvider::RasterMode::kGPU,
+ 0u /*shared_image_usage_flags*/);
+ EXPECT_FALSE(resource_provider);
}
TEST_F(SharedGpuContextTest, CompositingMode) {
@@ -209,51 +212,21 @@ TEST_F(SoftwareCompositingTest, CompositingMode) {
EXPECT_FALSE(SharedGpuContext::IsGpuCompositingEnabled());
}
-class MailboxSharedGpuContextTest : public Test {
- public:
- void SetUp() override {
- task_runner_ = base::MakeRefCounted<base::NullTaskRunner>();
- handle_ = std::make_unique<base::ThreadTaskRunnerHandle>(task_runner_);
- context_ = viz::TestContextProvider::Create();
- InitializeSharedGpuContext(context_.get());
- }
-
- scoped_refptr<viz::TestContextProvider> context_;
- scoped_refptr<base::NullTaskRunner> task_runner_;
- std::unique_ptr<base::ThreadTaskRunnerHandle> handle_;
-};
-
-TEST_F(MailboxSharedGpuContextTest, MailboxCaching) {
+TEST_F(SharedGpuContextTestViz, AccelerateImageBufferSurfaceAutoRecovery) {
+ // Verifies that after a context loss, attempting to allocate an
+ // AcceleratedImageBufferSurface will restore the context and succeed
+ test_context_provider_->TestContextGL()->set_context_lost(true);
+ EXPECT_FALSE(SharedGpuContext::IsValidWithoutRestoring());
IntSize size(10, 10);
std::unique_ptr<CanvasResourceProvider> resource_provider =
- CanvasResourceProvider::Create(
- size,
- CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(),
- 0, // msaa_sample_count
+ CanvasResourceProvider::CreateSharedImageProvider(
+ size, SharedGpuContext::ContextProviderWrapper(),
kLow_SkFilterQuality, CanvasColorParams(),
- CanvasResourceProvider::kDefaultPresentationMode,
- nullptr // canvas_resource_dispatcher
- );
- ASSERT_TRUE(resource_provider->IsAccelerated());
+ true /*is_origin_top_left*/, CanvasResourceProvider::RasterMode::kGPU,
+ 0u /*shared_image_usage_flags*/);
EXPECT_TRUE(resource_provider && resource_provider->IsValid());
- scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot();
- GLenum texture_target = GL_TEXTURE_2D;
- gpu::Mailbox mailbox[3];
-
- // Creating the SkImage representation from the shared image mailbox registers
- // the same mailbox mapping to this SkImage with the cache. This ensures we
- // don't recreate a non-shared image mailbox if going from SkImage to mailbox.
- mailbox[0] = image->GetMailbox();
- SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox[1], texture_target,
- image->PaintImageForCurrentFrame().GetSkImage(), GL_NEAREST);
- EXPECT_EQ(mailbox[0], mailbox[1]);
-
- SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox[2], texture_target,
- image->PaintImageForCurrentFrame().GetSkImage(), GL_NEAREST);
- EXPECT_EQ(mailbox[1], mailbox[2]);
+ EXPECT_TRUE(resource_provider->IsAccelerated());
+ EXPECT_TRUE(SharedGpuContext::IsValidWithoutRestoring());
}
} // unnamed namespace
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
index 08aea5a6e62..0736906278c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
@@ -2858,7 +2858,11 @@ void WebGLImageConversion::ImageExtractor::ExtractImage(
if (!skia_image)
return;
- image_source_format_ = SK_B32_SHIFT ? kDataFormatRGBA8 : kDataFormatBGRA8;
+#if SK_B32_SHIFT
+ image_source_format_ = kDataFormatRGBA8;
+#else
+ image_source_format_ = kDataFormatBGRA8;
+#endif
image_source_unpack_alignment_ =
0; // FIXME: this seems to always be zero - why use at all?
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc
new file mode 100644
index 00000000000..241c2c76d2a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc
@@ -0,0 +1,82 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h"
+
+#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+
+namespace blink {
+
+namespace {
+static constexpr uint64_t kDawnRowPitchAlignmentBits = 8;
+
+// Calculate row pitch for T2B/B2T copy
+// TODO(shaobo.yan@intel.com): Using Dawn's constants once they are exposed
+uint64_t AlignWebGPURowPitch(uint64_t bytesPerRow) {
+ return (((bytesPerRow - 1) >> kDawnRowPitchAlignmentBits) + 1)
+ << kDawnRowPitchAlignmentBits;
+}
+
+} // anonymous namespace
+
+WebGPUImageUploadSizeInfo ComputeImageBitmapWebGPUUploadSizeInfo(
+ const IntRect& rect,
+ const CanvasColorParams& color_params) {
+ WebGPUImageUploadSizeInfo info;
+ uint64_t bytes_per_pixel = color_params.BytesPerPixel();
+
+ uint64_t row_pitch = AlignWebGPURowPitch(rect.Width() * bytes_per_pixel);
+
+ // Currently, row pitch for buffer copy view in WebGPU is an uint32_t type
+ // value and the maximum value is std::numeric_limits<uint32_t>::max().
+ DCHECK(row_pitch <= std::numeric_limits<uint32_t>::max());
+
+ info.wgpu_row_pitch = static_cast<uint32_t>(row_pitch);
+ info.size_in_bytes = row_pitch * rect.Height();
+
+ return info;
+}
+
+bool CopyBytesFromImageBitmapForWebGPU(scoped_refptr<StaticBitmapImage> image,
+ base::span<uint8_t> dst,
+ const IntRect& rect,
+ const CanvasColorParams& color_params) {
+ DCHECK(image);
+ DCHECK_GT(dst.size(), static_cast<size_t>(0));
+ DCHECK(image->width() - rect.X() >= rect.Width());
+ DCHECK(image->height() - rect.Y() >= rect.Height());
+
+ WebGPUImageUploadSizeInfo wgpu_info =
+ ComputeImageBitmapWebGPUUploadSizeInfo(rect, color_params);
+ DCHECK_EQ(static_cast<uint64_t>(dst.size()), wgpu_info.size_in_bytes);
+
+ // Prepare extract data from SkImage.
+ // TODO(shaobo.yan@intel.com): Make sure the data is in the correct format for
+ // copying to WebGPU
+ SkColorType color_type =
+ (color_params.GetSkColorType() == kRGBA_F16_SkColorType)
+ ? kRGBA_F16_SkColorType
+ : kRGBA_8888_SkColorType;
+
+ // Read pixel request dst info.
+ SkImageInfo info = SkImageInfo::Make(
+ rect.Width(), rect.Height(), color_type, kUnpremul_SkAlphaType,
+ color_params.GetSkColorSpaceForSkSurfaces());
+
+ sk_sp<SkImage> sk_image = image->PaintImageForCurrentFrame().GetSkImage();
+
+ if (!sk_image)
+ return false;
+
+ bool read_pixels_successful = sk_image->readPixels(
+ info, dst.data(), wgpu_info.wgpu_row_pitch, rect.X(), rect.Y());
+
+ if (!read_pixels_successful) {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h
new file mode 100644
index 00000000000..4f6c690d7b3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_IMAGE_BITMAP_HANDLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_IMAGE_BITMAP_HANDLER_H_
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+
+namespace blink {
+
+struct WebGPUImageUploadSizeInfo {
+ uint64_t size_in_bytes;
+ uint32_t wgpu_row_pitch;
+};
+
+class CanvasColorParams;
+class IntRect;
+class StaticBitmapImage;
+
+WebGPUImageUploadSizeInfo PLATFORM_EXPORT
+ComputeImageBitmapWebGPUUploadSizeInfo(const IntRect& rect,
+ const CanvasColorParams& color_params);
+bool PLATFORM_EXPORT
+CopyBytesFromImageBitmapForWebGPU(scoped_refptr<StaticBitmapImage> image,
+ base::span<uint8_t> dst,
+ const IntRect& rect,
+ const CanvasColorParams& color_params);
+} // namespace blink
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_IMAGE_BITMAP_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc
new file mode 100644
index 00000000000..f2c4766e921
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc
@@ -0,0 +1,110 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+
+namespace blink {
+
+static constexpr uint64_t kMaxArrayLength = 40000;
+
+class WebGPUImageBitmapHandlerTest : public testing::Test {
+ protected:
+ void SetUp() override {}
+
+ void VerifyCopyBytesForWebGPU(uint64_t width,
+ uint64_t height,
+ SkImageInfo info,
+ CanvasColorParams param,
+ IntRect copyRect) {
+ const uint64_t content_length = width * height * param.BytesPerPixel();
+ std::array<uint8_t, kMaxArrayLength> contents = {0};
+ // Initialize contents.
+ for (size_t i = 0; i < content_length; ++i) {
+ contents[i] = i % std::numeric_limits<uint8_t>::max();
+ }
+
+ sk_sp<SkData> image_pixels =
+ SkData::MakeWithCopy(contents.data(), content_length);
+ scoped_refptr<StaticBitmapImage> image =
+ StaticBitmapImage::Create(std::move(image_pixels), info);
+
+ WebGPUImageUploadSizeInfo wgpu_info =
+ ComputeImageBitmapWebGPUUploadSizeInfo(copyRect, param);
+
+ const uint64_t result_length = wgpu_info.size_in_bytes;
+ std::array<uint8_t, kMaxArrayLength> results = {0};
+ bool success = CopyBytesFromImageBitmapForWebGPU(
+ image, base::span<uint8_t>(results.data(), result_length), copyRect,
+ param);
+ ASSERT_EQ(success, true);
+
+ // Compare content and results
+ uint32_t row_pitch = wgpu_info.wgpu_row_pitch;
+ uint32_t content_row_index =
+ (copyRect.Y() * width + copyRect.X()) * param.BytesPerPixel();
+ uint32_t result_row_index = 0;
+ for (int i = 0; i < copyRect.Height(); ++i) {
+ EXPECT_EQ(0,
+ memcmp(&contents[content_row_index], &results[result_row_index],
+ copyRect.Width() * param.BytesPerPixel()));
+ content_row_index += width * param.BytesPerPixel();
+ result_row_index += row_pitch;
+ }
+ }
+};
+
+// Test calculate size
+TEST_F(WebGPUImageBitmapHandlerTest, VerifyGetWGPUResourceInfo) {
+ uint64_t imageWidth = 63;
+ uint64_t imageHeight = 1;
+ CanvasColorParams param(CanvasColorSpace::kSRGB, CanvasPixelFormat::kRGBA8,
+ OpacityMode::kNonOpaque);
+
+ // Prebaked expected values.
+ uint32_t expected_row_pitch = 256;
+ uint64_t expected_size = 256;
+
+ IntRect test_rect(0, 0, imageWidth, imageHeight);
+ WebGPUImageUploadSizeInfo info =
+ ComputeImageBitmapWebGPUUploadSizeInfo(test_rect, param);
+ ASSERT_EQ(expected_size, info.size_in_bytes);
+ ASSERT_EQ(expected_row_pitch, info.wgpu_row_pitch);
+}
+
+// Copy full image bitmap test
+TEST_F(WebGPUImageBitmapHandlerTest, VerifyCopyBytesFromImageBitmapForWebGPU) {
+ uint64_t imageWidth = 4;
+ uint64_t imageHeight = 2;
+ SkImageInfo info = SkImageInfo::Make(
+ imageWidth, imageHeight, SkColorType::kRGBA_8888_SkColorType,
+ SkAlphaType::kUnpremul_SkAlphaType, SkColorSpace::MakeSRGB());
+
+ IntRect image_data_rect(0, 0, imageWidth, imageHeight);
+ CanvasColorParams color_params(CanvasColorSpace::kSRGB,
+ CanvasPixelFormat::kRGBA8,
+ OpacityMode::kNonOpaque);
+ VerifyCopyBytesForWebGPU(imageWidth, imageHeight, info, color_params,
+ image_data_rect);
+}
+
+// Copy sub image bitmap test
+TEST_F(WebGPUImageBitmapHandlerTest, VerifyCopyBytesFromSubImageBitmap) {
+ uint64_t imageWidth = 63;
+ uint64_t imageHeight = 4;
+ SkImageInfo info = SkImageInfo::Make(
+ imageWidth, imageHeight, SkColorType::kRGBA_8888_SkColorType,
+ SkAlphaType::kUnpremul_SkAlphaType, SkColorSpace::MakeSRGB());
+
+ IntRect image_data_rect(2, 2, 60, 2);
+ CanvasColorParams color_params(CanvasColorSpace::kSRGB,
+ CanvasPixelFormat::kRGBA8,
+ OpacityMode::kNonOpaque);
+ VerifyCopyBytesForWebGPU(imageWidth, imageHeight, info, color_params,
+ image_data_rect);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index d2fd96c760f..98dc0c889fc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -29,10 +29,12 @@ viz::ResourceFormat WGPUFormatToViz(WGPUTextureFormat format) {
WebGPUSwapBufferProvider::WebGPUSwapBufferProvider(
Client* client,
scoped_refptr<DawnControlClientHolder> dawn_control_client,
+ uint64_t device_client_id,
WGPUTextureUsage usage,
WGPUTextureFormat format)
: dawn_control_client_(dawn_control_client),
client_(client),
+ device_client_id_(device_client_id),
usage_(usage),
format_(WGPUFormatToViz(format)) {
// Create a layer that will be used by the canvas and will ask for a
@@ -48,8 +50,6 @@ WebGPUSwapBufferProvider::WebGPUSwapBufferProvider(
// paths to keep the rendering correct in that cases.
layer_->SetContentsOpaque(true);
layer_->SetPremultipliedAlpha(true);
-
- GraphicsLayer::RegisterContentsLayer(layer_.get());
}
WebGPUSwapBufferProvider::~WebGPUSwapBufferProvider() {
@@ -67,7 +67,6 @@ void WebGPUSwapBufferProvider::Neuter() {
}
if (layer_) {
- GraphicsLayer::UnregisterContentsLayer(layer_.get());
layer_->ClearClient();
layer_ = nullptr;
}
@@ -85,8 +84,7 @@ void WebGPUSwapBufferProvider::Neuter() {
neutered_ = true;
}
-WGPUTexture WebGPUSwapBufferProvider::GetNewTexture(WGPUDevice device,
- const IntSize& size) {
+WGPUTexture WebGPUSwapBufferProvider::GetNewTexture(const IntSize& size) {
DCHECK(!current_swap_buffer_ && !dawn_control_client_->IsDestroyed());
gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
@@ -97,28 +95,27 @@ WGPUTexture WebGPUSwapBufferProvider::GetNewTexture(WGPUDevice device,
// TODO(cwallez@chromium.org): have some recycling mechanism.
gpu::Mailbox mailbox = sii->CreateSharedImage(
format_, static_cast<gfx::Size>(size), gfx::ColorSpace::CreateSRGB(),
- gpu::SHARED_IMAGE_USAGE_WEBGPU | gpu::SHARED_IMAGE_USAGE_DISPLAY);
+ gpu::SHARED_IMAGE_USAGE_WEBGPU |
+ gpu::SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE |
+ gpu::SHARED_IMAGE_USAGE_DISPLAY);
gpu::SyncToken creation_token = sii->GenUnverifiedSyncToken();
current_swap_buffer_ = base::AdoptRef(new SwapBuffer(
this, mailbox, creation_token, static_cast<gfx::Size>(size)));
- // Make sure previous Dawn wire commands are sent so that for example the ID
- // is freed before we associate the SharedImage.
- webgpu->FlushCommands();
-
// Ensure the shared image is allocated service-side before working with it
webgpu->WaitSyncTokenCHROMIUM(
current_swap_buffer_->access_finished_token.GetConstData());
// Associate the mailbox to a dawn_wire client DawnTexture object
- gpu::webgpu::ReservedTexture reservation = webgpu->ReserveTexture(device);
+ gpu::webgpu::ReservedTexture reservation =
+ webgpu->ReserveTexture(device_client_id_);
DCHECK(reservation.texture);
wire_texture_id_ = reservation.id;
wire_texture_generation_ = reservation.generation;
webgpu->AssociateMailbox(
- 0, 0, reservation.id, reservation.generation, usage_,
+ device_client_id_, 0, reservation.id, reservation.generation, usage_,
reinterpret_cast<GLbyte*>(&current_swap_buffer_->mailbox));
// When the page request a texture it means we'll need to present it on the
@@ -146,7 +143,8 @@ bool WebGPUSwapBufferProvider::PrepareTransferableResource(
// to the texture are errors.
gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
DCHECK_NE(wire_texture_id_, 0u);
- webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
+ webgpu->DissociateMailbox(device_client_id_, wire_texture_id_,
+ wire_texture_generation_);
// Make the compositor wait on previous Dawn commands.
webgpu->GenUnverifiedSyncTokenCHROMIUM(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
index 601e49b0f6c..e1a6ae443cf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
@@ -35,13 +35,14 @@ class PLATFORM_EXPORT WebGPUSwapBufferProvider
WebGPUSwapBufferProvider(
Client* client,
scoped_refptr<DawnControlClientHolder> dawn_control_client,
+ uint64_t device_client_id,
WGPUTextureUsage usage,
WGPUTextureFormat format);
~WebGPUSwapBufferProvider() override;
cc::Layer* CcLayer();
void Neuter();
- WGPUTexture GetNewTexture(WGPUDevice device, const IntSize& size);
+ WGPUTexture GetNewTexture(const IntSize& size);
// cc::TextureLayerClient implementation.
bool PrepareTransferableResource(
@@ -81,6 +82,7 @@ class PLATFORM_EXPORT WebGPUSwapBufferProvider
scoped_refptr<DawnControlClientHolder> dawn_control_client_;
Client* client_;
+ uint64_t device_client_id_;
scoped_refptr<cc::TextureLayer> layer_;
bool neutered_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
index 6ff93d7e300..19100740ef6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
@@ -19,7 +19,8 @@ namespace {
class MockWebGPUInterface : public gpu::webgpu::WebGPUInterfaceStub {
public:
- MOCK_METHOD1(ReserveTexture, gpu::webgpu::ReservedTexture(WGPUDevice device));
+ MOCK_METHOD1(ReserveTexture,
+ gpu::webgpu::ReservedTexture(uint64_t device_client_id));
// It is hard to use GMock with SyncTokens represented as GLByte*, instead we
// remember which were the last sync tokens generated or waited upon.
@@ -57,10 +58,15 @@ class WebGPUSwapBufferProviderForTests : public WebGPUSwapBufferProvider {
WebGPUSwapBufferProviderForTests(
bool* alive,
Client* client,
+ uint64_t client_device_id_,
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUTextureUsage usage,
WGPUTextureFormat format)
- : WebGPUSwapBufferProvider(client, dawn_control_client, usage, format),
+ : WebGPUSwapBufferProvider(client,
+ dawn_control_client,
+ client_device_id_,
+ usage,
+ format),
alive_(alive) {}
~WebGPUSwapBufferProviderForTests() override { *alive_ = false; }
@@ -82,8 +88,10 @@ class WebGPUSwapBufferProviderTest : public testing::Test {
dawn_control_client_ =
base::MakeRefCounted<DawnControlClientHolder>(std::move(provider));
+
+ static const uint64_t kDeviceClientID = 1;
provider_ = base::MakeRefCounted<WebGPUSwapBufferProviderForTests>(
- &provider_alive_, &client_, dawn_control_client_,
+ &provider_alive_, &client_, kDeviceClientID, dawn_control_client_,
WGPUTextureUsage_OutputAttachment, WGPUTextureFormat_RGBA8Unorm);
}
@@ -116,17 +124,17 @@ TEST_F(WebGPUSwapBufferProviderTest,
// Produce resources.
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation1));
- provider_->GetNewTexture(nullptr, kSize);
+ provider_->GetNewTexture(kSize);
EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource1,
&release_callback1));
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation2));
- provider_->GetNewTexture(nullptr, kSize);
+ provider_->GetNewTexture(kSize);
EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource2,
&release_callback2));
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation3));
- provider_->GetNewTexture(nullptr, kSize);
+ provider_->GetNewTexture(kSize);
EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource3,
&release_callback3));
@@ -154,7 +162,7 @@ TEST_F(WebGPUSwapBufferProviderTest, VerifyResizingProperlyAffectsResources) {
// Produce one resource of size kSize.
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation));
- provider_->GetNewTexture(nullptr, static_cast<IntSize>(kSize));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
&release_callback));
EXPECT_EQ(static_cast<gfx::Size>(kSize), sii_->MostRecentSize());
@@ -162,7 +170,7 @@ TEST_F(WebGPUSwapBufferProviderTest, VerifyResizingProperlyAffectsResources) {
// Produce one resource of size kOtherSize.
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation));
- provider_->GetNewTexture(nullptr, static_cast<IntSize>(kOtherSize));
+ provider_->GetNewTexture(static_cast<IntSize>(kOtherSize));
EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
&release_callback));
EXPECT_EQ(static_cast<gfx::Size>(kOtherSize), sii_->MostRecentSize());
@@ -170,7 +178,7 @@ TEST_F(WebGPUSwapBufferProviderTest, VerifyResizingProperlyAffectsResources) {
// Produce one resource of size kSize again.
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation));
- provider_->GetNewTexture(nullptr, static_cast<IntSize>(kSize));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
&release_callback));
EXPECT_EQ(static_cast<gfx::Size>(kSize), sii_->MostRecentSize());
@@ -188,7 +196,7 @@ TEST_F(WebGPUSwapBufferProviderTest, VerifyInsertAndWaitSyncTokenCorrectly) {
// Produce the first resource, check that WebGPU will wait for the creation of
// the shared image
EXPECT_CALL(*webgpu_, ReserveTexture(_)).WillOnce(Return(reservation));
- provider_->GetNewTexture(nullptr, static_cast<IntSize>(kSize));
+ provider_->GetNewTexture(static_cast<IntSize>(kSize));
EXPECT_EQ(sii_->MostRecentGeneratedToken(),
webgpu_->most_recent_waited_token);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
index 63b92488b08..e456c90a383 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -18,9 +18,7 @@ namespace blink {
XRFrameTransport::XRFrameTransport() : submit_frame_client_receiver_(this) {}
-XRFrameTransport::~XRFrameTransport() {
- CallPreviousFrameCallback();
-}
+XRFrameTransport::~XRFrameTransport() = default;
void XRFrameTransport::PresentChange() {
frame_copier_ = nullptr;
@@ -79,13 +77,6 @@ void XRFrameTransport::FramePreImage(gpu::gles2::GLES2Interface* gl) {
}
}
-void XRFrameTransport::CallPreviousFrameCallback() {
- if (previous_image_release_callback_) {
- previous_image_release_callback_->Run(gpu::SyncToken(), false);
- previous_image_release_callback_ = nullptr;
- }
-}
-
void XRFrameTransport::FrameSubmitMissing(
device::mojom::blink::XRPresentationProvider* vr_presentation_provider,
gpu::gles2::GLES2Interface* gl,
@@ -101,7 +92,6 @@ void XRFrameTransport::FrameSubmit(
gpu::gles2::GLES2Interface* gl,
DrawingBuffer::Client* drawing_buffer_client,
scoped_refptr<Image> image_ref,
- std::unique_ptr<viz::SingleReleaseCallback> release_callback,
int16_t vr_frame_id) {
DCHECK(transport_options_);
@@ -114,8 +104,6 @@ void XRFrameTransport::FrameSubmit(
// without waiting.
if (transport_options_->wait_for_transfer_notification)
WaitForPreviousTransfer();
- CallPreviousFrameCallback();
- previous_image_release_callback_ = std::move(release_callback);
if (!frame_copier_ || !last_transfer_succeeded_) {
frame_copier_ = std::make_unique<GpuMemoryBufferImageCopy>(gl);
}
@@ -137,12 +125,11 @@ void XRFrameTransport::FrameSubmit(
}
// We decompose the cloned handle, and use it to create a
- // mojo::ScopedHandle which will own cleanup of the handle, and will be
+ // mojo::PlatformHandle which will own cleanup of the handle, and will be
// passed over IPC.
gfx::GpuMemoryBufferHandle gpu_handle = gpu_memory_buffer->CloneHandle();
vr_presentation_provider->SubmitFrameWithTextureHandle(
- vr_frame_id,
- mojo::WrapPlatformFile(gpu_handle.dxgi_handle.GetHandle()));
+ vr_frame_id, mojo::PlatformHandle(std::move(gpu_handle.dxgi_handle)));
#else
NOTIMPLEMENTED();
#endif
@@ -155,9 +142,7 @@ void XRFrameTransport::FrameSubmit(
// image until the mailbox was consumed.
StaticBitmapImage* static_image =
static_cast<StaticBitmapImage*>(image_ref.get());
- TRACE_EVENT_BEGIN0("gpu", "XRFrameTransport::EnsureMailbox");
- static_image->EnsureMailbox(kVerifiedSyncToken, GL_NEAREST);
- TRACE_EVENT_END0("gpu", "XRFrameTransport::EnsureMailbox");
+ static_image->EnsureSyncTokenVerified();
// Conditionally wait for the previous render to finish. A late wait here
// attempts to overlap work in parallel with the previous frame's
@@ -173,19 +158,15 @@ void XRFrameTransport::FrameSubmit(
if (transport_options_->wait_for_transfer_notification)
WaitForPreviousTransfer();
previous_image_ = std::move(image_ref);
- CallPreviousFrameCallback();
- previous_image_release_callback_ = std::move(release_callback);
// Create mailbox and sync token for transfer.
TRACE_EVENT_BEGIN0("gpu", "XRFrameTransport::GetMailbox");
- auto mailbox = static_image->GetMailbox();
+ auto mailbox_holder = static_image->GetMailboxHolder();
TRACE_EVENT_END0("gpu", "XRFrameTransport::GetMailbox");
- auto sync_token = static_image->GetSyncToken();
TRACE_EVENT_BEGIN0("gpu", "XRFrameTransport::SubmitFrame");
- vr_presentation_provider->SubmitFrame(
- vr_frame_id, gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D),
- frame_wait_time_);
+ vr_presentation_provider->SubmitFrame(vr_frame_id, mailbox_holder,
+ frame_wait_time_);
TRACE_EVENT_END0("gpu", "XRFrameTransport::SubmitFrame");
} else if (transport_options_->transport_method ==
device::mojom::blink::XRPresentationTransportMethod::
@@ -264,6 +245,6 @@ base::TimeDelta XRFrameTransport::WaitForGpuFenceReceived() {
return base::TimeTicks::Now() - start;
}
-void XRFrameTransport::Trace(blink::Visitor* visitor) {}
+void XRFrameTransport::Trace(Visitor* visitor) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
index f0fa0523692..982f5ad3d33 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
@@ -52,20 +52,18 @@ class PLATFORM_EXPORT XRFrameTransport final
gpu::gles2::GLES2Interface*,
DrawingBuffer::Client*,
scoped_refptr<Image> image_ref,
- std::unique_ptr<viz::SingleReleaseCallback>,
int16_t vr_frame_id);
void FrameSubmitMissing(device::mojom::blink::XRPresentationProvider*,
gpu::gles2::GLES2Interface*,
int16_t vr_frame_id);
- virtual void Trace(blink::Visitor*);
+ virtual void Trace(Visitor*);
private:
void WaitForPreviousTransfer();
base::TimeDelta WaitForPreviousRenderToFinish();
base::TimeDelta WaitForGpuFenceReceived();
- void CallPreviousFrameCallback();
// XRPresentationClient
void OnSubmitFrameTransferred(bool success) override;
@@ -78,7 +76,6 @@ class PLATFORM_EXPORT XRFrameTransport final
// Used to keep the image alive until the next frame if using
// waitForPreviousTransferToFinish.
scoped_refptr<Image> previous_image_;
- std::unique_ptr<viz::SingleReleaseCallback> previous_image_release_callback_;
bool waiting_for_previous_frame_transfer_ = false;
bool last_transfer_succeeded_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
index f4660896cee..9578314ff56 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -25,16 +26,27 @@ namespace blink {
// some of the common bits into a base class?
XRWebGLDrawingBuffer::ColorBuffer::ColorBuffer(
- XRWebGLDrawingBuffer* drawing_buffer,
+ base::WeakPtr<XRWebGLDrawingBuffer> drawing_buffer,
const IntSize& size,
const gpu::Mailbox& mailbox,
GLuint texture_id)
- : drawing_buffer(drawing_buffer),
+ : owning_thread_ref(base::PlatformThread::CurrentRef()),
+ drawing_buffer(std::move(drawing_buffer)),
size(size),
texture_id(texture_id),
mailbox(mailbox) {}
XRWebGLDrawingBuffer::ColorBuffer::~ColorBuffer() {
+ if (base::PlatformThread::CurrentRef() != owning_thread_ref ||
+ !drawing_buffer) {
+ // If the context has been destroyed no cleanup is necessary since all
+ // resources below are automatically destroyed. Note that if a ColorBuffer
+ // is being destroyed on a different thread, it implies that the owning
+ // thread was destroyed which means the associated context was also
+ // destroyed.
+ return;
+ }
+
gpu::gles2::GLES2Interface* gl = drawing_buffer->ContextGL();
if (receive_sync_token.HasData())
gl->WaitSyncTokenCHROMIUM(receive_sync_token.GetConstData());
@@ -105,68 +117,6 @@ scoped_refptr<XRWebGLDrawingBuffer> XRWebGLDrawingBuffer::Create(
return xr_drawing_buffer;
}
-void XRWebGLDrawingBuffer::MirrorClient::OnMirrorImageAvailable(
- scoped_refptr<StaticBitmapImage> image,
- std::unique_ptr<viz::SingleReleaseCallback> callback) {
- // Replace the next image if we have one already.
- if (next_image_ && next_release_callback_) {
- next_release_callback_->Run(gpu::SyncToken(), false);
- }
-
- // Set our new image.
- next_image_ = image;
- next_release_callback_ = std::move(callback);
-}
-
-void XRWebGLDrawingBuffer::MirrorClient::BeginDestruction() {
- // Call all callbacks we have to clean up associated resources. For
- // next_release_callback_, we report the previous image as "not lost", meaning
- // we can reuse the texture/image. For previous_release_callback_
- // and current_release_callback_, we report the image as lost, because we
- // don't know if the consumer is still using them, so they should not be
- // reused.
- if (previous_release_callback_) {
- previous_release_callback_->Run(gpu::SyncToken(), true);
- previous_release_callback_ = nullptr;
- }
-
- if (current_release_callback_) {
- current_release_callback_->Run(gpu::SyncToken(), true);
- current_release_callback_ = nullptr;
- }
-
- if (next_release_callback_) {
- next_release_callback_->Run(gpu::SyncToken(), false);
- next_release_callback_ = nullptr;
- }
-
- next_image_ = nullptr;
-}
-
-scoped_refptr<StaticBitmapImage>
-XRWebGLDrawingBuffer::MirrorClient::GetLastImage() {
- if (!next_image_)
- return nullptr;
-
- scoped_refptr<StaticBitmapImage> ret = next_image_;
- next_image_ = nullptr;
- DCHECK(!previous_release_callback_);
- previous_release_callback_ = std::move(current_release_callback_);
- DCHECK(!current_release_callback_);
- current_release_callback_ = std::move(next_release_callback_);
- return ret;
-}
-
-void XRWebGLDrawingBuffer::MirrorClient::CallLastReleaseCallback() {
- if (previous_release_callback_)
- previous_release_callback_->Run(gpu::SyncToken(), false);
- previous_release_callback_ = nullptr;
-}
-
-XRWebGLDrawingBuffer::MirrorClient::~MirrorClient() {
- BeginDestruction();
-}
-
XRWebGLDrawingBuffer::XRWebGLDrawingBuffer(DrawingBuffer* drawing_buffer,
GLuint framebuffer,
bool discard_framebuffer_supported,
@@ -178,11 +128,10 @@ XRWebGLDrawingBuffer::XRWebGLDrawingBuffer(DrawingBuffer* drawing_buffer,
discard_framebuffer_supported_(discard_framebuffer_supported),
depth_(want_depth_buffer),
stencil_(want_stencil_buffer),
- alpha_(want_alpha_channel) {}
+ alpha_(want_alpha_channel),
+ weak_factory_(this) {}
void XRWebGLDrawingBuffer::BeginDestruction() {
- mirror_client_ = nullptr;
-
if (back_color_buffer_) {
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
gl->EndSharedImageAccessDirectCHROMIUM(back_color_buffer_->texture_id);
@@ -242,18 +191,6 @@ gpu::gles2::GLES2Interface* XRWebGLDrawingBuffer::ContextGL() {
return drawing_buffer_->ContextGL();
}
-void XRWebGLDrawingBuffer::SetMirrorClient(scoped_refptr<MirrorClient> client) {
- mirror_client_ = client;
- if (mirror_client_) {
- // Immediately send a black 1x1 image to the mirror client to ensure that
- // it has content to show.
- sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(1, 1);
- mirror_client_->OnMirrorImageAvailable(
- UnacceleratedStaticBitmapImage::Create(surface->makeImageSnapshot()),
- nullptr);
- }
-}
-
bool XRWebGLDrawingBuffer::ContextLost() {
return drawing_buffer_->destroyed();
}
@@ -523,7 +460,8 @@ XRWebGLDrawingBuffer::CreateColorBuffer() {
DrawingBuffer::Client* client = drawing_buffer_->client();
client->DrawingBufferClientRestoreTexture2DBinding();
- return base::AdoptRef(new ColorBuffer(this, size_, mailbox, texture_id));
+ return base::MakeRefCounted<ColorBuffer>(weak_factory_.GetWeakPtr(), size_,
+ mailbox, texture_id);
}
scoped_refptr<XRWebGLDrawingBuffer::ColorBuffer>
@@ -626,8 +564,7 @@ void XRWebGLDrawingBuffer::SwapColorBuffers() {
}
scoped_refptr<StaticBitmapImage>
-XRWebGLDrawingBuffer::TransferToStaticBitmapImage(
- std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
+XRWebGLDrawingBuffer::TransferToStaticBitmapImage() {
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
scoped_refptr<ColorBuffer> buffer;
bool success = false;
@@ -661,47 +598,45 @@ XRWebGLDrawingBuffer::TransferToStaticBitmapImage(
// This holds a ref on the XRWebGLDrawingBuffer that will keep it alive
// until the mailbox is released (and while the callback is running).
auto func =
- WTF::Bind(mirror_client_ ? &XRWebGLDrawingBuffer::MailboxReleasedToMirror
- : &XRWebGLDrawingBuffer::MailboxReleased,
- scoped_refptr<XRWebGLDrawingBuffer>(this), buffer);
+ base::BindOnce(&XRWebGLDrawingBuffer::NotifyMailboxReleased, buffer);
std::unique_ptr<viz::SingleReleaseCallback> release_callback =
viz::SingleReleaseCallback::Create(std::move(func));
+ const SkImageInfo sk_image_info =
+ SkImageInfo::MakeN32Premul(size_.Width(), size_.Height());
+
+ return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
+ buffer->mailbox, buffer->produce_sync_token,
+ /* shared_image_texture_id = */ 0, sk_image_info, GL_TEXTURE_2D,
+ /* is_origin_top_left = */ false,
+ drawing_buffer_->ContextProviderWeakPtr(),
+ base::PlatformThread::CurrentRef(), Thread::Current()->GetTaskRunner(),
+ std::move(release_callback));
+}
- // Make our own textureId that is a reference on the same shared image being
- // used as the front buffer. We do not need a
- // Begin/EndSharedImageAccessDirectCHROMIUM as the texture id is just for
- // lifetime, not actual access. We do not need to wait on the sync token
- // since the GL context has already waited on it. Similarly, the release
- // callback will run on the same context so we don't need to send a sync token
- // for this consume action back to it.
- GLuint texture_id =
- gl->CreateAndTexStorage2DSharedImageCHROMIUM(buffer->mailbox.name);
+// static
+void XRWebGLDrawingBuffer::NotifyMailboxReleased(
+ scoped_refptr<ColorBuffer> color_buffer,
+ const gpu::SyncToken& sync_token,
+ bool lost_resource) {
+ DCHECK(color_buffer->owning_thread_ref == base::PlatformThread::CurrentRef());
- if (out_release_callback) {
- *out_release_callback = std::move(release_callback);
- } else {
- release_callback->Run(gpu::SyncToken(), true /* lost_resource */);
+ // Update the SyncToken to ensure that we will wait for it even if we
+ // immediately destroy this buffer.
+ color_buffer->receive_sync_token = sync_token;
+ if (color_buffer->drawing_buffer) {
+ color_buffer->drawing_buffer->MailboxReleased(color_buffer, lost_resource);
}
-
- return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
- buffer->mailbox, buffer->produce_sync_token, texture_id,
- drawing_buffer_->ContextProviderWeakPtr(), size_, false);
}
void XRWebGLDrawingBuffer::MailboxReleased(
scoped_refptr<ColorBuffer> color_buffer,
- const gpu::SyncToken& sync_token,
bool lost_resource) {
// If the mailbox has been returned by the compositor then it is no
// longer being presented, and so is no longer the front buffer.
if (color_buffer == front_color_buffer_)
front_color_buffer_ = nullptr;
- // Update the SyncToken to ensure that we will wait for it even if we
- // immediately destroy this buffer.
- color_buffer->receive_sync_token = sync_token;
-
if (drawing_buffer_->destroyed() || color_buffer->size != size_ ||
lost_resource) {
return;
@@ -714,35 +649,4 @@ void XRWebGLDrawingBuffer::MailboxReleased(
recycled_color_buffer_queue_.push_front(color_buffer);
}
-void XRWebGLDrawingBuffer::MailboxReleasedToMirror(
- scoped_refptr<ColorBuffer> color_buffer,
- const gpu::SyncToken& sync_token,
- bool lost_resource) {
- if (!mirror_client_ || lost_resource) {
- MailboxReleased(std::move(color_buffer), sync_token, lost_resource);
- return;
- }
-
- gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
- color_buffer->receive_sync_token = sync_token;
-
- auto func =
- WTF::Bind(&XRWebGLDrawingBuffer::MailboxReleased,
- scoped_refptr<XRWebGLDrawingBuffer>(this), color_buffer);
-
- std::unique_ptr<viz::SingleReleaseCallback> release_callback =
- viz::SingleReleaseCallback::Create(std::move(func));
-
- GLuint texture_id =
- gl->CreateAndTexStorage2DSharedImageCHROMIUM(color_buffer->mailbox.name);
-
- scoped_refptr<StaticBitmapImage> image =
- AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
- color_buffer->mailbox, color_buffer->produce_sync_token, texture_id,
- drawing_buffer_->ContextProviderWeakPtr(), color_buffer->size, false);
-
- mirror_client_->OnMirrorImageAvailable(std::move(image),
- std::move(release_callback));
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
index 44649d80dd6..26f28d0cc11 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
@@ -43,28 +43,7 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
void Resize(const IntSize&);
- scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(
- std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
-
- class PLATFORM_EXPORT MirrorClient : public RefCounted<MirrorClient> {
- public:
- void OnMirrorImageAvailable(scoped_refptr<StaticBitmapImage>,
- std::unique_ptr<viz::SingleReleaseCallback>);
-
- void BeginDestruction();
- scoped_refptr<StaticBitmapImage> GetLastImage();
- void CallLastReleaseCallback();
-
- ~MirrorClient();
-
- private:
- scoped_refptr<StaticBitmapImage> next_image_;
- std::unique_ptr<viz::SingleReleaseCallback> next_release_callback_;
- std::unique_ptr<viz::SingleReleaseCallback> current_release_callback_;
- std::unique_ptr<viz::SingleReleaseCallback> previous_release_callback_;
- };
-
- void SetMirrorClient(scoped_refptr<MirrorClient> mirror_client);
+ scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage();
void UseSharedBuffer(const gpu::MailboxHolder&);
void DoneWithSharedBuffer();
@@ -75,17 +54,22 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
void BeginDestruction();
private:
- struct PLATFORM_EXPORT ColorBuffer : public RefCounted<ColorBuffer> {
- ColorBuffer(XRWebGLDrawingBuffer*,
+ struct PLATFORM_EXPORT ColorBuffer
+ : public base::RefCountedThreadSafe<ColorBuffer> {
+ ColorBuffer(base::WeakPtr<XRWebGLDrawingBuffer>,
const IntSize&,
const gpu::Mailbox& mailbox,
GLuint texture_id);
~ColorBuffer();
+ // The thread on which the ColorBuffer is created and the DrawingBuffer is
+ // bound to.
+ const base::PlatformThreadRef owning_thread_ref;
+
// The owning XRWebGLDrawingBuffer. Note that DrawingBuffer is explicitly
// destroyed by the BeginDestruction method, which will eventually drain all
// of its ColorBuffers.
- scoped_refptr<XRWebGLDrawingBuffer> drawing_buffer;
+ base::WeakPtr<XRWebGLDrawingBuffer> drawing_buffer;
const IntSize size;
// The id of the texture that imports the shared image into the
@@ -126,12 +110,10 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
void ClearBoundFramebuffer();
- void MailboxReleased(scoped_refptr<ColorBuffer>,
- const gpu::SyncToken&,
- bool lost_resource);
- void MailboxReleasedToMirror(scoped_refptr<ColorBuffer>,
- const gpu::SyncToken&,
- bool lost_resource);
+ static void NotifyMailboxReleased(scoped_refptr<ColorBuffer>,
+ const gpu::SyncToken&,
+ bool lost_resource);
+ void MailboxReleased(scoped_refptr<ColorBuffer>, bool lost_resource);
// Reference to the DrawingBuffer that owns the GL context for this object.
scoped_refptr<DrawingBuffer> drawing_buffer_;
@@ -174,7 +156,7 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
int max_texture_size_ = 0;
int sample_count_ = 0;
- scoped_refptr<MirrorClient> mirror_client_;
+ base::WeakPtrFactory<XRWebGLDrawingBuffer> weak_factory_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc
index 6e0c7398786..00925bfa333 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc
@@ -72,21 +72,21 @@ gfx::GpuMemoryBuffer* GpuMemoryBufferImageCopy::CopyImage(Image* image) {
// Bind the read framebuffer to our image.
StaticBitmapImage* static_image = static_cast<StaticBitmapImage*>(image);
- static_image->EnsureMailbox(kOrderingBarrier, GL_NEAREST);
- auto mailbox = static_image->GetMailbox();
- auto sync_token = static_image->GetSyncToken();
+ auto mailbox_holder = static_image->GetMailboxHolder();
+
// Not strictly necessary since we are on the same context, but keeping
// for cleanliness and in case we ever move off the same context.
- gl_->WaitSyncTokenCHROMIUM(sync_token.GetData());
+ gl_->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetData());
GLuint source_texture_id;
- if (mailbox.IsSharedImage()) {
- source_texture_id =
- gl_->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name);
+ if (mailbox_holder.mailbox.IsSharedImage()) {
+ source_texture_id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM(
+ mailbox_holder.mailbox.name);
gl_->BeginSharedImageAccessDirectCHROMIUM(
source_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
} else {
- source_texture_id = gl_->CreateAndConsumeTextureCHROMIUM(mailbox.name);
+ source_texture_id =
+ gl_->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name);
}
gl_->BindTexture(GL_TEXTURE_2D, 0);
@@ -97,10 +97,14 @@ gfx::GpuMemoryBuffer* GpuMemoryBufferImageCopy::CopyImage(Image* image) {
// Cleanup the read framebuffer, associated image and texture.
gl_->BindTexture(GL_TEXTURE_2D, 0);
- if (mailbox.IsSharedImage())
+ if (mailbox_holder.mailbox.IsSharedImage())
gl_->EndSharedImageAccessDirectCHROMIUM(source_texture_id);
gl_->DeleteTextures(1, &source_texture_id);
+ gpu::SyncToken copy_done_sync_token;
+ gl_->GenSyncTokenCHROMIUM(copy_done_sync_token.GetData());
+ static_image->UpdateSyncToken(copy_done_sync_token);
+
// Cleanup the draw framebuffer, associated image and texture.
gl_->BindTexture(target, dest_texture_id);
gl_->ReleaseTexImage2DCHROMIUM(target, image_id);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc
index f9fd7b25ee8..dbd7b216fc2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc
@@ -54,7 +54,8 @@ void GradientGeneratedImage::Draw(cc::PaintCanvas* canvas,
}
void GradientGeneratedImage::DrawTile(GraphicsContext& context,
- const FloatRect& src_rect) {
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum) {
// TODO(ccameron): This function should not ignore |context|'s color behavior.
// https://crbug.com/672306
PaintFlags gradient_flags(context.FillFlags());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
index 66641fb359c..072a19c233b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
@@ -59,7 +59,9 @@ class PLATFORM_EXPORT GradientGeneratedImage final : public GeneratedImage {
RespectImageOrientationEnum,
ImageClampingMode,
ImageDecodingMode) override;
- void DrawTile(GraphicsContext&, const FloatRect&) override;
+ void DrawTile(GraphicsContext&,
+ const FloatRect&,
+ RespectImageOrientationEnum) override;
GradientGeneratedImage(scoped_refptr<Gradient> generator,
const FloatSize& size)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
index 3bf0b074a5b..8473a8d0f75 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -58,6 +58,7 @@
#include "third_party/skia/include/effects/SkTableColorFilter.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "third_party/skia/include/utils/SkNullCanvas.h"
+#include "ui/base/ui_base_features.h"
namespace blink {
@@ -89,7 +90,6 @@ class GraphicsContext::DarkModeFlags final {
};
GraphicsContext::GraphicsContext(PaintController& paint_controller,
- DisabledMode disable_context_or_painting,
printing::MetafileSkia* metafile,
paint_preview::PaintPreviewTracker* tracker)
: canvas_(nullptr),
@@ -102,7 +102,6 @@ GraphicsContext::GraphicsContext(PaintController& paint_controller,
layer_count_(0),
disable_destruction_checks_(false),
#endif
- disabled_state_(disable_context_or_painting),
device_scale_factor_(1.0f),
printing_(false),
is_painting_preview_(false),
@@ -111,13 +110,6 @@ GraphicsContext::GraphicsContext(PaintController& paint_controller,
// allocate several here.
paint_state_stack_.push_back(std::make_unique<GraphicsContextState>());
paint_state_ = paint_state_stack_.back().get();
-
- if (ContextDisabled()) {
- DEFINE_STATIC_LOCAL(SkCanvas*, null_sk_canvas,
- (SkMakeNullCanvas().release()));
- DEFINE_STATIC_LOCAL(SkiaPaintCanvas, null_canvas, (null_sk_canvas));
- canvas_ = &null_canvas;
- }
}
GraphicsContext::~GraphicsContext() {
@@ -132,9 +124,6 @@ GraphicsContext::~GraphicsContext() {
}
void GraphicsContext::Save() {
- if (ContextDisabled())
- return;
-
paint_state_->IncrementSaveCount();
DCHECK(canvas_);
@@ -142,9 +131,6 @@ void GraphicsContext::Save() {
}
void GraphicsContext::Restore() {
- if (ContextDisabled())
- return;
-
if (!paint_state_index_ && !paint_state_->SaveCount()) {
DLOG(ERROR) << "ERROR void GraphicsContext::restore() stack is empty";
return;
@@ -179,19 +165,12 @@ void GraphicsContext::SetDarkMode(const DarkModeSettings& settings) {
}
void GraphicsContext::SaveLayer(const SkRect* bounds, const PaintFlags* flags) {
- if (ContextDisabled())
- return;
-
DCHECK(canvas_);
canvas_->saveLayer(bounds, flags);
}
void GraphicsContext::RestoreLayer() {
- if (ContextDisabled())
- return;
-
DCHECK(canvas_);
-
canvas_->restore();
}
@@ -201,6 +180,17 @@ void GraphicsContext::SetInDrawingRecorder(bool val) {
in_drawing_recorder_ = val;
}
+void GraphicsContext::SetDOMNodeId(DOMNodeId new_node_id) {
+ if (canvas_)
+ canvas_->setNodeId(new_node_id);
+
+ dom_node_id_ = new_node_id;
+}
+
+DOMNodeId GraphicsContext::GetDOMNodeId() const {
+ return dom_node_id_;
+}
+
void GraphicsContext::SetShadow(
const FloatSize& offset,
float blur,
@@ -208,9 +198,6 @@ void GraphicsContext::SetShadow(
DrawLooperBuilder::ShadowTransformMode shadow_transform_mode,
DrawLooperBuilder::ShadowAlphaMode shadow_alpha_mode,
ShadowMode shadow_mode) {
- if (ContextDisabled())
- return;
-
DrawLooperBuilder draw_looper_builder;
if (!color.Alpha()) {
// When shadow-only but there is no shadow, we use an empty draw looper
@@ -231,9 +218,6 @@ void GraphicsContext::SetShadow(
}
void GraphicsContext::SetDrawLooper(sk_sp<SkDrawLooper> draw_looper) {
- if (ContextDisabled())
- return;
-
MutableState()->SetDrawLooper(std::move(draw_looper));
}
@@ -253,11 +237,7 @@ void GraphicsContext::SetColorFilter(ColorFilter color_filter) {
}
void GraphicsContext::Concat(const SkMatrix& matrix) {
- if (ContextDisabled())
- return;
-
DCHECK(canvas_);
-
canvas_->concat(matrix);
}
@@ -266,9 +246,6 @@ void GraphicsContext::BeginLayer(float opacity,
const FloatRect* bounds,
ColorFilter color_filter,
sk_sp<PaintFilter> image_filter) {
- if (ContextDisabled())
- return;
-
PaintFlags layer_flags;
layer_flags.setAlpha(static_cast<unsigned char>(opacity * 255));
layer_flags.setBlendMode(xfermode);
@@ -288,9 +265,6 @@ void GraphicsContext::BeginLayer(float opacity,
}
void GraphicsContext::EndLayer() {
- if (ContextDisabled())
- return;
-
RestoreLayer();
#if DCHECK_IS_ON()
@@ -299,9 +273,6 @@ void GraphicsContext::EndLayer() {
}
void GraphicsContext::BeginRecording(const FloatRect& bounds) {
- if (ContextDisabled())
- return;
-
DCHECK(!canvas_);
canvas_ = paint_recorder_.beginRecording(bounds);
if (metafile_)
@@ -310,25 +281,7 @@ void GraphicsContext::BeginRecording(const FloatRect& bounds) {
canvas_->SetPaintPreviewTracker(tracker_);
}
-namespace {
-
-sk_sp<PaintRecord> CreateEmptyPaintRecord() {
- PaintRecorder recorder;
- recorder.beginRecording(SkRect::MakeEmpty());
- return recorder.finishRecordingAsPicture();
-}
-
-} // anonymous namespace
-
sk_sp<PaintRecord> GraphicsContext::EndRecording() {
- if (ContextDisabled()) {
- // Clients expect endRecording() to always return a non-null paint record.
- // Cache an empty one to minimize overhead when disabled.
- DEFINE_STATIC_LOCAL(const sk_sp<PaintRecord>, empty_paint_record,
- (CreateEmptyPaintRecord()));
- return empty_paint_record;
- }
-
sk_sp<PaintRecord> record = paint_recorder_.finishRecordingAsPicture();
canvas_ = nullptr;
DCHECK(record);
@@ -336,7 +289,7 @@ sk_sp<PaintRecord> GraphicsContext::EndRecording() {
}
void GraphicsContext::DrawRecord(sk_sp<const PaintRecord> record) {
- if (ContextDisabled() || !record || !record->size())
+ if (!record || !record->size())
return;
DCHECK(canvas_);
@@ -347,7 +300,7 @@ void GraphicsContext::CompositeRecord(sk_sp<PaintRecord> record,
const FloatRect& dest,
const FloatRect& src,
SkBlendMode op) {
- if (ContextDisabled() || !record)
+ if (!record)
return;
DCHECK(canvas_);
@@ -369,7 +322,16 @@ void GraphicsContext::CompositeRecord(sk_sp<PaintRecord> record,
namespace {
-int AdjustedFocusRingOffset(int offset, int width, bool is_outset) {
+int AdjustedFocusRingOffset(int offset,
+ int default_offset,
+ int width,
+ bool is_outset) {
+ if (::features::IsFormControlsRefreshEnabled()) {
+ // For FormControlsRefresh the focus ring has a default offset that
+ // depends on the element type.
+ return default_offset;
+ }
+
#if defined(OS_MACOSX)
return offset + 2;
#else
@@ -382,34 +344,45 @@ int AdjustedFocusRingOffset(int offset, int width, bool is_outset) {
} // namespace
int GraphicsContext::FocusRingOutsetExtent(int offset,
+ int default_offset,
int width,
bool is_outset) {
// Unlike normal outlines (whole width is outside of the offset), focus
// rings can be drawn with the center of the path aligned with the offset, so
// only half of the width is outside of the offset.
- return AdjustedFocusRingOffset(offset, width, is_outset) + (width + 1) / 2;
+ if (::features::IsFormControlsRefreshEnabled()) {
+ // For FormControlsRefresh 2/3 of the width is outside of the offset.
+ return AdjustedFocusRingOffset(offset, default_offset, width, is_outset) +
+ std::ceil(width / 3.f) * 2;
+ }
+
+ return AdjustedFocusRingOffset(offset, /*default_offset=*/0, width,
+ is_outset) +
+ (width + 1) / 2;
}
void GraphicsContext::DrawFocusRingPath(const SkPath& path,
const Color& color,
- float width) {
+ float width,
+ float border_radius) {
DrawPlatformFocusRing(
path, canvas_,
dark_mode_filter_
.InvertColorIfNeeded(color, DarkModeFilter::ElementRole::kBackground)
.Rgb(),
- width);
+ width, border_radius);
}
void GraphicsContext::DrawFocusRingRect(const SkRect& rect,
const Color& color,
- float width) {
+ float width,
+ float border_radius) {
DrawPlatformFocusRing(
rect, canvas_,
dark_mode_filter_
.InvertColorIfNeeded(color, DarkModeFilter::ElementRole::kBackground)
.Rgb(),
- width);
+ width, border_radius);
}
void GraphicsContext::DrawFocusRing(const Path& focus_ring_path,
@@ -417,26 +390,27 @@ void GraphicsContext::DrawFocusRing(const Path& focus_ring_path,
int offset,
const Color& color) {
// FIXME: Implement support for offset.
- if (ContextDisabled())
- return;
-
- DrawFocusRingPath(focus_ring_path.GetSkPath(), color, width);
+ DrawFocusRingPath(focus_ring_path.GetSkPath(), color, /*width=*/width,
+ /*radius=*/width);
}
void GraphicsContext::DrawFocusRingInternal(const Vector<IntRect>& rects,
float width,
int offset,
+ float border_radius,
const Color& color,
bool is_outset) {
- if (ContextDisabled())
- return;
-
unsigned rect_count = rects.size();
if (!rect_count)
return;
SkRegion focus_ring_region;
- offset = AdjustedFocusRingOffset(offset, std::ceil(width), is_outset);
+ if (!::features::IsFormControlsRefreshEnabled()) {
+ // For FormControlsRefresh the offset is already adjusted by
+ // GraphicsContext::DrawFocusRing.
+ offset = AdjustedFocusRingOffset(offset, /*default_offset=*/0,
+ std::ceil(width), is_outset);
+ }
for (unsigned i = 0; i < rect_count; i++) {
SkIRect r = rects[i];
if (r.isEmpty())
@@ -449,12 +423,12 @@ void GraphicsContext::DrawFocusRingInternal(const Vector<IntRect>& rects,
return;
if (focus_ring_region.isRect()) {
- DrawFocusRingRect(SkRect::Make(focus_ring_region.getBounds()), color,
- width);
+ DrawFocusRingRect(SkRect::Make(focus_ring_region.getBounds()), color, width,
+ border_radius);
} else {
SkPath path;
if (focus_ring_region.getBoundaryPath(&path))
- DrawFocusRingPath(path, color, width);
+ DrawFocusRingPath(path, color, width, border_radius);
}
}
@@ -478,22 +452,48 @@ bool ShouldDrawInnerFocusRingForContrast(bool is_outset,
void GraphicsContext::DrawFocusRing(const Vector<IntRect>& rects,
float width,
int offset,
+ int default_offset,
+ float border_radius,
+ float min_border_width,
const Color& color,
bool is_outset) {
- // If a focus ring is outset and the color is dark, it may be hard to see on
- // dark backgrounds. In this case, we'll actually draw two focus rings, the
- // outset focus ring with a white inner ring for contrast.
- if (ShouldDrawInnerFocusRingForContrast(is_outset, width, color)) {
- int contrast_offset = static_cast<int>(std::floor(width * 0.5));
- // We create a 1px gap for the contrast ring. The contrast ring is drawn
- // first, and we overdraw by a pixel to ensure no gaps or AA artifacts.
- DrawFocusRingInternal(rects, contrast_offset, offset, SK_ColorWHITE,
- is_outset);
- DrawFocusRingInternal(rects, width - contrast_offset,
- offset + contrast_offset, color, is_outset);
-
+ if (::features::IsFormControlsRefreshEnabled()) {
+ // The focus ring is made of two borders which have a 2:1 ratio.
+ const float first_border_width = (width / 3) * 2;
+ const float second_border_width = width - first_border_width;
+
+ offset = AdjustedFocusRingOffset(offset, default_offset, std::ceil(width),
+ is_outset);
+ // How much space the focus ring would like to take from the actual border.
+ const float inside_border_width = 1;
+ if (min_border_width >= inside_border_width) {
+ offset -= inside_border_width;
+ }
+ // The white ring is drawn first, and we overdraw to ensure no gaps or AA
+ // artifacts.
+ DrawFocusRingInternal(rects, first_border_width,
+ offset + std::ceil(second_border_width),
+ border_radius, SK_ColorWHITE, is_outset);
+ DrawFocusRingInternal(rects, first_border_width, offset, border_radius,
+ color, is_outset);
} else {
- DrawFocusRingInternal(rects, width, offset, color, is_outset);
+ // If a focus ring is outset and the color is dark, it may be hard to see on
+ // dark backgrounds. In this case, we'll actually draw two focus rings, the
+ // outset focus ring with a white inner ring for contrast.
+ if (ShouldDrawInnerFocusRingForContrast(is_outset, width, color)) {
+ int contrast_offset = static_cast<int>(std::floor(width * 0.5));
+ // We create a 1px gap for the contrast ring. The contrast ring is drawn
+ // first, and we overdraw by a pixel to ensure no gaps or AA artifacts.
+ DrawFocusRingInternal(rects, contrast_offset, offset, border_radius,
+ SK_ColorWHITE, is_outset);
+ DrawFocusRingInternal(rects, width - contrast_offset,
+ offset + contrast_offset, border_radius, color,
+ is_outset);
+
+ } else {
+ DrawFocusRingInternal(rects, width, offset, border_radius, color,
+ is_outset);
+ }
}
}
@@ -520,9 +520,6 @@ void GraphicsContext::DrawInnerShadow(const FloatRoundedRect& rect,
float shadow_blur,
float shadow_spread,
Edges clipped_edges) {
- if (ContextDisabled())
- return;
-
Color shadow_color = dark_mode_filter_.InvertColorIfNeeded(
orig_shadow_color, DarkModeFilter::ElementRole::kBackground);
@@ -679,8 +676,6 @@ static void EnforceDotsAtEndpoints(GraphicsContext& context,
void GraphicsContext::DrawLine(const IntPoint& point1,
const IntPoint& point2,
const DarkModeFilter::ElementRole role) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
StrokeStyle pen_style = GetStrokeStyle();
@@ -728,9 +723,6 @@ void GraphicsContext::DrawLine(const IntPoint& point1,
}
void GraphicsContext::DrawLineForText(const FloatPoint& pt, float width) {
- if (ContextDisabled())
- return;
-
if (width <= 0)
return;
@@ -739,7 +731,7 @@ void GraphicsContext::DrawLineForText(const FloatPoint& pt, float width) {
case kNoStroke:
case kSolidStroke:
case kDoubleStroke: {
- int thickness = SkMax32(static_cast<int>(StrokeThickness()), 1);
+ int thickness = std::max(static_cast<int>(StrokeThickness()), 1);
SkRect r;
r.fLeft = WebCoreFloatToSkScalar(pt.X());
// Avoid anti-aliasing lines. Currently, these are always horizontal.
@@ -770,9 +762,6 @@ void GraphicsContext::DrawLineForText(const FloatPoint& pt, float width) {
// Draws a filled rectangle with a stroked border.
void GraphicsContext::DrawRect(const IntRect& rect) {
- if (ContextDisabled())
- return;
-
if (rect.IsEmpty())
return;
@@ -798,9 +787,6 @@ void GraphicsContext::DrawText(const Font& font,
const FloatPoint& point,
const PaintFlags& flags,
DOMNodeId node_id) {
- if (ContextDisabled())
- return;
-
font.DrawText(canvas_, text_info, point, device_scale_factor_, node_id,
DarkModeFlags(this, flags, DarkModeFilter::ElementRole::kText));
}
@@ -829,9 +815,6 @@ void GraphicsContext::DrawTextInternal(const Font& font,
const TextPaintInfo& text_info,
const FloatPoint& point,
DOMNodeId node_id) {
- if (ContextDisabled())
- return;
-
DrawTextPasses([&](const PaintFlags& flags) {
font.DrawText(
canvas_, text_info, point, device_scale_factor_, node_id,
@@ -858,9 +841,6 @@ void GraphicsContext::DrawEmphasisMarksInternal(const Font& font,
const TextPaintInfo& text_info,
const AtomicString& mark,
const FloatPoint& point) {
- if (ContextDisabled())
- return;
-
DrawTextPasses(
[&font, &text_info, &mark, &point, this](const PaintFlags& flags) {
font.DrawEmphasisMarks(
@@ -889,9 +869,6 @@ void GraphicsContext::DrawBidiText(
const TextRunPaintInfo& run_info,
const FloatPoint& point,
Font::CustomFontNotReadyAction custom_font_not_ready_action) {
- if (ContextDisabled())
- return;
-
DrawTextPasses([&font, &run_info, &point, custom_font_not_ready_action,
this](const PaintFlags& flags) {
if (font.DrawBidiText(
@@ -910,9 +887,6 @@ void GraphicsContext::DrawHighlightForText(const Font& font,
const Color& background_color,
int from,
int to) {
- if (ContextDisabled())
- return;
-
FillRect(font.SelectionRectForText(run, point, h, from, to),
background_color);
}
@@ -925,7 +899,7 @@ void GraphicsContext::DrawImage(
bool has_filter_property,
SkBlendMode op,
RespectImageOrientationEnum should_respect_image_orientation) {
- if (ContextDisabled() || !image)
+ if (!image)
return;
const FloatRect src = src_ptr ? *src_ptr : FloatRect(image->Rect());
@@ -952,7 +926,7 @@ void GraphicsContext::DrawImageRRect(
bool has_filter_property,
SkBlendMode op,
RespectImageOrientationEnum respect_orientation) {
- if (ContextDisabled() || !image)
+ if (!image)
return;
if (!dest.IsRounded()) {
@@ -978,7 +952,8 @@ void GraphicsContext::DrawImageRRect(
&image_flags);
bool use_shader = (visible_src == src_rect) &&
- (respect_orientation == kDoNotRespectImageOrientation);
+ (respect_orientation == kDoNotRespectImageOrientation ||
+ image->HasDefaultOrientation());
if (use_shader) {
const SkMatrix local_matrix = SkMatrix::MakeRectToRect(
visible_src, dest.Rect(), SkMatrix::kFill_ScaleToFit);
@@ -1026,62 +1001,52 @@ SkFilterQuality GraphicsContext::ComputeFilterQuality(
std::min(resampling, ImageInterpolationQuality()));
}
-void GraphicsContext::DrawImageTiled(Image* image,
- const FloatRect& dest_rect,
- const FloatRect& src_rect,
- const FloatSize& scale_src_to_dest,
- const FloatPoint& phase,
- const FloatSize& repeat_spacing,
- SkBlendMode op) {
- if (ContextDisabled() || !image)
+void GraphicsContext::DrawImageTiled(
+ Image* image,
+ const FloatRect& dest_rect,
+ const FloatRect& src_rect,
+ const FloatSize& scale_src_to_dest,
+ const FloatPoint& phase,
+ const FloatSize& repeat_spacing,
+ SkBlendMode op,
+ RespectImageOrientationEnum respect_orientation) {
+ if (!image)
return;
image->DrawPattern(*this, src_rect, scale_src_to_dest, phase, op, dest_rect,
- repeat_spacing);
+ repeat_spacing, respect_orientation);
paint_controller_.SetImagePainted();
}
void GraphicsContext::DrawOval(const SkRect& oval,
const PaintFlags& flags,
const DarkModeFilter::ElementRole role) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->drawOval(oval, DarkModeFlags(this, flags, role));
}
void GraphicsContext::DrawPath(const SkPath& path,
const PaintFlags& flags,
const DarkModeFilter::ElementRole role) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->drawPath(path, DarkModeFlags(this, flags, role));
}
void GraphicsContext::DrawRect(const SkRect& rect,
const PaintFlags& flags,
const DarkModeFilter::ElementRole role) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->drawRect(rect, DarkModeFlags(this, flags, role));
}
void GraphicsContext::DrawRRect(const SkRRect& rrect, const PaintFlags& flags) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->drawRRect(
rrect,
DarkModeFlags(this, flags, DarkModeFilter::ElementRole::kBackground));
}
void GraphicsContext::FillPath(const Path& path_to_fill) {
- if (ContextDisabled() || path_to_fill.IsEmpty())
+ if (path_to_fill.IsEmpty())
return;
DrawPath(path_to_fill.GetSkPath(), ImmutableState()->FillFlags());
@@ -1098,9 +1063,6 @@ void GraphicsContext::FillRect(const IntRect& rect,
}
void GraphicsContext::FillRect(const FloatRect& rect) {
- if (ContextDisabled())
- return;
-
DrawRect(rect, ImmutableState()->FillFlags());
}
@@ -1114,9 +1076,6 @@ void GraphicsContext::FillRect(const FloatRect& rect,
const Color& color,
SkBlendMode xfer_mode,
DarkModeFilter::ElementRole role) {
- if (ContextDisabled())
- return;
-
PaintFlags flags = ImmutableState()->FillFlags();
flags.setColor(color.Rgb());
flags.setBlendMode(xfer_mode);
@@ -1126,9 +1085,6 @@ void GraphicsContext::FillRect(const FloatRect& rect,
void GraphicsContext::FillRoundedRect(const FloatRoundedRect& rrect,
const Color& color) {
- if (ContextDisabled())
- return;
-
if (!rrect.IsRounded() || !rrect.IsRenderable()) {
FillRect(rrect.Rect(), color);
return;
@@ -1191,8 +1147,6 @@ bool IsSimpleDRRect(const FloatRoundedRect& outer,
void GraphicsContext::FillDRRect(const FloatRoundedRect& outer,
const FloatRoundedRect& inner,
const Color& color) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
if (!IsSimpleDRRect(outer, inner)) {
@@ -1227,16 +1181,13 @@ void GraphicsContext::FillDRRect(const FloatRoundedRect& outer,
}
void GraphicsContext::FillEllipse(const FloatRect& ellipse) {
- if (ContextDisabled())
- return;
-
DrawOval(ellipse, ImmutableState()->FillFlags());
}
void GraphicsContext::StrokePath(const Path& path_to_stroke,
const int length,
const int dash_thickness) {
- if (ContextDisabled() || path_to_stroke.IsEmpty())
+ if (path_to_stroke.IsEmpty())
return;
DrawPath(path_to_stroke.GetSkPath(),
@@ -1244,9 +1195,6 @@ void GraphicsContext::StrokePath(const Path& path_to_stroke,
}
void GraphicsContext::StrokeRect(const FloatRect& rect, float line_width) {
- if (ContextDisabled())
- return;
-
PaintFlags flags(ImmutableState()->StrokeFlags());
flags.setStrokeWidth(WebCoreFloatToSkScalar(line_width));
// Reset the dash effect to account for the width
@@ -1271,18 +1219,12 @@ void GraphicsContext::StrokeRect(const FloatRect& rect, float line_width) {
}
void GraphicsContext::StrokeEllipse(const FloatRect& ellipse) {
- if (ContextDisabled())
- return;
-
DrawOval(ellipse, ImmutableState()->StrokeFlags());
}
void GraphicsContext::ClipRoundedRect(const FloatRoundedRect& rrect,
SkClipOp clip_op,
AntiAliasingMode should_antialias) {
- if (ContextDisabled())
- return;
-
if (!rrect.IsRounded()) {
ClipRect(rrect.Rect(), should_antialias, clip_op);
return;
@@ -1292,9 +1234,6 @@ void GraphicsContext::ClipRoundedRect(const FloatRoundedRect& rrect,
}
void GraphicsContext::ClipOut(const Path& path_to_clip) {
- if (ContextDisabled())
- return;
-
// Use const_cast and temporarily toggle the inverse fill type instead of
// copying the path.
SkPath& path = const_cast<SkPath&>(path_to_clip.GetSkPath());
@@ -1304,54 +1243,37 @@ void GraphicsContext::ClipOut(const Path& path_to_clip) {
}
void GraphicsContext::ClipOutRoundedRect(const FloatRoundedRect& rect) {
- if (ContextDisabled())
- return;
-
ClipRoundedRect(rect, SkClipOp::kDifference);
}
void GraphicsContext::ClipRect(const SkRect& rect,
AntiAliasingMode aa,
SkClipOp op) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->clipRect(rect, op, aa == kAntiAliased);
}
void GraphicsContext::ClipPath(const SkPath& path,
AntiAliasingMode aa,
SkClipOp op) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->clipPath(path, op, aa == kAntiAliased);
}
void GraphicsContext::ClipRRect(const SkRRect& rect,
AntiAliasingMode aa,
SkClipOp op) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->clipRRect(rect, op, aa == kAntiAliased);
}
void GraphicsContext::Rotate(float angle_in_radians) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->rotate(
WebCoreFloatToSkScalar(angle_in_radians * (180.0f / 3.14159265f)));
}
void GraphicsContext::Translate(float x, float y) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
if (!x && !y)
@@ -1361,18 +1283,13 @@ void GraphicsContext::Translate(float x, float y) {
}
void GraphicsContext::Scale(float x, float y) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
-
canvas_->scale(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}
void GraphicsContext::SetURLForRect(const KURL& link,
const IntRect& dest_rect) {
- if (ContextDisabled())
- return;
- DCHECK(canvas_);
+ DCHECK(canvas_ || tracker_);
// Intercept URL rects when painting previews.
if (IsPaintingPreview() && tracker_) {
@@ -1387,9 +1304,7 @@ void GraphicsContext::SetURLForRect(const KURL& link,
void GraphicsContext::SetURLFragmentForRect(const String& dest_name,
const IntRect& rect) {
- if (ContextDisabled())
- return;
- DCHECK(canvas_);
+ DCHECK(canvas_ || tracker_);
// Intercept URL rects when painting previews.
if (IsPaintingPreview() && tracker_) {
@@ -1404,8 +1319,6 @@ void GraphicsContext::SetURLFragmentForRect(const String& dest_name,
void GraphicsContext::SetURLDestinationLocation(const String& name,
const IntPoint& location) {
- if (ContextDisabled())
- return;
DCHECK(canvas_);
SkRect rect = SkRect::MakeXYWH(location.X(), location.Y(), 0, 0);
@@ -1422,9 +1335,6 @@ void GraphicsContext::FillRectWithRoundedHole(
const FloatRect& rect,
const FloatRoundedRect& rounded_hole_rect,
const Color& color) {
- if (ContextDisabled())
- return;
-
PaintFlags flags(ImmutableState()->FillFlags());
flags.setColor(
dark_mode_filter_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
index b33ed07b357..6e943b9810e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -70,14 +70,7 @@ class PLATFORM_EXPORT GraphicsContext {
USING_FAST_MALLOC(GraphicsContext);
public:
- enum DisabledMode {
- kNothingDisabled = 0, // Run as normal.
- kFullyDisabled = 1 // Do absolutely minimal work to remove the cost of
- // the context from performance tests.
- };
-
explicit GraphicsContext(PaintController&,
- DisabledMode = kNothingDisabled,
printing::MetafileSkia* = nullptr,
paint_preview::PaintPreviewTracker* = nullptr);
@@ -91,8 +84,6 @@ class PLATFORM_EXPORT GraphicsContext {
return paint_controller_;
}
- bool ContextDisabled() const { return disabled_state_; }
-
const DarkModeSettings& dark_mode_settings() const {
return dark_mode_filter_.settings();
}
@@ -242,22 +233,22 @@ class PLATFORM_EXPORT GraphicsContext {
const FloatRect* src_rect = nullptr,
bool has_filter_property = false,
SkBlendMode = SkBlendMode::kSrcOver,
- RespectImageOrientationEnum = kDoNotRespectImageOrientation);
- void DrawImageRRect(
- Image*,
- Image::ImageDecodingMode,
- const FloatRoundedRect& dest,
- const FloatRect& src_rect,
- bool has_filter_property = false,
- SkBlendMode = SkBlendMode::kSrcOver,
- RespectImageOrientationEnum = kDoNotRespectImageOrientation);
+ RespectImageOrientationEnum = kRespectImageOrientation);
+ void DrawImageRRect(Image*,
+ Image::ImageDecodingMode,
+ const FloatRoundedRect& dest,
+ const FloatRect& src_rect,
+ bool has_filter_property = false,
+ SkBlendMode = SkBlendMode::kSrcOver,
+ RespectImageOrientationEnum = kRespectImageOrientation);
void DrawImageTiled(Image* image,
const FloatRect& dest_rect,
const FloatRect& src_rect,
const FloatSize& scale_src_to_dest,
const FloatPoint& phase,
const FloatSize& repeat_spacing,
- SkBlendMode = SkBlendMode::kSrcOver);
+ SkBlendMode = SkBlendMode::kSrcOver,
+ RespectImageOrientationEnum = kRespectImageOrientation);
// These methods write to the canvas.
// Also drawLine(const IntPoint& point1, const IntPoint& point2) and
@@ -371,6 +362,9 @@ class PLATFORM_EXPORT GraphicsContext {
void DrawFocusRing(const Vector<IntRect>&,
float width,
int offset,
+ int default_offset,
+ float border_radius,
+ float min_border_width,
const Color&,
bool is_outset);
void DrawFocusRing(const Path&, float width, int offset, const Color&);
@@ -428,14 +422,25 @@ class PLATFORM_EXPORT GraphicsContext {
FloatPoint& p2,
float stroke_width);
- static int FocusRingOutsetExtent(int offset, int width, bool is_outset);
+ static int FocusRingOutsetExtent(int offset,
+ int default_offset,
+ int width,
+ bool is_outset);
void SetInDrawingRecorder(bool);
bool InDrawingRecorder() const { return in_drawing_recorder_; }
+ // Set the DOM Node Id on the canvas. This is used to associate
+ // the drawing commands with the structure tree for the page when
+ // creating a tagged PDF. Callers are responsible for restoring it.
+ void SetDOMNodeId(DOMNodeId);
+ DOMNodeId GetDOMNodeId() const;
+
static sk_sp<SkColorFilter> WebCoreColorFilterToSkiaColorFilter(ColorFilter);
private:
+ friend class ScopedDarkModeElementRoleOverride;
+
const GraphicsContextState* ImmutableState() const { return paint_state_; }
GraphicsContextState* MutableState() {
@@ -462,12 +467,19 @@ class PLATFORM_EXPORT GraphicsContext {
void RestoreLayer();
// Helpers for drawing a focus ring (drawFocusRing)
- void DrawFocusRingPath(const SkPath&, const Color&, float width);
- void DrawFocusRingRect(const SkRect&, const Color&, float width);
+ void DrawFocusRingPath(const SkPath&,
+ const Color&,
+ float width,
+ float border_radius);
+ void DrawFocusRingRect(const SkRect&,
+ const Color&,
+ float width,
+ float border_radius);
void DrawFocusRingInternal(const Vector<IntRect>&,
float width,
int offset,
+ float border_radius,
const Color&,
bool is_outset);
@@ -479,9 +491,6 @@ class PLATFORM_EXPORT GraphicsContext {
// Apply deferred paint state saves
void RealizePaintSave() {
- if (ContextDisabled())
- return;
-
if (paint_state_->SaveCount()) {
paint_state_->DecrementSaveCount();
++paint_state_index_;
@@ -503,7 +512,9 @@ class PLATFORM_EXPORT GraphicsContext {
class DarkModeFlags;
- // null indicates painting is contextDisabled. Never delete this object.
+ // This is owned by paint_recorder_. Never delete this object.
+ // Drawing operations are allowed only after the first BeginRecording() which
+ // initializes this to not null.
cc::PaintCanvas* canvas_;
PaintController& paint_controller_;
@@ -529,8 +540,6 @@ class PLATFORM_EXPORT GraphicsContext {
bool disable_destruction_checks_;
#endif
- const DisabledMode disabled_state_;
-
float device_scale_factor_;
// TODO(gilmanmh): Investigate making this base::Optional<DarkModeFilter>
@@ -540,6 +549,9 @@ class PLATFORM_EXPORT GraphicsContext {
unsigned is_painting_preview_ : 1;
unsigned in_drawing_recorder_ : 1;
+ // The current node ID, which is used for marked content in a tagged PDF.
+ DOMNodeId dom_node_id_ = kInvalidDOMNodeId;
+
DISALLOW_COPY_AND_ASSIGN(GraphicsContext);
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 7f39c9e8911..8cafc6b08ac 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -37,9 +37,7 @@
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/public/platform/web_float_rect.h"
-#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
@@ -76,12 +74,18 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
contents_visible_(true),
hit_testable_(false),
needs_check_raster_invalidation_(false),
+ contents_layer_is_picture_image_layer_(false),
painted_(false),
painting_phase_(kGraphicsLayerPaintAllWithOverflowClip),
parent_(nullptr),
mask_layer_(nullptr),
- contents_layer_(nullptr),
- contents_layer_id_(0) {
+ raster_invalidation_function_(
+ base::BindRepeating(&GraphicsLayer::SetNeedsDisplayInRect,
+ base::Unretained(this))) {
+ // TODO(crbug.com/1033240): Debugging information for the referenced bug.
+ // Remove when it is fixed.
+ CHECK(&client_);
+
#if DCHECK_IS_ON()
DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
client.VerifyNotPainting();
@@ -95,7 +99,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
GraphicsLayer::~GraphicsLayer() {
CcLayer()->ClearClient();
- SetContentsLayer(nullptr);
+ contents_layer_ = nullptr;
#if DCHECK_IS_ON()
client_.VerifyNotPainting();
@@ -125,10 +129,12 @@ void GraphicsLayer::AppendAdditionalInfoAsJSON(LayerTreeFlags flags,
if (&layer != layer_.get())
return;
- if ((flags & kLayerTreeIncludesPaintInvalidations) &&
+ if ((flags & (kLayerTreeIncludesInvalidations |
+ kLayerTreeIncludesDetailedInvalidations)) &&
Client().IsTrackingRasterInvalidations() &&
GetRasterInvalidationTracking()) {
- GetRasterInvalidationTracking()->AsJSON(&json);
+ GetRasterInvalidationTracking()->AsJSON(
+ &json, flags & kLayerTreeIncludesDetailedInvalidations);
}
GraphicsLayerPaintingPhase painting_phase = PaintingPhase();
@@ -206,11 +212,10 @@ bool GraphicsLayer::SetChildren(const GraphicsLayerVector& new_children) {
RemoveAllChildren();
- size_t list_size = new_children.size();
- for (size_t i = 0; i < list_size; ++i)
- AddChildInternal(new_children[i]);
+ for (auto* new_child : new_children)
+ AddChildInternal(new_child);
- UpdateChildList();
+ NotifyChildListChange();
return true;
}
@@ -224,13 +229,13 @@ void GraphicsLayer::AddChildInternal(GraphicsLayer* child_layer) {
child_layer->SetParent(this);
children_.push_back(child_layer);
- // Don't call updateChildList here, this function is used in cases where it
- // should not be called until all children are processed.
+ // Don't call NotifyChildListChange here, this function is used in cases where
+ // it should not be called until all children are processed.
}
void GraphicsLayer::AddChild(GraphicsLayer* child_layer) {
AddChildInternal(child_layer);
- UpdateChildList();
+ NotifyChildListChange();
}
void GraphicsLayer::RemoveAllChildren() {
@@ -258,8 +263,6 @@ void GraphicsLayer::SetOffsetFromLayoutObject(const IntSize& offset) {
return;
offset_from_layout_object_ = offset;
- CcLayer()->SetFiltersOrigin(FloatPoint() -
- FloatSize(offset_from_layout_object_));
// If the compositing layer offset changes, we need to repaint.
SetNeedsDisplay();
@@ -287,6 +290,9 @@ bool GraphicsLayer::PaintRecursively() {
void GraphicsLayer::PaintRecursivelyInternal(
Vector<GraphicsLayer*>& repainted_layers) {
+ // TODO(crbug.com/1033240): Debugging information for the referenced bug.
+ // Remove when it is fixed.
+ CHECK(&client_);
if (client_.PaintBlockedByDisplayLockIncludingAncestors(
DisplayLockContextLifecycleTarget::kSelf)) {
return;
@@ -304,7 +310,7 @@ void GraphicsLayer::PaintRecursivelyInternal(
child->PaintRecursivelyInternal(repainted_layers);
}
-bool GraphicsLayer::Paint(GraphicsContext::DisabledMode disabled_mode) {
+bool GraphicsLayer::Paint() {
#if !DCHECK_IS_ON()
// TODO(crbug.com/853096): Investigate why we can ever reach here without
// a valid layer state. Seems to only happen on Android builds.
@@ -312,7 +318,7 @@ bool GraphicsLayer::Paint(GraphicsContext::DisabledMode disabled_mode) {
return false;
#endif
- if (PaintWithoutCommit(disabled_mode)) {
+ if (PaintWithoutCommit()) {
GetPaintController().CommitNewDisplayItems();
UpdateSafeOpaqueBackgroundColor();
} else if (!needs_check_raster_invalidation_) {
@@ -330,6 +336,7 @@ bool GraphicsLayer::Paint(GraphicsContext::DisabledMode disabled_mode) {
// Generate raster invalidations for SPv1.
IntRect layer_bounds(layer_state_->offset, IntSize(Size()));
EnsureRasterInvalidator().Generate(
+ raster_invalidation_function_,
GetPaintController().GetPaintArtifactShared(), layer_bounds,
layer_state_->state, VisualRectSubpixelOffset(), this);
@@ -354,21 +361,17 @@ bool GraphicsLayer::Paint(GraphicsContext::DisabledMode disabled_mode) {
void GraphicsLayer::UpdateSafeOpaqueBackgroundColor() {
if (!DrawsContent())
return;
- // Copy the first chunk's safe opaque background color over to the cc::Layer.
- const auto& chunks = GetPaintController().GetPaintArtifact().PaintChunks();
CcLayer()->SetSafeOpaqueBackgroundColor(
- chunks.size() ? chunks[0].safe_opaque_background_color : SK_ColorWHITE);
+ GetPaintController().GetPaintArtifact().SafeOpaqueBackgroundColor(
+ GetPaintController().GetPaintArtifact().PaintChunks()));
}
bool GraphicsLayer::PaintWithoutCommitForTesting(
const base::Optional<IntRect>& interest_rect) {
- return PaintWithoutCommit(GraphicsContext::kNothingDisabled,
- base::OptionalOrNullptr(interest_rect));
+ return PaintWithoutCommit(base::OptionalOrNullptr(interest_rect));
}
-bool GraphicsLayer::PaintWithoutCommit(
- GraphicsContext::DisabledMode disabled_mode,
- const IntRect* interest_rect) {
+bool GraphicsLayer::PaintWithoutCommit(const IntRect* interest_rect) {
DCHECK(PaintsContentOrHitTest());
if (client_.ShouldThrottleRendering() || client_.IsUnderSVGHiddenContainer())
@@ -381,7 +384,7 @@ bool GraphicsLayer::PaintWithoutCommit(
interest_rect = &new_interest_rect;
}
- if (!GetPaintController().SubsequenceCachingIsDisabled() &&
+ if (!GetPaintController().ShouldForcePaintForBenchmark() &&
!client_.NeedsRepaint(*this) &&
!GetPaintController().CacheIsAllInvalid() &&
previous_interest_rect_ == *interest_rect) {
@@ -389,9 +392,9 @@ bool GraphicsLayer::PaintWithoutCommit(
return false;
}
- GraphicsContext context(GetPaintController(), disabled_mode, nullptr);
+ GraphicsContext context(GetPaintController());
DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
- GetPaintController().UpdateCurrentPaintChunkProperties(base::nullopt,
+ GetPaintController().UpdateCurrentPaintChunkProperties(nullptr,
layer_state_->state);
previous_interest_rect_ = *interest_rect;
@@ -399,7 +402,7 @@ bool GraphicsLayer::PaintWithoutCommit(
return true;
}
-void GraphicsLayer::UpdateChildList() {
+void GraphicsLayer::NotifyChildListChange() {
// cc::Layers are created in PaintArtifactCompositor.
client_.GraphicsLayersDidChange();
}
@@ -412,125 +415,56 @@ void GraphicsLayer::UpdateLayerIsDrawable() {
// contentsVisible.
CcLayer()->SetIsDrawable(draws_content_ && contents_visible_);
- if (cc::Layer* contents_layer = ContentsLayerIfRegistered())
- contents_layer->SetIsDrawable(contents_visible_);
+ if (contents_layer_)
+ contents_layer_->SetIsDrawable(contents_visible_);
if (draws_content_)
CcLayer()->SetNeedsDisplay();
}
-void GraphicsLayer::UpdateContentsRect() {
- cc::Layer* contents_layer = ContentsLayerIfRegistered();
- if (!contents_layer)
+void GraphicsLayer::UpdateContentsLayerBounds() {
+ if (!contents_layer_)
return;
- contents_layer->SetPosition(
- FloatPoint(contents_rect_.X(), contents_rect_.Y()));
- if (!image_layer_) {
- contents_layer->SetBounds(static_cast<gfx::Size>(contents_rect_.Size()));
- } else {
- DCHECK_EQ(image_layer_.get(), contents_layer_);
- // The image_layer_ has fixed bounds, and we apply bounds changes via the
- // transform instead. Since we never change the transform on the
- // |image_layer_| otherwise, we can assume it is identity and just apply
- // the bounds to it directly. Same thing for transform origin.
- DCHECK(image_layer_->transform_origin() == gfx::Point3F());
-
- if (contents_rect_.Size().IsEmpty() || image_size_.IsEmpty()) {
- image_layer_->SetTransform(gfx::Transform());
- contents_layer->SetBounds(static_cast<gfx::Size>(contents_rect_.Size()));
- } else {
- gfx::Transform image_transform;
- image_transform.Scale(
- static_cast<float>(contents_rect_.Width()) / image_size_.Width(),
- static_cast<float>(contents_rect_.Height()) / image_size_.Height());
- image_layer_->SetTransform(image_transform);
- image_layer_->SetBounds(static_cast<gfx::Size>(image_size_));
- }
+ IntSize contents_size = contents_rect_.Size();
+ if (contents_layer_is_picture_image_layer_) {
+ if (!contents_size.IsEmpty() && !image_size_.IsEmpty())
+ contents_size = image_size_;
}
+ contents_layer_->SetBounds(gfx::Size(contents_size));
}
-static HashSet<int>* g_registered_layer_set;
-
-void GraphicsLayer::RegisterContentsLayer(cc::Layer* layer) {
- if (!g_registered_layer_set)
- g_registered_layer_set = new HashSet<int>;
- CHECK(!g_registered_layer_set->Contains(layer->id()));
- g_registered_layer_set->insert(layer->id());
-}
-
-void GraphicsLayer::UnregisterContentsLayer(cc::Layer* layer) {
- DCHECK(g_registered_layer_set);
- CHECK(g_registered_layer_set->Contains(layer->id()));
- g_registered_layer_set->erase(layer->id());
+void GraphicsLayer::SetContentsToCcLayer(
+ scoped_refptr<cc::Layer> contents_layer,
+ bool prevent_contents_opaque_changes) {
+ DCHECK_NE(contents_layer, layer_);
+ SetContentsTo(std::move(contents_layer), prevent_contents_opaque_changes);
+ contents_layer_is_picture_image_layer_ = false;
}
-void GraphicsLayer::SetContentsTo(cc::Layer* layer,
+void GraphicsLayer::SetContentsTo(scoped_refptr<cc::Layer> layer,
bool prevent_contents_opaque_changes) {
- bool children_changed = false;
if (layer) {
- DCHECK(g_registered_layer_set);
- CHECK(g_registered_layer_set->Contains(layer->id()));
- if (contents_layer_id_ != layer->id()) {
- SetupContentsLayer(layer);
- children_changed = true;
+ if (contents_layer_ != layer) {
+ contents_layer_ = std::move(layer);
+ // It is necessary to call SetDrawsContent() as soon as we receive the new
+ // contents_layer, for the correctness of early exit conditions in
+ // SetDrawsContent() and SetContentsVisible().
+ contents_layer_->SetIsDrawable(contents_visible_);
+ contents_layer_->SetHitTestable(contents_visible_);
+ NotifyChildListChange();
}
- UpdateContentsRect();
+ UpdateContentsLayerBounds();
prevent_contents_opaque_changes_ = prevent_contents_opaque_changes;
- } else {
- if (contents_layer_) {
- children_changed = true;
-
- // The old contents layer will be removed via updateChildList.
- SetContentsLayer(nullptr);
- }
+ } else if (contents_layer_) {
+ contents_layer_ = nullptr;
+ NotifyChildListChange();
}
-
- if (children_changed)
- UpdateChildList();
-}
-
-void GraphicsLayer::SetupContentsLayer(cc::Layer* contents_layer) {
- DCHECK(contents_layer);
- SetContentsLayer(contents_layer);
-
- contents_layer_->SetTransformOrigin(FloatPoint3D());
- contents_layer_->SetUseParentBackfaceVisibility(true);
-
- // It is necessary to call SetDrawsContent() as soon as we receive the new
- // contents_layer, for the correctness of early exit conditions in
- // SetDrawsContent() and SetContentsVisible().
- contents_layer_->SetIsDrawable(contents_visible_);
- contents_layer_->SetHitTestable(contents_visible_);
-}
-
-void GraphicsLayer::ClearContentsLayerIfUnregistered() {
- if (!contents_layer_id_ ||
- g_registered_layer_set->Contains(contents_layer_id_))
- return;
-
- SetContentsLayer(nullptr);
-}
-
-void GraphicsLayer::SetContentsLayer(cc::Layer* contents_layer) {
- contents_layer_ = contents_layer;
- if (!contents_layer_) {
- contents_layer_id_ = 0;
- return;
- }
- contents_layer_id_ = contents_layer_->id();
-}
-
-cc::Layer* GraphicsLayer::ContentsLayerIfRegistered() {
- ClearContentsLayerIfUnregistered();
- return contents_layer_;
}
RasterInvalidator& GraphicsLayer::EnsureRasterInvalidator() {
if (!raster_invalidator_) {
- raster_invalidator_ =
- std::make_unique<RasterInvalidator>(base::BindRepeating(
- &GraphicsLayer::SetNeedsDisplayInRect, base::Unretained(this)));
+ raster_invalidator_ = std::make_unique<RasterInvalidator>();
raster_invalidator_->SetTracksRasterInvalidations(
client_.IsTrackingRasterInvalidations());
}
@@ -575,7 +509,7 @@ void GraphicsLayer::TrackRasterInvalidation(const DisplayItemClient& client,
}
String GraphicsLayer::DebugName(const cc::Layer* layer) const {
- if (layer->id() == contents_layer_id_)
+ if (layer == contents_layer_.get())
return "ContentsLayer for " + client_.DebugName(this);
if (layer == layer_.get())
@@ -601,15 +535,6 @@ void GraphicsLayer::SetSize(const gfx::Size& size) {
// Note that we don't resize m_contentsLayer. It's up the caller to do that.
}
-
-bool GraphicsLayer::MasksToBounds() const {
- return CcLayer()->masks_to_bounds();
-}
-
-void GraphicsLayer::SetMasksToBounds(bool masks_to_bounds) {
- CcLayer()->SetMasksToBounds(masks_to_bounds);
-}
-
void GraphicsLayer::SetDrawsContent(bool draws_content) {
// NOTE: This early-exit is only correct because we also properly call
// cc::Layer::SetIsDrawable() whenever |contents_layer_| is set to a new
@@ -651,7 +576,6 @@ bool GraphicsLayer::ContentsOpaque() const {
void GraphicsLayer::SetContentsOpaque(bool opaque) {
CcLayer()->SetContentsOpaque(opaque);
- ClearContentsLayerIfUnregistered();
if (contents_layer_ && !prevent_contents_opaque_changes_)
contents_layer_->SetContentsOpaque(opaque);
}
@@ -675,8 +599,8 @@ void GraphicsLayer::SetHitTestable(bool should_hit_test) {
}
void GraphicsLayer::SetContentsNeedsDisplay() {
- if (cc::Layer* contents_layer = ContentsLayerIfRegistered()) {
- contents_layer->SetNeedsDisplay();
+ if (contents_layer_) {
+ contents_layer_->SetNeedsDisplay();
TrackRasterInvalidation(*this, contents_rect_,
PaintInvalidationReason::kFullLayer);
}
@@ -710,7 +634,7 @@ void GraphicsLayer::SetContentsRect(const IntRect& rect) {
return;
contents_rect_ = rect;
- UpdateContentsRect();
+ UpdateContentsLayerBounds();
client_.GraphicsLayersDidChange();
}
@@ -724,16 +648,17 @@ void GraphicsLayer::SetContentsToImage(
ImageOrientation image_orientation = kOriginTopLeft;
SkMatrix matrix;
- if (paint_image && image->IsBitmapImage() &&
+ auto* bitmap_image = DynamicTo<BitmapImage>(image);
+ if (paint_image && bitmap_image &&
respect_image_orientation == kRespectImageOrientation) {
- image_orientation = ToBitmapImage(image)->CurrentFrameOrientation();
+ image_orientation = bitmap_image->CurrentFrameOrientation();
image_size_ = IntSize(paint_image.width(), paint_image.height());
if (image_orientation.UsesWidthAsHeight())
image_size_ = image_size_.TransposedSize();
auto affine =
image_orientation.TransformFromDefault(FloatSize(image_size_));
auto transform = affine.ToTransformationMatrix();
- matrix = TransformationMatrix::ToSkMatrix44(transform);
+ matrix = SkMatrix(TransformationMatrix::ToSkMatrix44(transform));
} else if (paint_image) {
matrix = SkMatrix::I();
image_size_ = IntSize(paint_image.width(), paint_image.height());
@@ -742,27 +667,28 @@ void GraphicsLayer::SetContentsToImage(
image_size_ = IntSize();
}
+ scoped_refptr<cc::PictureImageLayer> image_layer;
if (paint_image) {
paint_image =
PaintImageBuilder::WithCopy(std::move(paint_image))
.set_decoding_mode(Image::ToPaintImageDecodingMode(decode_mode))
.TakePaintImage();
- if (!image_layer_) {
- image_layer_ = cc::PictureImageLayer::Create();
- RegisterContentsLayer(image_layer_.get());
+ if (!contents_layer_is_picture_image_layer_) {
+ image_layer = cc::PictureImageLayer::Create();
+ contents_layer_is_picture_image_layer_ = true;
+ } else {
+ image_layer = static_cast<cc::PictureImageLayer*>(contents_layer_.get());
}
- image_layer_->SetImage(std::move(paint_image), matrix,
- image_orientation.UsesWidthAsHeight());
+ image_layer->SetImage(std::move(paint_image), matrix,
+ image_orientation.UsesWidthAsHeight());
// Image layers can not be marked as opaque due to crbug.com/870857.
- image_layer_->SetContentsOpaque(false);
- UpdateContentsRect();
- } else if (image_layer_) {
- UnregisterContentsLayer(image_layer_.get());
- image_layer_ = nullptr;
+ image_layer->SetContentsOpaque(false);
+ } else {
+ contents_layer_is_picture_image_layer_ = false;
}
- SetContentsTo(image_layer_.get(),
- /*prevent_contents_opaque_changes=*/true);
+ SetContentsTo(std::move(image_layer),
+ /* prevent_contents_opaque_changes=*/true);
}
cc::PictureLayer* GraphicsLayer::CcLayer() const {
@@ -770,8 +696,10 @@ cc::PictureLayer* GraphicsLayer::CcLayer() const {
}
void GraphicsLayer::SetFilterQuality(SkFilterQuality filter_quality) {
- if (image_layer_)
- image_layer_->SetNearestNeighbor(filter_quality == kNone_SkFilterQuality);
+ if (contents_layer_is_picture_image_layer_) {
+ static_cast<cc::PictureImageLayer*>(contents_layer_.get())
+ ->SetNearestNeighbor(filter_quality == kNone_SkFilterQuality);
+ }
}
void GraphicsLayer::SetPaintingPhase(GraphicsLayerPaintingPhase phase) {
@@ -857,35 +785,24 @@ scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
PaintingControlSetting painting_control) {
TRACE_EVENT0("blink,benchmark", "GraphicsLayer::PaintContents");
- PaintController& paint_controller = GetPaintController();
- paint_controller.SetDisplayItemConstructionIsDisabled(
- painting_control == DISPLAY_LIST_CONSTRUCTION_DISABLED);
- paint_controller.SetSubsequenceCachingIsDisabled(
- painting_control == SUBSEQUENCE_CACHING_DISABLED);
-
- if (painting_control == PARTIAL_INVALIDATION)
- client_.InvalidateTargetElementForTesting();
+ if (painting_control == SUBSEQUENCE_CACHING_DISABLED)
+ PaintController::SetSubsequenceCachingDisabledForBenchmark();
+ else if (painting_control == PARTIAL_INVALIDATION)
+ PaintController::SetPartialInvalidationForBenchmark();
+ PaintController& paint_controller = GetPaintController();
// We also disable caching when Painting or Construction are disabled. In both
// cases we would like to compare assuming the full cost of recording, not the
// cost of re-using cached content.
- if (painting_control == DISPLAY_LIST_CACHING_DISABLED ||
- painting_control == DISPLAY_LIST_PAINTING_DISABLED ||
- painting_control == DISPLAY_LIST_CONSTRUCTION_DISABLED)
+ if (painting_control == DISPLAY_LIST_CACHING_DISABLED)
paint_controller.InvalidateAll();
- GraphicsContext::DisabledMode disabled_mode =
- GraphicsContext::kNothingDisabled;
- if (painting_control == DISPLAY_LIST_PAINTING_DISABLED ||
- painting_control == DISPLAY_LIST_CONSTRUCTION_DISABLED)
- disabled_mode = GraphicsContext::kFullyDisabled;
-
// Anything other than PAINTING_BEHAVIOR_NORMAL is for testing. In non-testing
// scenarios, it is an error to call GraphicsLayer::Paint. Actual painting
// occurs in LocalFrameView::PaintTree() which calls GraphicsLayer::Paint();
// this method merely copies the painted output to the cc::DisplayItemList.
if (painting_control != PAINTING_BEHAVIOR_NORMAL)
- Paint(disabled_mode);
+ Paint();
auto display_list = base::MakeRefCounted<cc::DisplayItemList>();
@@ -896,8 +813,7 @@ scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
VisualRectSubpixelOffset(),
paint_controller.GetPaintArtifact().GetDisplayItemList(), *display_list);
- paint_controller.SetDisplayItemConstructionIsDisabled(false);
- paint_controller.SetSubsequenceCachingIsDisabled(false);
+ PaintController::ClearFlagsForBenchmark();
display_list->Finalize();
return display_list;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 269eb43a3ef..14ed1bad11b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -47,6 +47,7 @@
#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h"
#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h"
#include "third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -57,7 +58,6 @@
#include "third_party/skia/include/core/SkRefCnt.h"
namespace cc {
-class PictureImageLayer;
class PictureLayer;
} // namespace cc
@@ -127,15 +127,12 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
void SetRenderingContext(int id);
- bool MasksToBounds() const;
- void SetMasksToBounds(bool);
-
bool DrawsContent() const { return draws_content_; }
void SetDrawsContent(bool);
- // False if no hit test display items will be painted onto this GraphicsLayer.
- // This is different from |DrawsContent| because hit test display items are
- // internal to blink and are not copied to the cc::Layer's display list.
+ // False if no hit test data will be recorded onto this GraphicsLayer.
+ // This is different from |DrawsContent| because hit test data are internal
+ // to blink and are not copied to the cc::Layer's display list.
bool PaintsHitTest() const { return paints_hit_test_; }
void SetPaintsHitTest(bool paints) { paints_hit_test_ = paints; }
@@ -177,19 +174,15 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
void SetContentsToImage(
Image*,
Image::ImageDecodingMode decode_mode,
- RespectImageOrientationEnum = kDoNotRespectImageOrientation);
+ RespectImageOrientationEnum = kRespectImageOrientation);
// If |prevent_contents_opaque_changes| is set to true, then calls to
- // SetContentsOpaque() will not be passed on to the |layer|. Use when
- // the client wants to have control of the opaqueness of the contents
- // |layer| independently of what outcome painting produces.
- void SetContentsToCcLayer(cc::Layer* layer,
- bool prevent_contents_opaque_changes) {
- SetContentsTo(layer, prevent_contents_opaque_changes);
- }
+ // SetContentsOpaque() will not be passed on to |contents_layer|. Use when
+ // the client wants to have control of the opaqueness of |contents_layer|
+ // independently of what outcome painting produces.
+ void SetContentsToCcLayer(scoped_refptr<cc::Layer> contents_layer,
+ bool prevent_contents_opaque_changes);
bool HasContentsLayer() const { return ContentsLayer(); }
- cc::Layer* ContentsLayer() const {
- return const_cast<GraphicsLayer*>(this)->ContentsLayerIfRegistered();
- }
+ cc::Layer* ContentsLayer() const { return contents_layer_.get(); }
const IntRect& ContentsRect() const { return contents_rect_; }
@@ -204,13 +197,10 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
const IntRect&,
PaintInvalidationReason);
- static void RegisterContentsLayer(cc::Layer*);
- static void UnregisterContentsLayer(cc::Layer*);
-
IntRect InterestRect();
bool PaintRecursively();
// Returns true if this layer is repainted.
- bool Paint(GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled);
+ bool Paint();
PaintController& GetPaintController() const;
@@ -275,12 +265,10 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
void UpdateSafeOpaqueBackgroundColor();
// Returns true if PaintController::PaintArtifact() changed and needs commit.
- bool PaintWithoutCommit(
- GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled,
- const IntRect* interest_rect = nullptr);
+ bool PaintWithoutCommit(const IntRect* interest_rect = nullptr);
- // Adds a child without calling updateChildList(), so that adding children
- // can be batched before updating.
+ // Adds a child without calling NotifyChildListChange(), so that adding
+ // children can be batched before updating.
void AddChildInternal(GraphicsLayer*);
#if DCHECK_IS_ON()
@@ -288,15 +276,12 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
#endif
// Helper functions used by settors to keep layer's the state consistent.
- void UpdateChildList();
+ void NotifyChildListChange();
void UpdateLayerIsDrawable();
- void UpdateContentsRect();
+ void UpdateContentsLayerBounds();
- void SetContentsTo(cc::Layer*, bool prevent_contents_opaque_changes);
- void SetupContentsLayer(cc::Layer*);
- void ClearContentsLayerIfUnregistered();
- cc::Layer* ContentsLayerIfRegistered();
- void SetContentsLayer(cc::Layer*);
+ void SetContentsTo(scoped_refptr<cc::Layer>,
+ bool prevent_contents_opaque_changes);
RasterInvalidator& EnsureRasterInvalidator();
void SetNeedsDisplayInRect(const IntRect&);
@@ -316,6 +301,7 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
bool contents_visible_ : 1;
bool hit_testable_ : 1;
bool needs_check_raster_invalidation_ : 1;
+ bool contents_layer_is_picture_image_layer_ : 1;
bool painted_ : 1;
@@ -330,15 +316,8 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
IntRect contents_rect_;
scoped_refptr<cc::PictureLayer> layer_;
- scoped_refptr<cc::PictureImageLayer> image_layer_;
IntSize image_size_;
- cc::Layer* contents_layer_;
- // We don't have ownership of contents_layer_, but we do want to know if a
- // given layer is the same as our current layer in SetContentsTo(). Since
- // |contents_layer_| may be deleted at this point, we stash an ID away when we
- // know |contents_layer_| is alive and use that for comparisons from that
- // point on.
- int contents_layer_id_;
+ scoped_refptr<cc::Layer> contents_layer_;
SquashingDisallowedReasons squashing_disallowed_reasons_ =
SquashingDisallowedReason::kNone;
@@ -355,6 +334,7 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
std::unique_ptr<LayerState> contents_layer_state_;
std::unique_ptr<RasterInvalidator> raster_invalidator_;
+ RasterInvalidator::RasterInvalidationFunction raster_invalidation_function_;
DOMNodeId owner_node_id_ = kInvalidDOMNodeId;
CompositingReasons compositing_reasons_ = CompositingReason::kNone;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
index 091a8e66c36..0106ae1c9be 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
@@ -56,8 +56,6 @@ class PLATFORM_EXPORT GraphicsLayerClient {
public:
virtual ~GraphicsLayerClient() = default;
- virtual void InvalidateTargetElementForTesting() {}
-
virtual IntRect ComputeInterestRect(
const GraphicsLayer*,
const IntRect& previous_interest_rect) const = 0;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
index e1c3148b159..35ea37342e2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
@@ -149,11 +149,10 @@ TEST_P(GraphicsLayerTest, SetDrawsContentFalse) {
TEST_P(GraphicsLayerTest, ContentsLayer) {
auto& graphics_layer = layers_.graphics_layer();
auto contents_layer = cc::Layer::Create();
- GraphicsLayer::RegisterContentsLayer(contents_layer.get());
- graphics_layer.SetContentsToCcLayer(contents_layer.get(), true);
+ graphics_layer.SetContentsToCcLayer(contents_layer, true);
EXPECT_TRUE(graphics_layer.HasContentsLayer());
EXPECT_EQ(contents_layer.get(), graphics_layer.ContentsLayer());
- GraphicsLayer::UnregisterContentsLayer(contents_layer.get());
+ graphics_layer.SetContentsToCcLayer(nullptr, true);
EXPECT_FALSE(graphics_layer.HasContentsLayer());
EXPECT_EQ(nullptr, graphics_layer.ContentsLayer());
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.cc b/chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.cc
deleted file mode 100644
index ce10491b66e..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/hit_test_rect.h"
-
-#include "cc/base/region.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-// static
-LayoutRect HitTestRect::GetBounds(const Vector<HitTestRect>& hit_test_rects) {
- cc::Region region;
- for (const HitTestRect& hit_test_rect : hit_test_rects) {
- const LayoutRect& rect = hit_test_rect.rect;
- region.Union(EnclosingIntRect(rect));
- }
- const auto& rect = region.bounds();
- return LayoutRect(IntRect(rect));
-}
-
-String HitTestRect::ToString() const {
- // TODO(pdr): Print the value of |allowed_touch_action|.
- return rect.ToString();
-}
-
-std::ostream& operator<<(std::ostream& os, const HitTestRect& hit_test_rect) {
- return os << hit_test_rect.ToString();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.h b/chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.h
deleted file mode 100644
index 258b6848f7d..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/hit_test_rect.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_HIT_TEST_RECT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_HIT_TEST_RECT_H_
-
-#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/graphics/touch_action.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-
-// TODO(pdr): Rename this TouchActionRect.
-struct PLATFORM_EXPORT HitTestRect {
- LayoutRect rect;
- TouchAction allowed_touch_action;
-
- HitTestRect(const LayoutRect& layout_rect)
- : HitTestRect(layout_rect, TouchAction::kTouchActionNone) {}
- HitTestRect(const LayoutRect& layout_rect, TouchAction action)
- : rect(layout_rect), allowed_touch_action(action) {}
-
- static LayoutRect GetBounds(const Vector<HitTestRect>&);
-
- bool operator==(const HitTestRect& rhs) const {
- return rect == rhs.rect && allowed_touch_action == rhs.allowed_touch_action;
- }
-
- bool operator!=(const HitTestRect& rhs) const { return !(*this == rhs); }
-
- String ToString() const;
-};
-
-PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const HitTestRect&);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_HIT_TEST_RECT_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.cc b/chromium/third_party/blink/renderer/platform/graphics/image.cc
index bcb20fdcc85..444fec9627d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.cc
@@ -215,7 +215,8 @@ void Image::DrawPattern(GraphicsContext& context,
const FloatPoint& phase,
SkBlendMode composite_op,
const FloatRect& dest_rect,
- const FloatSize& repeat_spacing) {
+ const FloatSize& repeat_spacing,
+ RespectImageOrientationEnum) {
TRACE_EVENT0("skia", "Image::drawPattern");
if (dest_rect.IsEmpty())
@@ -325,16 +326,22 @@ bool Image::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) {
return true;
}
+IntSize Image::Size(
+ RespectImageOrientationEnum respect_image_orientation) const {
+ if (respect_image_orientation == kRespectImageOrientation)
+ return SizeRespectingOrientation();
+ return Size();
+}
+
SkBitmap Image::AsSkBitmapForCurrentFrame(
- RespectImageOrientationEnum should_respect_image_orientation) {
+ RespectImageOrientationEnum respect_image_orientation) {
PaintImage paint_image = PaintImageForCurrentFrame();
if (!paint_image)
return {};
- if (should_respect_image_orientation == kRespectImageOrientation &&
- IsBitmapImage()) {
- ImageOrientation orientation =
- ToBitmapImage(this)->CurrentFrameOrientation();
+ auto* bitmap_image = DynamicTo<BitmapImage>(this);
+ if (respect_image_orientation == kRespectImageOrientation && bitmap_image) {
+ ImageOrientation orientation = bitmap_image->CurrentFrameOrientation();
paint_image = ResizeAndOrientImage(paint_image, orientation);
if (!paint_image)
return {};
@@ -372,6 +379,15 @@ bool Image::GetBitmap(const FloatRect& src_rect, SkBitmap* bitmap) {
return true;
}
+FloatRect Image::CorrectSrcRectForImageOrientation(FloatSize image_size,
+ FloatRect src_rect) const {
+ ImageOrientation orientation = CurrentFrameOrientation();
+ DCHECK(orientation != kDefaultImageOrientation);
+ AffineTransform forward_map = orientation.TransformFromDefault(image_size);
+ AffineTransform inverse_map = forward_map.Inverse();
+ return inverse_map.MapRect(src_rect);
+}
+
DarkModeClassification Image::GetDarkModeClassification(
const FloatRect& src_rect) {
// Assuming that multiple uses of the same sprite region all have the same
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.h b/chromium/third_party/blink/renderer/platform/graphics/image.h
index 445dbd8f71f..40cce084170 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.h
@@ -30,6 +30,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
+#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
@@ -57,7 +58,6 @@ class ImageDecodeCache;
namespace blink {
class DarkModeImageClassifier;
-class FloatPoint;
class FloatRect;
class GraphicsContext;
class Image;
@@ -109,9 +109,16 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
virtual bool HasIntrinsicSize() const { return true; }
virtual IntSize Size() const = 0;
+ IntSize Size(RespectImageOrientationEnum) const;
+ virtual IntSize SizeRespectingOrientation() const { return Size(); }
+ virtual FloatSize SizeAsFloat(
+ RespectImageOrientationEnum respect_orientation) const {
+ return FloatSize(Size(respect_orientation));
+ }
IntRect Rect() const { return IntRect(IntPoint(), Size()); }
int width() const { return Size().Width(); }
int height() const { return Size().Height(); }
+
virtual bool GetHotSpot(IntPoint&) const { return false; }
enum SizeAvailability {
@@ -201,6 +208,22 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
virtual PaintImage PaintImageForCurrentFrame() = 0;
+ virtual bool HasDefaultOrientation() const { return true; }
+
+ // Most image types have the default orientation. Only bitmap derived image
+ // types need to override this method.
+ virtual ImageOrientation CurrentFrameOrientation() const {
+ return kDefaultImageOrientation;
+ }
+
+ // Correct the src rect (rotate and maybe translate it) to account for a
+ // non-default image orientation. The image must have non-default orientation
+ // to call this method. The image_size is the oriented size of the image (i.e.
+ // after orientation has been applied). src_rect may be a subset of the image,
+ // also oriented.
+ FloatRect CorrectSrcRectForImageOrientation(FloatSize image_size,
+ FloatRect src_rect) const;
+
enum ImageClampingMode {
kClampImageToSourceRect,
kDoNotClampImageToSourceRect
@@ -276,7 +299,8 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
const FloatPoint& phase,
SkBlendMode,
const FloatRect&,
- const FloatSize& repeat_spacing);
+ const FloatSize& repeat_spacing,
+ RespectImageOrientationEnum);
// Creates and initializes a PaintImageBuilder with the metadata flags for the
// PaintImage.
@@ -285,7 +309,7 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
// Whether or not size is available yet.
virtual bool IsSizeAvailable() { return true; }
- typedef FloatSize ClassificationKey;
+ typedef FloatPoint ClassificationKey;
HashMap<ClassificationKey, DarkModeClassification> dark_mode_classifications_;
private:
@@ -304,10 +328,6 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
DISALLOW_COPY_AND_ASSIGN(Image);
};
-#define DEFINE_IMAGE_TYPE_CASTS(typeName) \
- DEFINE_TYPE_CASTS(typeName, Image, image, image->Is##typeName(), \
- image.Is##typeName())
-
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc b/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc
index 5a6dab40814..4c261b515a9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_decoder_wrapper.cc
@@ -112,7 +112,7 @@ bool ImageDecoderWrapper::Decode(ImageDecoderFactory* factory,
// For multi-frame image decoders, we need to know how many frames are
// in that image in order to release the decoder when all frames are
- // decoded. frameCount() is reliable only if all data is received and set in
+ // decoded. FrameCount() is reliable only if all data is received and set in
// decoder, particularly with GIF.
if (all_data_received_)
*frame_count = decoder->FrameCount();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_observer.h b/chromium/third_party/blink/renderer/platform/graphics/image_observer.h
index db0a5275b0a..1cf6d753c4d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_observer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_observer.h
@@ -51,7 +51,7 @@ class PLATFORM_EXPORT ImageObserver : public GarbageCollectedMixin {
// See the comment of Image::SetData().
virtual void AsyncLoadCompleted(const Image*) = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
index bb7e49923e7..8ede5551e3c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
@@ -86,19 +86,6 @@ class InterceptingCanvasBase : public SkCanvas {
void onDrawOval(const SkRect&, const SkPaint&) override = 0;
void onDrawRRect(const SkRRect&, const SkPaint&) override = 0;
void onDrawPath(const SkPath&, const SkPaint&) override = 0;
- void onDrawBitmap(const SkBitmap&,
- SkScalar left,
- SkScalar top,
- const SkPaint*) override = 0;
- void onDrawBitmapRect(const SkBitmap&,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint*,
- SrcRectConstraint) override = 0;
- void onDrawBitmapNine(const SkBitmap&,
- const SkIRect& center,
- const SkRect& dst,
- const SkPaint*) override = 0;
void onDrawImage(const SkImage*,
SkScalar,
SkScalar,
@@ -127,7 +114,10 @@ class InterceptingCanvasBase : public SkCanvas {
const SkMatrix*,
const SkPaint*) override = 0;
void didSetMatrix(const SkMatrix&) override = 0;
+ void didConcat44(const SkScalar[16]) override = 0;
void didConcat(const SkMatrix&) override = 0;
+ void didScale(SkScalar, SkScalar) override = 0;
+ void didTranslate(SkScalar, SkScalar) override = 0;
void willSave() override = 0;
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override = 0;
void willRestore() override = 0;
@@ -187,31 +177,6 @@ class InterceptingCanvas : public InterceptingCanvasBase {
this->SkCanvas::onDrawPath(path, paint);
}
- void onDrawBitmap(const SkBitmap& bitmap,
- SkScalar left,
- SkScalar top,
- const SkPaint* paint) override {
- Interceptor interceptor(this);
- this->SkCanvas::onDrawBitmap(bitmap, left, top, paint);
- }
-
- void onDrawBitmapRect(const SkBitmap& bitmap,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint* paint,
- SrcRectConstraint constraint) override {
- Interceptor interceptor(this);
- this->SkCanvas::onDrawBitmapRect(bitmap, src, dst, paint, constraint);
- }
-
- void onDrawBitmapNine(const SkBitmap& bitmap,
- const SkIRect& center,
- const SkRect& dst,
- const SkPaint* paint) override {
- Interceptor interceptor(this);
- this->SkCanvas::onDrawBitmapNine(bitmap, center, dst, paint);
- }
-
void onDrawImage(const SkImage* image,
SkScalar x,
SkScalar y,
@@ -285,12 +250,22 @@ class InterceptingCanvas : public InterceptingCanvasBase {
void didSetMatrix(const SkMatrix& matrix) override {
Interceptor interceptor(this);
- this->SkCanvas::didSetMatrix(matrix);
+ }
+
+ void didConcat44(const SkScalar m[16]) override {
+ Interceptor interceptor(this);
}
void didConcat(const SkMatrix& matrix) override {
Interceptor interceptor(this);
- this->SkCanvas::didConcat(matrix);
+ }
+
+ void didScale(SkScalar x, SkScalar y) override {
+ Interceptor interceptor(this);
+ }
+
+ void didTranslate(SkScalar x, SkScalar y) override {
+ Interceptor interceptor(this);
}
void willSave() override {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
index b22ea1d9e6d..9fe75a4f661 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -73,15 +73,6 @@ std::unique_ptr<JSONObject> ObjectForSkRect(const SkRect& rect) {
return rect_item;
}
-std::unique_ptr<JSONObject> ObjectForSkIRect(const SkIRect& rect) {
- auto rect_item = std::make_unique<JSONObject>();
- rect_item->SetDouble("left", rect.left());
- rect_item->SetDouble("top", rect.top());
- rect_item->SetDouble("right", rect.right());
- rect_item->SetDouble("bottom", rect.bottom());
- return rect_item;
-}
-
String PointModeName(SkCanvas::PointMode mode) {
switch (mode) {
case SkCanvas::kPoints_PointMode:
@@ -248,57 +239,6 @@ std::unique_ptr<JSONObject> ObjectForSkPath(const SkPath& path) {
return path_item;
}
-String ColorTypeName(SkColorType color_type) {
- switch (color_type) {
- case kUnknown_SkColorType:
- return "None";
- case kAlpha_8_SkColorType:
- return "A8";
- case kRGB_565_SkColorType:
- return "RGB565";
- case kARGB_4444_SkColorType:
- return "ARGB4444";
- case kN32_SkColorType:
- return "ARGB8888";
- default:
- NOTREACHED();
- return "?";
- };
-}
-
-std::unique_ptr<JSONObject> ObjectForBitmapData(const SkBitmap& bitmap) {
- Vector<unsigned char> output;
-
- SkPixmap src;
- bool peekResult = bitmap.peekPixels(&src);
- DCHECK(peekResult);
-
- SkPngEncoder::Options options;
- options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
- options.fZLibLevel = 3;
- if (!ImageEncoder::Encode(&output, src, options)) {
- return nullptr;
- }
-
- auto data_item = std::make_unique<JSONObject>();
- data_item->SetString("base64", Base64Encode(output));
- data_item->SetString("mimeType", "image/png");
- return data_item;
-}
-
-std::unique_ptr<JSONObject> ObjectForSkBitmap(const SkBitmap& bitmap) {
- auto bitmap_item = std::make_unique<JSONObject>();
- bitmap_item->SetInteger("width", bitmap.width());
- bitmap_item->SetInteger("height", bitmap.height());
- bitmap_item->SetString("config", ColorTypeName(bitmap.colorType()));
- bitmap_item->SetBoolean("opaque", bitmap.isOpaque());
- bitmap_item->SetBoolean("immutable", bitmap.isImmutable());
- bitmap_item->SetBoolean("volatile", bitmap.isVolatile());
- bitmap_item->SetInteger("genID", bitmap.getGenerationID());
- bitmap_item->SetObject("data", ObjectForBitmapData(bitmap));
- return bitmap_item;
-}
-
std::unique_ptr<JSONObject> ObjectForSkImage(const SkImage* image) {
auto image_item = std::make_unique<JSONObject>();
image_item->SetInteger("width", image->width());
@@ -315,6 +255,14 @@ std::unique_ptr<JSONArray> ArrayForSkMatrix(const SkMatrix& matrix) {
return matrix_array;
}
+std::unique_ptr<JSONArray> ArrayForSkScalars(size_t count,
+ const SkScalar array[]) {
+ auto points_array_item = std::make_unique<JSONArray>();
+ for (size_t i = 0; i < count; ++i)
+ points_array_item->PushDouble(array[i]);
+ return points_array_item;
+}
+
std::unique_ptr<JSONObject> ObjectForSkShader(const SkShader& shader) {
return std::make_unique<JSONObject>();
}
@@ -520,51 +468,6 @@ void LoggingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
this->SkCanvas::onDrawPath(path, paint);
}
-void LoggingCanvas::onDrawBitmap(const SkBitmap& bitmap,
- SkScalar left,
- SkScalar top,
- const SkPaint* paint) {
- AutoLogger logger(this);
- JSONObject* params = logger.LogItemWithParams("drawBitmap");
- params->SetDouble("left", left);
- params->SetDouble("top", top);
- params->SetObject("bitmap", ObjectForSkBitmap(bitmap));
- if (paint)
- params->SetObject("paint", ObjectForSkPaint(*paint));
- this->SkCanvas::onDrawBitmap(bitmap, left, top, paint);
-}
-
-void LoggingCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint* paint,
- SrcRectConstraint constraint) {
- AutoLogger logger(this);
- JSONObject* params = logger.LogItemWithParams("drawBitmapRectToRect");
- params->SetObject("bitmap", ObjectForSkBitmap(bitmap));
- if (src)
- params->SetObject("src", ObjectForSkRect(*src));
- params->SetObject("dst", ObjectForSkRect(dst));
- if (paint)
- params->SetObject("paint", ObjectForSkPaint(*paint));
- params->SetInteger("flags", constraint);
- this->SkCanvas::onDrawBitmapRect(bitmap, src, dst, paint, constraint);
-}
-
-void LoggingCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
- const SkIRect& center,
- const SkRect& dst,
- const SkPaint* paint) {
- AutoLogger logger(this);
- JSONObject* params = logger.LogItemWithParams("drawBitmapNine");
- params->SetObject("bitmap", ObjectForSkBitmap(bitmap));
- params->SetObject("center", ObjectForSkIRect(center));
- params->SetObject("dst", ObjectForSkRect(dst));
- if (paint)
- params->SetObject("paint", ObjectForSkPaint(*paint));
- this->SkCanvas::onDrawBitmapNine(bitmap, center, dst, paint);
-}
-
void LoggingCanvas::onDrawImage(const SkImage* image,
SkScalar left,
SkScalar top,
@@ -677,7 +580,12 @@ void LoggingCanvas::didSetMatrix(const SkMatrix& matrix) {
AutoLogger logger(this);
JSONObject* params = logger.LogItemWithParams("setMatrix");
params->SetArray("matrix", ArrayForSkMatrix(matrix));
- this->SkCanvas::didSetMatrix(matrix);
+}
+
+void LoggingCanvas::didConcat44(const SkScalar m[16]) {
+ AutoLogger logger(this);
+ JSONObject* params = logger.LogItemWithParams("concat44");
+ params->SetArray("matrix44", ArrayForSkScalars(16, m));
}
void LoggingCanvas::didConcat(const SkMatrix& matrix) {
@@ -701,7 +609,20 @@ void LoggingCanvas::didConcat(const SkMatrix& matrix) {
params = logger.LogItemWithParams("concat");
params->SetArray("matrix", ArrayForSkMatrix(matrix));
}
- this->SkCanvas::didConcat(matrix);
+}
+
+void LoggingCanvas::didScale(SkScalar x, SkScalar y) {
+ AutoLogger logger(this);
+ JSONObject* params = logger.LogItemWithParams("scale");
+ params->SetDouble("scaleX", x);
+ params->SetDouble("scaleY", y);
+}
+
+void LoggingCanvas::didTranslate(SkScalar x, SkScalar y) {
+ AutoLogger logger(this);
+ JSONObject* params = logger.LogItemWithParams("translate");
+ params->SetDouble("dx", x);
+ params->SetDouble("dy", y);
}
void LoggingCanvas::willSave() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h
index 3951bbf51da..82b00979c9f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h
@@ -53,19 +53,6 @@ class LoggingCanvas : public InterceptingCanvasBase {
void onDrawOval(const SkRect&, const SkPaint&) override;
void onDrawRRect(const SkRRect&, const SkPaint&) override;
void onDrawPath(const SkPath&, const SkPaint&) override;
- void onDrawBitmap(const SkBitmap&,
- SkScalar left,
- SkScalar top,
- const SkPaint*) override;
- void onDrawBitmapRect(const SkBitmap&,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint*,
- SrcRectConstraint) override;
- void onDrawBitmapNine(const SkBitmap&,
- const SkIRect& center,
- const SkRect& dst,
- const SkPaint*) override;
void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override;
void onDrawImageRect(const SkImage*,
const SkRect* src,
@@ -91,7 +78,10 @@ class LoggingCanvas : public InterceptingCanvasBase {
const SkMatrix*,
const SkPaint*) override;
void didSetMatrix(const SkMatrix&) override;
+ void didConcat44(const SkScalar[16]) override;
void didConcat(const SkMatrix&) override;
+ void didScale(SkScalar, SkScalar) override;
+ void didTranslate(SkScalar, SkScalar) override;
void willSave() override;
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
void willRestore() override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
deleted file mode 100644
index d0ac4be0f10..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h"
-
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
-#include "third_party/blink/renderer/platform/graphics/skia_texture_holder.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-
-namespace blink {
-
-namespace {
-
-void ReleaseTexture(
- bool is_converted_from_skia_texture,
- unsigned texture_id,
- std::unique_ptr<gpu::Mailbox> mailbox,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
- std::unique_ptr<gpu::SyncToken> sync_token) {
- if (!is_converted_from_skia_texture && texture_id && context_provider) {
- context_provider->ContextProvider()->ContextGL()->WaitSyncTokenCHROMIUM(
- sync_token->GetData());
- context_provider->ContextProvider()->ContextGL()->DeleteTextures(
- 1, &texture_id);
- }
-}
-
-} // namespace
-
-MailboxTextureHolder::MailboxTextureHolder(
- const gpu::Mailbox& mailbox,
- const gpu::SyncToken& sync_token,
- unsigned texture_id_to_delete_after_mailbox_consumed,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper,
- IntSize mailbox_size,
- bool is_origin_top_left)
- : TextureHolder(std::move(context_provider_wrapper),
- base::MakeRefCounted<MailboxRef>(nullptr),
- is_origin_top_left),
- mailbox_(mailbox),
- texture_id_(texture_id_to_delete_after_mailbox_consumed),
- is_converted_from_skia_texture_(false),
- thread_id_(0),
- sk_image_info_(SkImageInfo::MakeN32Premul(mailbox_size.Width(),
- mailbox_size.Height())),
- texture_target_(GL_TEXTURE_2D) {
- mailbox_ref()->set_sync_token(sync_token);
- InitCommon();
-}
-
-MailboxTextureHolder::MailboxTextureHolder(
- const gpu::Mailbox& mailbox,
- const gpu::SyncToken& sync_token,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper,
- scoped_refptr<MailboxRef> mailbox_ref,
- PlatformThreadId context_thread_id,
- const SkImageInfo& sk_image_info,
- GLenum texture_target,
- bool is_origin_top_left)
- : TextureHolder(std::move(context_provider_wrapper),
- std::move(mailbox_ref),
- is_origin_top_left),
- mailbox_(mailbox),
- texture_id_(0),
- is_converted_from_skia_texture_(false),
- thread_id_(context_thread_id),
- sk_image_info_(sk_image_info),
- texture_target_(texture_target) {
- DCHECK(thread_id_);
- DCHECK(!IsCrossThread() || sync_token.verified_flush());
- this->mailbox_ref()->set_sync_token(sync_token);
-}
-
-MailboxTextureHolder::MailboxTextureHolder(
- const SkiaTextureHolder* texture_holder,
- GLenum filter)
- : TextureHolder(texture_holder->ContextProviderWrapper(),
- texture_holder->mailbox_ref(),
- texture_holder->IsOriginTopLeft()),
- texture_id_(0),
- is_converted_from_skia_texture_(true),
- thread_id_(0) {
- sk_sp<SkImage> image = texture_holder->GetSkImage();
- DCHECK(image);
- sk_image_info_ = image->imageInfo();
-
- if (!ContextProviderWrapper())
- return;
-
- if (!ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox_, texture_target_, image, filter))
- return;
-
- InitCommon();
-}
-
-void MailboxTextureHolder::Sync(MailboxSyncMode mode) {
- gpu::SyncToken sync_token = mailbox_ref()->sync_token();
-
- if (IsCrossThread()) {
- // Was originally created on another thread. Should already have a sync
- // token from the original source context, already verified if needed.
- DCHECK(sync_token.HasData());
- DCHECK(mode != kVerifiedSyncToken || sync_token.verified_flush());
- return;
- }
-
- if (!ContextProviderWrapper())
- return;
-
- TRACE_EVENT0("blink", "MailboxTextureHolder::Sync");
-
- gpu::gles2::GLES2Interface* gl =
- ContextProviderWrapper()->ContextProvider()->ContextGL();
-
- if (mode == kOrderingBarrier) {
- if (!did_issue_ordering_barrier_) {
- gl->OrderingBarrierCHROMIUM();
- did_issue_ordering_barrier_ = true;
- }
- return;
- }
-
- if (!sync_token.HasData()) {
- if (mode == kVerifiedSyncToken) {
- gl->GenSyncTokenCHROMIUM(sync_token.GetData());
- } else {
- gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
- }
- mailbox_ref()->set_sync_token(sync_token);
- return;
- }
-
- // At this point we have a pre-existing sync token. We just need to verify
- // it if needed. Providing a verified sync token when unverified is requested
- // is fine.
- if (mode == kVerifiedSyncToken && !sync_token.verified_flush()) {
- int8_t* token_data = sync_token.GetData();
- // TODO(junov): Batch this verification in the case where there are multiple
- // offscreen canvases being committed.
- gl->ShallowFlushCHROMIUM();
- gl->VerifySyncTokensCHROMIUM(&token_data, 1);
- sync_token.SetVerifyFlush();
- mailbox_ref()->set_sync_token(sync_token);
- }
-}
-
-void MailboxTextureHolder::InitCommon() {
- DCHECK(!thread_id_);
- thread_id_ = base::PlatformThread::CurrentId();
- texture_thread_task_runner_ = Thread::Current()->GetTaskRunner();
-}
-
-bool MailboxTextureHolder::IsValid() const {
- if (IsCrossThread()) {
- // If context is is from another thread, validity cannot be verified.
- // Just assume valid. Potential problem will be detected later.
- return true;
- }
- return !!ContextProviderWrapper();
-}
-
-bool MailboxTextureHolder::IsCrossThread() const {
- return thread_id_ != base::PlatformThread::CurrentId();
-}
-
-MailboxTextureHolder::~MailboxTextureHolder() {
- std::unique_ptr<gpu::SyncToken> passed_sync_token(
- new gpu::SyncToken(mailbox_ref()->sync_token()));
- std::unique_ptr<gpu::Mailbox> passed_mailbox(new gpu::Mailbox(mailbox_));
-
- if (texture_thread_task_runner_ && IsCrossThread()) {
- PostCrossThreadTask(
- *texture_thread_task_runner_, FROM_HERE,
- CrossThreadBindOnce(&ReleaseTexture, is_converted_from_skia_texture_,
- texture_id_, WTF::Passed(std::move(passed_mailbox)),
- WTF::Passed(ContextProviderWrapper()),
- WTF::Passed(std::move(passed_sync_token))));
- } else {
- ReleaseTexture(is_converted_from_skia_texture_, texture_id_,
- std::move(passed_mailbox), ContextProviderWrapper(),
- std::move(passed_sync_token));
- }
-
- texture_id_ = 0u; // invalidate the texture.
- texture_thread_task_runner_ = nullptr;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
deleted file mode 100644
index da4d6800f99..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MAILBOX_TEXTURE_HOLDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MAILBOX_TEXTURE_HOLDER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/texture_holder.h"
-#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
-
-namespace blink {
-class SkiaTextureHolder;
-
-class PLATFORM_EXPORT MailboxTextureHolder final : public TextureHolder {
- public:
- ~MailboxTextureHolder() override;
-
- // TextureHolder impl.
- IntSize Size() const final {
- return IntSize(sk_image_info_.width(), sk_image_info_.height());
- }
- bool CurrentFrameKnownToBeOpaque() const final { return false; }
- bool IsValid() const final;
-
- bool IsCrossThread() const;
- const gpu::Mailbox& GetMailbox() const { return mailbox_; }
- const gpu::SyncToken& GetSyncToken() const {
- return mailbox_ref()->sync_token();
- }
- void UpdateSyncToken(gpu::SyncToken sync_token) {
- mailbox_ref()->set_sync_token(sync_token);
- }
- const SkImageInfo& sk_image_info() const { return sk_image_info_; }
- GLenum texture_target() const { return texture_target_; }
-
- void Sync(MailboxSyncMode);
- // In WebGL's commit or transferToImageBitmap calls, it will call the
- // DrawingBuffer::transferToStaticBitmapImage function, which produces the
- // input parameters for this method.
- MailboxTextureHolder(const gpu::Mailbox&,
- const gpu::SyncToken&,
- unsigned texture_id_to_delete_after_mailbox_consumed,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
- IntSize mailbox_size,
- bool is_origin_top_left);
- // This function turns a texture-backed SkImage into a mailbox and a
- // syncToken.
- MailboxTextureHolder(const SkiaTextureHolder*, GLenum filter);
- // This function may be used when the MailboxTextureHolder is created on a
- // different thread. The caller must provide a verified sync token if it is
- // created cross-thread.
- MailboxTextureHolder(const gpu::Mailbox&,
- const gpu::SyncToken&,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
- scoped_refptr<MailboxRef> mailbox_ref,
- PlatformThreadId context_thread_id,
- const SkImageInfo& sk_image_info,
- GLenum texture_target,
- bool is_origin_top_left);
-
- private:
- void InitCommon();
-
- gpu::Mailbox mailbox_;
- unsigned texture_id_;
- bool is_converted_from_skia_texture_;
- scoped_refptr<base::SingleThreadTaskRunner> texture_thread_task_runner_;
- base::PlatformThreadId thread_id_;
- bool did_issue_ordering_barrier_ = false;
- SkImageInfo sk_image_info_;
- GLenum texture_target_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MAILBOX_TEXTURE_HOLDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc
new file mode 100644
index 00000000000..3659a862b3e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h"
+
+namespace blink {
+
+MemoryManagedPaintCanvas::MemoryManagedPaintCanvas(
+ cc::DisplayItemList* list,
+ const SkRect& bounds,
+ base::RepeatingClosure set_needs_flush_callback)
+ : RecordPaintCanvas(list, bounds),
+ set_needs_flush_callback_(std::move(set_needs_flush_callback)) {}
+
+MemoryManagedPaintCanvas::~MemoryManagedPaintCanvas() = default;
+
+void MemoryManagedPaintCanvas::drawImage(const cc::PaintImage& image,
+ SkScalar left,
+ SkScalar top,
+ const cc::PaintFlags* flags) {
+ DCHECK(!image.IsPaintWorklet());
+ RecordPaintCanvas::drawImage(image, left, top, flags);
+ UpdateMemoryUsage(image);
+}
+
+void MemoryManagedPaintCanvas::drawImageRect(
+ const cc::PaintImage& image,
+ const SkRect& src,
+ const SkRect& dst,
+ const cc::PaintFlags* flags,
+ PaintCanvas::SrcRectConstraint constraint) {
+ RecordPaintCanvas::drawImageRect(image, src, dst, flags, constraint);
+ UpdateMemoryUsage(image);
+}
+
+void MemoryManagedPaintCanvas::UpdateMemoryUsage(const cc::PaintImage& image) {
+ if (cached_image_ids_.contains(image.GetContentIdForFrame(0u)))
+ return;
+
+ cached_image_ids_.insert(image.GetContentIdForFrame(0u));
+ total_stored_image_memory_ +=
+ image.GetSkImage()->imageInfo().computeMinByteSize();
+
+ if (total_stored_image_memory_ > kMaxPinnedMemory)
+ set_needs_flush_callback_.Run();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h
new file mode 100644
index 00000000000..444d771f899
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h
@@ -0,0 +1,52 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MEMORY_MANAGED_PAINT_CANVAS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MEMORY_MANAGED_PAINT_CANVAS_H_
+
+#include <memory>
+
+#include "cc/paint/record_paint_canvas.h"
+#include "third_party/blink/public/platform/platform.h"
+
+namespace blink {
+
+// MemoryManagedPaintCanvas overrides the potentially memory intensive image
+// drawing methods of PaintCanvas and keeps track of how much memory is
+// being pinned between flushes. This allows the rendering context to flush if
+// too much memory is used.
+class PLATFORM_EXPORT MemoryManagedPaintCanvas final
+ : public cc::RecordPaintCanvas {
+ public:
+ MemoryManagedPaintCanvas(cc::DisplayItemList* list,
+ const SkRect& bounds,
+ base::RepeatingClosure set_needs_flush_callback);
+ explicit MemoryManagedPaintCanvas(const cc::RecordPaintCanvas&) = delete;
+ ~MemoryManagedPaintCanvas() override;
+
+ void drawImage(const cc::PaintImage& image,
+ SkScalar left,
+ SkScalar top,
+ const cc::PaintFlags* flags) override;
+ void drawImageRect(const cc::PaintImage& image,
+ const SkRect& src,
+ const SkRect& dst,
+ const cc::PaintFlags* flags,
+ SrcRectConstraint constraint) override;
+
+ private:
+ void UpdateMemoryUsage(const cc::PaintImage& image);
+
+ base::flat_set<int> cached_image_ids_;
+ uint64_t total_stored_image_memory_ = 0;
+
+ base::RepeatingClosure set_needs_flush_callback_;
+
+ // The same value as is used in content::WebGraphicsConext3DProviderImpl.
+ static constexpr uint64_t kMaxPinnedMemory = 64 * 1024 * 1024;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MEMORY_MANAGED_PAINT_CANVAS_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.cc b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.cc
new file mode 100644
index 00000000000..1f179973d11
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h"
+
+namespace blink {
+
+MemoryManagedPaintRecorder::MemoryManagedPaintRecorder(
+ base::RepeatingClosure set_needs_flush_callback)
+ : set_needs_flush_callback_(std::move(set_needs_flush_callback)) {}
+
+std::unique_ptr<cc::RecordPaintCanvas> MemoryManagedPaintRecorder::CreateCanvas(
+ cc::DisplayItemList* list,
+ const SkRect& bounds) {
+ return std::make_unique<MemoryManagedPaintCanvas>(list, bounds,
+ set_needs_flush_callback_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h
new file mode 100644
index 00000000000..1450219da57
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MEMORY_MANAGED_PAINT_RECORDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MEMORY_MANAGED_PAINT_RECORDER_H_
+
+#include "cc/paint/paint_recorder.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT MemoryManagedPaintRecorder : public cc::PaintRecorder {
+ public:
+ MemoryManagedPaintRecorder(base::RepeatingClosure set_needs_flush_callback);
+
+ protected:
+ std::unique_ptr<cc::RecordPaintCanvas> CreateCanvas(
+ cc::DisplayItemList* list,
+ const SkRect& bounds) override;
+
+ private:
+ base::RepeatingClosure set_needs_flush_callback_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_MEMORY_MANAGED_PAINT_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/README.md b/chromium/third_party/blink/renderer/platform/graphics/paint/README.md
index 6d367c9d5d3..ea389f5ca03 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/README.md
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/README.md
@@ -156,6 +156,13 @@ emit display items to a `PaintController` (using `GraphicsContext`).
Holds a `PaintRecord` which contains the paint operations required to draw some
atom of content.
+#### [GraphicsLayerDisplayItem](graphics_layer_display_item.h)
+
+Placeholder for `GraphicsLayers` allocated by the pre-CompositeAfterPaint
+compositing logic. Each one of these may or may not ultimately produce a
+`cc::PictureLayer`, depending on the layer squashing mechanism. This class
+becomes obsolete with CompositeAfterPaint.
+
#### [ForeignLayerDisplayItem](foreign_layer_display_item.h)
Draws an atom of content, but using a `cc::Layer` produced by some agent outside
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
index b4094008ba1..79156919709 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
+#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
@@ -32,14 +33,32 @@ class PLATFORM_EXPORT ClipPaintPropertyNode
// To make it less verbose and more readable to construct and update a node,
// a struct with default values is used to represent the state.
struct State {
+ State(scoped_refptr<const TransformPaintPropertyNode> local_transform_space,
+ const FloatRoundedRect& clip_rect)
+ : State(local_transform_space, clip_rect, clip_rect) {}
+
+ State(scoped_refptr<const TransformPaintPropertyNode>
+ local_transform_space_arg,
+ const FloatRoundedRect& clip_rect,
+ const FloatRoundedRect& pixel_snapped_clip_rect)
+ : local_transform_space(local_transform_space_arg) {
+ SetClipRect(clip_rect, pixel_snapped_clip_rect);
+ }
+
scoped_refptr<const TransformPaintPropertyNode> local_transform_space;
- FloatRoundedRect clip_rect;
base::Optional<FloatClipRect> clip_rect_excluding_overlay_scrollbars;
scoped_refptr<const RefCountedPath> clip_path;
+ void SetClipRect(const FloatRoundedRect& clip_rect_arg,
+ const FloatRoundedRect& pixel_snapped_clip_rect_arg) {
+ clip_rect = clip_rect_arg;
+ pixel_snapped_clip_rect = pixel_snapped_clip_rect_arg;
+ }
+
PaintPropertyChangeType ComputeChange(const State& other) const {
if (local_transform_space != other.local_transform_space ||
- clip_rect != other.clip_rect || clip_path != other.clip_path) {
+ pixel_snapped_clip_rect != other.pixel_snapped_clip_rect ||
+ clip_path != other.clip_path) {
return PaintPropertyChangeType::kChangedOnlyValues;
}
if (clip_rect_excluding_overlay_scrollbars !=
@@ -48,6 +67,12 @@ class PLATFORM_EXPORT ClipPaintPropertyNode
}
return PaintPropertyChangeType::kUnchanged;
}
+
+ friend class ClipPaintPropertyNode;
+
+ private:
+ FloatRoundedRect clip_rect;
+ FloatRoundedRect pixel_snapped_clip_rect;
};
// This node is really a sentinel, and does not represent a real clip space.
@@ -109,8 +134,13 @@ class PLATFORM_EXPORT ClipPaintPropertyNode
// a parent alias.
return *Unalias().state_.local_transform_space;
}
- const FloatRoundedRect& ClipRect() const { return state_.clip_rect; }
- const FloatClipRect ClipRectExcludingOverlayScrollbars() const {
+ // The pixel-snapped clip rect may be the same as the unsnapped one, in cases
+ // where pixel snapping is not desirable for a clip, such as for SVG.
+ const FloatRoundedRect& PixelSnappedClipRect() const {
+ return state_.pixel_snapped_clip_rect;
+ }
+ const FloatRoundedRect UnsnappedClipRect() const { return state_.clip_rect; }
+ const FloatClipRect UnsnappedClipRectExcludingOverlayScrollbars() const {
return state_.clip_rect_excluding_overlay_scrollbars
? *state_.clip_rect_excluding_overlay_scrollbars
: FloatClipRect(state_.clip_rect);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
index bb0ae38e08c..83d30acbb8b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -42,7 +42,7 @@ static WTF::String PaintPhaseAsDebugString(int paint_phase) {
case 8:
return "PaintPhaseDescendantOutlinesOnly";
case 9:
- return "PaintPhaseOverlayScrollbars";
+ return "PaintPhaseOverlayOverflowControls";
case 10:
return "PaintPhaseSelection";
case 11:
@@ -78,10 +78,10 @@ static WTF::String SpecialDrawingTypeAsDebugString(DisplayItem::Type type) {
DEBUG_STRING_CASE(ClippingMask);
DEBUG_STRING_CASE(ColumnRules);
DEBUG_STRING_CASE(DebugDrawing);
+ DEBUG_STRING_CASE(DocumentRootBackdrop);
DEBUG_STRING_CASE(DocumentBackground);
DEBUG_STRING_CASE(DragImage);
DEBUG_STRING_CASE(DragCaret);
- DEBUG_STRING_CASE(EmptyContentForFilters);
DEBUG_STRING_CASE(ForcedColorsModeBackplate);
DEBUG_STRING_CASE(SVGImage);
DEBUG_STRING_CASE(LinkHighlight);
@@ -123,7 +123,7 @@ static String ForeignLayerTypeAsDebugString(DisplayItem::Type type) {
DEBUG_STRING_CASE(ForeignLayerDevToolsOverlay);
DEBUG_STRING_CASE(ForeignLayerPlugin);
DEBUG_STRING_CASE(ForeignLayerVideo);
- DEBUG_STRING_CASE(ForeignLayerWrapper);
+ DEBUG_STRING_CASE(ForeignLayerRemoteFrame);
DEBUG_STRING_CASE(ForeignLayerContentsWrapper);
DEBUG_STRING_CASE(ForeignLayerLinkHighlight);
DEBUG_STRING_CASE(ForeignLayerViewportScroll);
@@ -132,6 +132,13 @@ static String ForeignLayerTypeAsDebugString(DisplayItem::Type type) {
}
}
+static String GraphicsLayerWrapperTypeAsDebugString(DisplayItem::Type type) {
+ switch (type) {
+ DEBUG_STRING_CASE(GraphicsLayerWrapper);
+ DEFAULT_CASE;
+ }
+}
+
WTF::String DisplayItem::TypeAsDebugString(Type type) {
if (IsDrawingType(type))
return DrawingTypeAsDebugString(type);
@@ -139,6 +146,9 @@ WTF::String DisplayItem::TypeAsDebugString(Type type) {
if (IsForeignLayerType(type))
return ForeignLayerTypeAsDebugString(type);
+ if (IsGraphicsLayerWrapperType(type))
+ return GraphicsLayerWrapperTypeAsDebugString(type);
+
PAINT_PHASE_BASED_DEBUG_STRINGS(Clip);
PAINT_PHASE_BASED_DEBUG_STRINGS(Scroll);
PAINT_PHASE_BASED_DEBUG_STRINGS(SVGTransform);
@@ -149,12 +159,8 @@ WTF::String DisplayItem::TypeAsDebugString(Type type) {
DEBUG_STRING_CASE(ScrollHitTest);
DEBUG_STRING_CASE(ResizerScrollHitTest);
DEBUG_STRING_CASE(PluginScrollHitTest);
- DEBUG_STRING_CASE(LayerChunkBackground);
- DEBUG_STRING_CASE(LayerChunkNegativeZOrderChildren);
- DEBUG_STRING_CASE(LayerChunkDescendantBackgrounds);
- DEBUG_STRING_CASE(LayerChunkFloat);
+ DEBUG_STRING_CASE(LayerChunk);
DEBUG_STRING_CASE(LayerChunkForeground);
- DEBUG_STRING_CASE(LayerChunkNormalFlowAndPositiveZOrderChildren);
DEBUG_STRING_CASE(ScrollbarHorizontal);
DEBUG_STRING_CASE(ScrollbarVertical);
DEBUG_STRING_CASE(UninitializedType);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
index 320f0d0bee5..6d9a09eff7e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -61,10 +61,10 @@ class PLATFORM_EXPORT DisplayItem {
kClippingMask,
kColumnRules,
kDebugDrawing,
+ kDocumentRootBackdrop,
kDocumentBackground,
kDragImage,
kDragCaret,
- kEmptyContentForFilters,
kForcedColorsModeBackplate,
kSVGImage,
kLinkHighlight,
@@ -100,13 +100,17 @@ class PLATFORM_EXPORT DisplayItem {
kForeignLayerDevToolsOverlay,
kForeignLayerPlugin,
kForeignLayerVideo,
- kForeignLayerWrapper,
+ kForeignLayerRemoteFrame,
kForeignLayerContentsWrapper,
kForeignLayerLinkHighlight,
kForeignLayerViewportScroll,
kForeignLayerViewportScrollbar,
kForeignLayerLast = kForeignLayerViewportScrollbar,
+ kGraphicsLayerWrapperFirst,
+ kGraphicsLayerWrapper = kGraphicsLayerWrapperFirst,
+ kGraphicsLayerWrapperLast = kGraphicsLayerWrapper,
+
kClipPaintPhaseFirst,
kClipPaintPhaseLast = kClipPaintPhaseFirst + kPaintPhaseMax,
@@ -119,26 +123,29 @@ class PLATFORM_EXPORT DisplayItem {
kSVGEffectPaintPhaseFirst,
kSVGEffectPaintPhaseLast = kSVGEffectPaintPhaseFirst + kPaintPhaseMax,
+ // The following hit test types are for paint chunks containing hit test
+ // data, when we don't have an previously set explicit chunk id when
+ // creating the paint chunk, or we need dedicated paint chunk for the hit
+ // test data.
+
// Compositor hit testing requires that layers are created and sized to
- // include content that does not paint. Hit test display items ensure
- // a layer exists and is sized properly even if no content would otherwise
- // be painted.
+ // include content that does not paint. Hit test data ensure a layer exists
+ // and is sized properly even if no content would otherwise be painted.
kHitTest,
// Used both for specifying the paint-order scroll location, and for non-
- // composited scroll hit testing (see: scroll_hit_test_display_item.h).
+ // composited scroll hit testing (see: hit_test_data.h).
kScrollHitTest,
// Used to prevent composited scrolling on the resize handle.
kResizerScrollHitTest,
// Used to prevent composited scrolling on plugins with wheel handlers.
kPluginScrollHitTest,
- kLayerChunkBackground,
- kLayerChunkNegativeZOrderChildren,
- kLayerChunkDescendantBackgrounds,
- kLayerChunkFloat,
+ // These are for paint chunks that are forced for layers.
+ kLayerChunk,
+ // This is used if a layer has any negative-z-index children. Otherwise the
+ // foreground is in the kLayerChunk chunk.
kLayerChunkForeground,
- kLayerChunkNormalFlowAndPositiveZOrderChildren,
// The following 2 types are For ScrollbarDisplayItem.
kScrollbarHorizontal,
@@ -152,7 +159,7 @@ class PLATFORM_EXPORT DisplayItem {
// later paint cycles when |client| may have been destroyed.
DisplayItem(const DisplayItemClient& client,
Type type,
- size_t derived_size,
+ wtf_size_t derived_size,
bool draws_content = false)
: client_(&client),
visual_rect_(client.VisualRect()),
@@ -161,10 +168,11 @@ class PLATFORM_EXPORT DisplayItem {
draws_content_(draws_content),
fragment_(0),
is_cacheable_(client.IsCacheable()),
- is_tombstone_(false) {
+ is_tombstone_(false),
+ is_moved_from_cached_subsequence_(false) {
// |derived_size| must fit in |derived_size_|.
// If it doesn't, enlarge |derived_size_| and fix this assert.
- SECURITY_DCHECK(derived_size < (1 << 8));
+ SECURITY_DCHECK(derived_size < (1 << 7));
SECURITY_DCHECK(derived_size >= sizeof(*this));
derived_size_ = static_cast<unsigned>(derived_size);
}
@@ -211,7 +219,7 @@ class PLATFORM_EXPORT DisplayItem {
// This is not sizeof(*this), because it needs to account for the size of
// the derived class (i.e. runtime type). Derived classes are expected to
// supply this to the DisplayItem constructor.
- size_t DerivedSize() const { return derived_size_; }
+ wtf_size_t DerivedSize() const { return derived_size_; }
// The fragment is part of the id, to uniquely identify display items in
// different fragments for the same client and type.
@@ -221,6 +229,8 @@ class PLATFORM_EXPORT DisplayItem {
fragment_ = fragment;
}
+ void SetVisualRectForTesting(const IntRect& r) { visual_rect_ = r; }
+
// See comments of enum Type for usage of the following macros.
#define DEFINE_CATEGORY_METHODS(Category) \
static constexpr bool Is##Category##Type(Type type) { \
@@ -243,20 +253,13 @@ class PLATFORM_EXPORT DisplayItem {
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Drawing)
DEFINE_CATEGORY_METHODS(ForeignLayer)
+ DEFINE_CATEGORY_METHODS(GraphicsLayerWrapper)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Clip)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Scroll)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGTransform)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGEffect)
- bool IsHitTest() const { return type_ == kHitTest; }
- bool IsScrollHitTest() const {
- return type_ == kScrollHitTest || IsResizerScrollHitTest() ||
- IsPluginScrollHitTest();
- }
- bool IsResizerScrollHitTest() const { return type_ == kResizerScrollHitTest; }
- bool IsPluginScrollHitTest() const { return type_ == kPluginScrollHitTest; }
-
bool IsScrollbar() const {
return type_ == kScrollbarHorizontal || type_ == kScrollbarVertical;
}
@@ -264,6 +267,13 @@ class PLATFORM_EXPORT DisplayItem {
bool IsCacheable() const { return is_cacheable_; }
void SetUncacheable() { is_cacheable_ = false; }
+ bool IsMovedFromCachedSubsequence() const {
+ return is_moved_from_cached_subsequence_;
+ }
+ void SetMovedFromCachedSubsequence(bool b) {
+ is_moved_from_cached_subsequence_ = b;
+ }
+
virtual bool Equals(const DisplayItem& other) const {
// Failure of this DCHECK would cause bad casts in subclasses.
SECURITY_CHECK(!is_tombstone_);
@@ -304,10 +314,11 @@ class PLATFORM_EXPORT DisplayItem {
static_assert(kTypeLast < (1 << 7), "DisplayItem::Type should fit in 7 bits");
unsigned type_ : 7;
unsigned draws_content_ : 1;
- unsigned derived_size_ : 8; // size of the actual derived class
+ unsigned derived_size_ : 7; // size of the actual derived class
unsigned fragment_ : 14;
unsigned is_cacheable_ : 1;
unsigned is_tombstone_ : 1;
+ unsigned is_moved_from_cached_subsequence_ : 1;
};
inline bool operator==(const DisplayItem::Id& a, const DisplayItem::Id& b) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h
index 5ded583d929..d702c6c758f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h
@@ -13,10 +13,11 @@
namespace blink {
class DisplayItemCacheSkipper final {
- DISALLOW_NEW();
+ STACK_ALLOCATED();
public:
- DisplayItemCacheSkipper(GraphicsContext& context) : context_(context) {
+ explicit DisplayItemCacheSkipper(GraphicsContext& context)
+ : context_(context) {
context.GetPaintController().BeginSkippingCache();
}
~DisplayItemCacheSkipper() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
index d29f0ecee1f..6e108747031 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
@@ -66,20 +66,6 @@ class PLATFORM_EXPORT DisplayItemClient {
// Called by PaintController::FinishCycle() for all clients after painting.
virtual void ClearPartialInvalidationVisualRect() const {}
- // This is declared here instead of in LayoutObject for verifying the
- // condition in DrawingRecorder.
- // Returns true if the object itself will not generate any effective painted
- // output no matter what size the object is. For example, this function can
- // return false for an object whose size is currently 0x0 but would have
- // effective painted output if it was set a non-empty size. It's used to skip
- // unforced paint invalidation of LayoutObjects (which is when
- // shouldDoFullPaintInvalidation is false, but mayNeedPaintInvalidation or
- // childShouldCheckForPaintInvalidation is true) to avoid unnecessary paint
- // invalidations of empty areas covered by such objects.
- virtual bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
- return false;
- }
-
// Indicates that the client will paint display items different from the ones
// cached by PaintController. However, PaintController allows a client to
// paint new display items that are not cached or to no longer paint some
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
index bb15ec6a712..d2f05789294 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
@@ -24,17 +24,17 @@ DisplayItemList::ItemsInPaintChunk(const PaintChunk& paint_chunk) const {
#if DCHECK_IS_ON()
-std::unique_ptr<JSONArray> DisplayItemList::SubsequenceAsJSON(
- size_t begin_index,
- size_t end_index,
+std::unique_ptr<JSONArray> DisplayItemList::DisplayItemsAsJSON(
+ wtf_size_t begin_index,
+ wtf_size_t end_index,
JsonFlags flags) const {
auto json_array = std::make_unique<JSONArray>();
AppendSubsequenceAsJSON(begin_index, end_index, flags, *json_array);
return json_array;
}
-void DisplayItemList::AppendSubsequenceAsJSON(size_t begin_index,
- size_t end_index,
+void DisplayItemList::AppendSubsequenceAsJSON(wtf_size_t begin_index,
+ wtf_size_t end_index,
JsonFlags flags,
JSONArray& json_array) const {
if (flags & kCompact) {
@@ -42,12 +42,12 @@ void DisplayItemList::AppendSubsequenceAsJSON(size_t begin_index,
<< "kCompact cannot show paint records";
DCHECK(!(flags & kShowOnlyDisplayItemTypes))
<< "kCompact cannot show display item types";
- for (size_t i = begin_index; i < end_index; ++i) {
+ for (auto i = begin_index; i < end_index; ++i) {
const auto& item = (*this)[i];
json_array.PushString(item.GetId().ToString());
}
} else {
- for (size_t i = begin_index; i < end_index; ++i) {
+ for (auto i = begin_index; i < end_index; ++i) {
auto json = std::make_unique<JSONObject>();
const auto& item = (*this)[i];
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
index d1f45b6e0d9..78b664c7902 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
@@ -19,14 +19,16 @@ struct PaintChunk;
// each derived display item; the ideal value is the least common multiple.
// The validity of kDisplayItemAlignment and kMaximumDisplayItemSize are checked
// in PaintController::CreateAndAppend().
-static const size_t kDisplayItemAlignment = alignof(ScrollbarDisplayItem);
-static const size_t kMaximumDisplayItemSize = sizeof(ScrollbarDisplayItem);
+static constexpr wtf_size_t kDisplayItemAlignment =
+ alignof(ScrollbarDisplayItem);
+static constexpr wtf_size_t kMaximumDisplayItemSize =
+ sizeof(ScrollbarDisplayItem);
// A container for a list of display items.
class PLATFORM_EXPORT DisplayItemList
: public ContiguousContainer<DisplayItem, kDisplayItemAlignment> {
public:
- DisplayItemList(size_t initial_size_bytes)
+ DisplayItemList(wtf_size_t initial_size_bytes)
: ContiguousContainer(kMaximumDisplayItemSize, initial_size_bytes) {}
DisplayItemList(DisplayItemList&& source)
: ContiguousContainer(std::move(source)) {}
@@ -42,7 +44,8 @@ class PLATFORM_EXPORT DisplayItemList
ContiguousContainer::AppendByMoving(item, item.DerivedSize());
// ContiguousContainer::AppendByMoving() calls an in-place constructor
// on item which replaces it with a tombstone/"dead display item" that
- // can be safely destructed but should never be used except for debugging.
+ // can be safely destructed but should never be used except for debugging
+ // and raster invalidation (see below).
DCHECK(item.IsTombstone());
// We need |visual_rect_| and |outset_for_raster_effects_| of the old
// display item for raster invalidation. Also, the fields that make up the
@@ -56,6 +59,7 @@ class PLATFORM_EXPORT DisplayItemList
DCHECK(item.GetId() == result.GetId());
item.visual_rect_ = result.visual_rect_;
item.outset_for_raster_effects_ = result.outset_for_raster_effects_;
+ result.SetMovedFromCachedSubsequence(false);
return result;
}
@@ -87,11 +91,11 @@ class PLATFORM_EXPORT DisplayItemList
};
typedef unsigned JsonFlags;
- std::unique_ptr<JSONArray> SubsequenceAsJSON(size_t begin_index,
- size_t end_index,
- JsonFlags) const;
- void AppendSubsequenceAsJSON(size_t begin_index,
- size_t end_index,
+ std::unique_ptr<JSONArray> DisplayItemsAsJSON(wtf_size_t begin_index,
+ wtf_size_t end_index,
+ JsonFlags) const;
+ void AppendSubsequenceAsJSON(wtf_size_t begin_index,
+ wtf_size_t end_index,
JsonFlags,
JSONArray&) const;
#endif // DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
index 2d2433bf88a..4cba6b8b266 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
@@ -22,12 +22,12 @@ void DisplayItemRasterInvalidator::Generate() {
Vector<bool> old_display_items_matched;
old_display_items_matched.resize(old_chunk_.size());
- size_t next_old_item_to_match = old_chunk_.begin_index;
- size_t max_cached_old_index = next_old_item_to_match;
+ auto next_old_item_to_match = old_chunk_.begin_index;
+ auto max_cached_old_index = next_old_item_to_match;
for (const auto& new_item :
new_paint_artifact_.GetDisplayItemList().ItemsInPaintChunk(new_chunk_)) {
- size_t matched_old_index =
+ auto matched_old_index =
MatchNewDisplayItemInOldChunk(new_item, next_old_item_to_match);
if (matched_old_index == kNotFound) {
if (new_item.DrawsContent()) {
@@ -69,7 +69,7 @@ void DisplayItemRasterInvalidator::Generate() {
value.reason = reason;
}
- size_t offset = matched_old_index - old_chunk_.begin_index;
+ wtf_size_t offset = matched_old_index - old_chunk_.begin_index;
DCHECK(!old_display_items_matched[offset]);
old_display_items_matched[offset] = true;
@@ -80,7 +80,7 @@ void DisplayItemRasterInvalidator::Generate() {
}
// Invalidate remaining unmatched (disappeared or uncacheable) old items.
- for (size_t i = old_chunk_.begin_index; i < old_chunk_.end_index; ++i) {
+ for (auto i = old_chunk_.begin_index; i < old_chunk_.end_index; ++i) {
if (old_display_items_matched[i - old_chunk_.begin_index])
continue;
@@ -97,9 +97,9 @@ void DisplayItemRasterInvalidator::Generate() {
}
}
-size_t DisplayItemRasterInvalidator::MatchNewDisplayItemInOldChunk(
+wtf_size_t DisplayItemRasterInvalidator::MatchNewDisplayItemInOldChunk(
const DisplayItem& new_item,
- size_t& next_old_item_to_match) {
+ wtf_size_t& next_old_item_to_match) {
if (!new_item.IsCacheable())
return kNotFound;
for (; next_old_item_to_match < old_chunk_.end_index;
@@ -111,7 +111,7 @@ size_t DisplayItemRasterInvalidator::MatchNewDisplayItemInOldChunk(
if (old_item.GetId() == new_item.GetId())
return next_old_item_to_match++;
// Add the skipped old item into index.
- old_display_items_index_.insert(&old_item.Client(), Vector<size_t>())
+ old_display_items_index_.insert(&old_item.Client(), Vector<wtf_size_t>())
.stored_value->value.push_back(next_old_item_to_match);
}
@@ -119,7 +119,7 @@ size_t DisplayItemRasterInvalidator::MatchNewDisplayItemInOldChunk(
auto it = old_display_items_index_.find(&new_item.Client());
if (it == old_display_items_index_.end())
return kNotFound;
- for (size_t i : it->value) {
+ for (auto i : it->value) {
const auto& old_item = old_paint_artifact_.GetDisplayItemList()[i];
if (old_item.GetId() == new_item.GetId())
return i;
@@ -136,7 +136,8 @@ void DisplayItemRasterInvalidator::AddRasterInvalidation(
if (r.IsEmpty())
return;
- invalidator_.AddRasterInvalidation(r, client, reason, old_or_new);
+ invalidator_.AddRasterInvalidation(raster_invalidation_function_, r, client,
+ reason, old_or_new);
}
void DisplayItemRasterInvalidator::GenerateRasterInvalidation(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h
index b37e15998eb..10828508e58 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h
@@ -15,13 +15,16 @@ class DisplayItemRasterInvalidator {
STACK_ALLOCATED();
public:
- DisplayItemRasterInvalidator(RasterInvalidator& invalidator,
- const PaintArtifact& old_paint_artifact,
- const PaintArtifact& new_paint_artifact,
- const PaintChunk& old_chunk,
- const PaintChunk& new_chunk,
- const ChunkToLayerMapper& mapper)
+ DisplayItemRasterInvalidator(
+ RasterInvalidator& invalidator,
+ RasterInvalidator::RasterInvalidationFunction function,
+ const PaintArtifact& old_paint_artifact,
+ const PaintArtifact& new_paint_artifact,
+ const PaintChunk& old_chunk,
+ const PaintChunk& new_chunk,
+ const ChunkToLayerMapper& mapper)
: invalidator_(invalidator),
+ raster_invalidation_function_(function),
old_paint_artifact_(old_paint_artifact),
new_paint_artifact_(new_paint_artifact),
old_chunk_(old_chunk),
@@ -40,9 +43,9 @@ class DisplayItemRasterInvalidator {
const IntRect&,
PaintInvalidationReason,
RasterInvalidator::ClientIsOldOrNew);
- ALWAYS_INLINE size_t
+ ALWAYS_INLINE wtf_size_t
MatchNewDisplayItemInOldChunk(const DisplayItem& new_item,
- size_t& next_old_item_to_match);
+ wtf_size_t& next_old_item_to_match);
ALWAYS_INLINE void GenerateRasterInvalidation(const DisplayItemClient&,
const IntRect* old_visual_rect,
const IntRect* new_visual_rect,
@@ -58,13 +61,15 @@ class DisplayItemRasterInvalidator {
PaintInvalidationReason reason);
RasterInvalidator& invalidator_;
+ RasterInvalidator::RasterInvalidationFunction raster_invalidation_function_;
const PaintArtifact& old_paint_artifact_;
const PaintArtifact& new_paint_artifact_;
const PaintChunk& old_chunk_;
const PaintChunk& new_chunk_;
const ChunkToLayerMapper& mapper_;
// Maps clients to indices of display items in old_chunk_.
- HashMap<const DisplayItemClient*, Vector<size_t>> old_display_items_index_;
+ HashMap<const DisplayItemClient*, Vector<wtf_size_t>>
+ old_display_items_index_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
index f3d5ff7a79f..b0eee71af71 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
@@ -19,12 +19,12 @@ using ::testing::UnorderedElementsAre;
class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase,
public PaintTestConfigurations {
protected:
- DisplayItemRasterInvalidatorTest() : invalidator_(base::DoNothing()) {}
+ DisplayItemRasterInvalidatorTest() = default;
Vector<RasterInvalidationInfo> GenerateRasterInvalidations() {
GetPaintController().CommitNewDisplayItems();
invalidator_.Generate(
- GetPaintController().GetPaintArtifactShared(),
+ base::DoNothing(), GetPaintController().GetPaintArtifactShared(),
// The layer rect is big enough not to clip display item raster
// invalidation rects.
IntRect(0, 0, 20000, 20000), PropertyTreeState::Root());
@@ -461,25 +461,27 @@ TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderCrossingChunks) {
auto container2_properties = DefaultPaintChunkProperties();
container2_properties.SetEffect(*container2_effect);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kBackgroundType), container1_properties);
+ PaintChunk::Id container1_id(container1, kBackgroundType);
+ PaintChunk::Id container2_id(container2, kBackgroundType);
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
+ container1_properties);
DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container2, kBackgroundType), container2_properties);
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
+ container2_properties);
DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
GenerateRasterInvalidations();
// Move content2 into container1, without invalidation.
invalidator_.SetTracksRasterInvalidations(true);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kBackgroundType), container1_properties);
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
+ container1_properties);
DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container2, kBackgroundType), container2_properties);
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
+ container2_properties);
DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
EXPECT_THAT(GenerateRasterInvalidations(),
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
index 0ab4e34249c..5e150bb70f9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
@@ -11,14 +11,9 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkData.h"
-namespace blink {
+#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
-#if DCHECK_IS_ON()
-void DrawingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetBoolean("opaque", known_to_be_opaque_);
-}
-#endif
+namespace blink {
static SkBitmap RecordToBitmap(sk_sp<const PaintRecord> record,
const IntRect& bounds) {
@@ -83,4 +78,114 @@ bool DrawingDisplayItem::Equals(const DisplayItem& other) const {
return BitmapsEqual(std::move(record), std::move(other_record), bounds);
}
+SkColor DrawingDisplayItem::BackgroundColor() const {
+ if (GetType() != DisplayItem::kBoxDecorationBackground &&
+ GetType() != DisplayItem::kDocumentBackground)
+ return SK_ColorTRANSPARENT;
+
+ if (!record_)
+ return SK_ColorTRANSPARENT;
+
+ for (cc::PaintOpBuffer::Iterator it(record_.get()); it; ++it) {
+ const auto* op = *it;
+ if (op->GetType() == cc::PaintOpType::DrawRect ||
+ op->GetType() == cc::PaintOpType::DrawRRect) {
+ const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
+ // Skip op with looper or shader which may modify the color.
+ if (!flags.getLooper() && !flags.getShader() &&
+ flags.getStyle() == cc::PaintFlags::kFill_Style)
+ return flags.getColor();
+ }
+ }
+ return SK_ColorTRANSPARENT;
+}
+
+// This is not a PaintRecord method because it's not a general opaqueness
+// detection algorithm (which might be more complex and slower), but works well
+// and fast for most blink painted results.
+bool DrawingDisplayItem::CalculateKnownToBeOpaque(
+ const PaintRecord* record) const {
+ if (!record)
+ return false;
+
+ // This limit keeps the algorithm fast, while allowing check of enough paint
+ // operations for most blink painted results.
+ constexpr wtf_size_t kOpCountLimit = 4;
+ wtf_size_t op_count = 0;
+ for (cc::PaintOpBuffer::Iterator it(record); it; ++it) {
+ if (++op_count > kOpCountLimit)
+ return false;
+
+ const auto* op = *it;
+ // Deal with the common pattern of clipped bleed avoiding images like:
+ // Save, ClipRect, Draw..., Restore.
+ if (op->GetType() == cc::PaintOpType::Save)
+ continue;
+ if (op->GetType() == cc::PaintOpType::ClipRect) {
+ const auto* clip_rect_op = static_cast<const cc::ClipRectOp*>(op);
+ if (!EnclosedIntRect(clip_rect_op->rect).Contains(VisualRect()))
+ return false;
+ continue;
+ }
+
+ if (!op->IsDrawOp())
+ return false;
+
+ if (op->GetType() == cc::PaintOpType::DrawRecord) {
+ return CalculateKnownToBeOpaque(
+ static_cast<const cc::DrawRecordOp*>(op)->record.get());
+ }
+
+ if (!op->IsPaintOpWithFlags())
+ continue;
+
+ const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
+ if (flags.getStyle() != cc::PaintFlags::kFill_Style || flags.getLooper() ||
+ (flags.getBlendMode() != SkBlendMode::kSrc &&
+ flags.getBlendMode() != SkBlendMode::kSrcOver) ||
+ flags.getMaskFilter() || flags.getColorFilter() ||
+ flags.getImageFilter() || flags.getAlpha() != SK_AlphaOPAQUE ||
+ (flags.getShader() && !flags.getShader()->IsOpaque()))
+ continue;
+
+ IntRect opaque_rect;
+ switch (op->GetType()) {
+ case cc::PaintOpType::DrawRect:
+ opaque_rect =
+ EnclosedIntRect(static_cast<const cc::DrawRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawIRect:
+ opaque_rect = IntRect(static_cast<const cc::DrawIRectOp*>(op)->rect);
+ break;
+ case cc::PaintOpType::DrawImage: {
+ const auto* draw_image_op = static_cast<const cc::DrawImageOp*>(op);
+ const auto& image = draw_image_op->image;
+ if (!image.IsOpaque())
+ continue;
+ opaque_rect = IntRect(draw_image_op->left, draw_image_op->top,
+ image.width(), image.height());
+ break;
+ }
+ case cc::PaintOpType::DrawImageRect: {
+ const auto* draw_image_rect_op =
+ static_cast<const cc::DrawImageRectOp*>(op);
+ const auto& image = draw_image_rect_op->image;
+ DCHECK(SkRect::MakeWH(image.width(), image.height())
+ .contains(draw_image_rect_op->src));
+ if (!image.IsOpaque())
+ continue;
+ opaque_rect = EnclosedIntRect(draw_image_rect_op->dst);
+ break;
+ }
+ default:
+ continue;
+ }
+
+ // We should never paint outside of the visual rect.
+ if (opaque_rect.Contains(VisualRect()))
+ return true;
+ }
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
index 9f3c691c5ff..a6fa2cd2fa4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
@@ -25,46 +25,45 @@ namespace blink {
// PaintRecord, and is in the space of the DisplayItemList. This allows the
// visual_rect to be compared between DrawingDisplayItems, and to give bounds
// around what the user can actually see from the PaintRecord.
-class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem {
+class PLATFORM_EXPORT DrawingDisplayItem : public DisplayItem {
public:
DISABLE_CFI_PERF
DrawingDisplayItem(const DisplayItemClient& client,
Type type,
- sk_sp<const PaintRecord> record,
- bool known_to_be_opaque = false);
+ sk_sp<const PaintRecord> record);
const sk_sp<const PaintRecord>& GetPaintRecord() const { return record_; }
+ bool Equals(const DisplayItem& other) const final;
+
bool KnownToBeOpaque() const {
- DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- return known_to_be_opaque_;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return false;
+ if (!known_to_be_opaque_.has_value())
+ known_to_be_opaque_.emplace(CalculateKnownToBeOpaque(record_.get()));
+ return *known_to_be_opaque_;
}
+ void SetKnownToBeOpaqueForTesting() { known_to_be_opaque_.emplace(true); }
- bool Equals(const DisplayItem& other) const final;
+ SkColor BackgroundColor() const;
private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const final;
-#endif
+ bool CalculateKnownToBeOpaque(const PaintRecord*) const;
sk_sp<const PaintRecord> record_;
-
- // True if there are no transparent areas. Only used for CompositeAfterPaint.
- const bool known_to_be_opaque_;
+ mutable base::Optional<bool> known_to_be_opaque_;
};
// TODO(dcheng): Move this ctor back inline once the clang plugin is fixed.
DISABLE_CFI_PERF
inline DrawingDisplayItem::DrawingDisplayItem(const DisplayItemClient& client,
Type type,
- sk_sp<const PaintRecord> record,
- bool known_to_be_opaque)
+ sk_sp<const PaintRecord> record)
: DisplayItem(client,
type,
sizeof(*this),
/* draws_content*/ record && record->size()),
- record_(DrawsContent() ? std::move(record) : nullptr),
- known_to_be_opaque_(known_to_be_opaque) {
+ record_(DrawsContent() ? std::move(record) : nullptr) {
DCHECK(IsDrawingType(type));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
index ccf85e0d22f..837a65d6dc8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
@@ -23,31 +23,36 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context,
DisplayItem::Type display_item_type)
: context_(context),
client_(display_item_client),
- type_(display_item_type),
- known_to_be_opaque_(false)
+ type_(display_item_type)
#if DCHECK_IS_ON()
,
initial_display_item_list_size_(
context_.GetPaintController().NewDisplayItemList().size())
#endif
{
- if (context.GetPaintController().DisplayItemConstructionIsDisabled())
- return;
-
// Must check DrawingRecorder::UseCachedDrawingIfPossible before creating the
// DrawingRecorder.
DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
+ context_.GetPaintController().ShouldForcePaintForBenchmark() ||
!UseCachedDrawingIfPossible(context_, client_, type_));
DCHECK(DisplayItem::IsDrawingType(display_item_type));
context.SetInDrawingRecorder(true);
context.BeginRecording(FloatRect());
+
+ if (context.Printing()) {
+ DOMNodeId dom_node_id = display_item_client.OwnerNodeId();
+ if (dom_node_id != kInvalidDOMNodeId) {
+ dom_node_id_to_restore_ = context.GetDOMNodeId();
+ context.SetDOMNodeId(dom_node_id);
+ }
+ }
}
DrawingRecorder::~DrawingRecorder() {
- if (context_.GetPaintController().DisplayItemConstructionIsDisabled())
- return;
+ if (context_.Printing() && dom_node_id_to_restore_)
+ context_.SetDOMNodeId(dom_node_id_to_restore_.value());
context_.SetInDrawingRecorder(false);
@@ -58,20 +63,8 @@ DrawingRecorder::~DrawingRecorder() {
}
#endif
- sk_sp<const PaintRecord> picture = context_.EndRecording();
-
-#if DCHECK_IS_ON()
- // When skipping cache (e.g. in PaintRecordBuilder with a temporary
- // PaintController), the client's painting might be different from its normal
- // painting.
- if (!context_.GetPaintController().IsSkippingCache() &&
- client_.PaintedOutputOfObjectHasNoEffectRegardlessOfSize()) {
- DCHECK_EQ(0u, picture->size()) << client_.DebugName();
- }
-#endif
-
context_.GetPaintController().CreateAndAppend<DrawingDisplayItem>(
- client_, type_, std::move(picture), known_to_be_opaque_);
+ client_, type_, context_.EndRecording());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
index 3c97d2c2445..3437f8d6ed6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
@@ -21,7 +21,7 @@ namespace blink {
class GraphicsContext;
class PLATFORM_EXPORT DrawingRecorder final {
- DISALLOW_NEW();
+ STACK_ALLOCATED();
public:
static bool UseCachedDrawingIfPossible(GraphicsContext& context,
@@ -50,22 +50,15 @@ class PLATFORM_EXPORT DrawingRecorder final {
~DrawingRecorder();
- void SetKnownToBeOpaque() {
- DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- known_to_be_opaque_ = true;
- }
-
private:
GraphicsContext& context_;
const DisplayItemClient& client_;
const DisplayItem::Type type_;
-
- // True if there are no transparent areas. Only used for CompositeAfterPaint.
- bool known_to_be_opaque_;
+ base::Optional<DOMNodeId> dom_node_id_to_restore_;
#if DCHECK_IS_ON()
// Ensures the list size does not change during the recorder's scope.
- size_t initial_display_item_list_size_;
+ wtf_size_t initial_display_item_list_size_;
#endif
DISALLOW_COPY_AND_ASSIGN(DrawingRecorder);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
index 480ff218deb..9c039137fd9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
@@ -249,6 +249,13 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
// CompositingReason::kActiveBackdropFilterAnimation;
}
+ // Whether the effect node uses the backdrop as an input. This includes
+ // exotic blending modes and backdrop filters.
+ bool HasBackdropEffect() const {
+ return BlendMode() != SkBlendMode::kSrcOver ||
+ !BackdropFilter().IsEmpty() || HasActiveBackdropFilterAnimation();
+ }
+
CompositingReasons DirectCompositingReasonsForDebugging() const {
return DirectCompositingReasons();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h
index c11b72e0597..d25a8428606 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h
@@ -132,6 +132,16 @@ inline bool operator!=(const FloatClipRect& a, const FloatClipRect& b) {
return !(a == b);
}
+// The difference between FloatClipRect() (infinite by default) and
+// InfiniteLooseFloatClipRect() is that the former means no clip at all, and the
+// latter means a clip with unknown bounds. The intersection of the former with
+// a tight clip rect is tight, and that of the latter is loose.
+inline FloatClipRect InfiniteLooseFloatClipRect() {
+ FloatClipRect rect;
+ rect.ClearIsTight();
+ return rect;
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_RECT_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
index daa76c1b077..690644d7dd0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
@@ -93,30 +93,25 @@ void ForeignLayerDisplayItem::PropertiesAsJSON(JSONObject& json) const {
}
#endif
-static void RecordForeignLayerInternal(
- GraphicsContext& context,
- const DisplayItemClient& client,
- DisplayItem::Type type,
- scoped_refptr<cc::Layer> layer,
- const FloatPoint& offset,
- const LayerAsJSONClient* json_client,
- const base::Optional<PropertyTreeState>& properties) {
+static void RecordForeignLayerInternal(GraphicsContext& context,
+ const DisplayItemClient& client,
+ DisplayItem::Type type,
+ scoped_refptr<cc::Layer> layer,
+ const FloatPoint& offset,
+ const LayerAsJSONClient* json_client,
+ const PropertyTreeState* properties) {
PaintController& paint_controller = context.GetPaintController();
- if (paint_controller.DisplayItemConstructionIsDisabled())
- return;
-
// This is like ScopedPaintChunkProperties but uses null id because foreign
// layer chunk doesn't need an id nor a client.
base::Optional<PropertyTreeState> previous_properties;
if (properties) {
previous_properties.emplace(paint_controller.CurrentPaintChunkProperties());
- paint_controller.UpdateCurrentPaintChunkProperties(base::nullopt,
- *properties);
+ paint_controller.UpdateCurrentPaintChunkProperties(nullptr, *properties);
}
paint_controller.CreateAndAppend<ForeignLayerDisplayItem>(
client, type, std::move(layer), offset, json_client);
if (properties) {
- paint_controller.UpdateCurrentPaintChunkProperties(base::nullopt,
+ paint_controller.UpdateCurrentPaintChunkProperties(nullptr,
*previous_properties);
}
}
@@ -126,25 +121,9 @@ void RecordForeignLayer(GraphicsContext& context,
DisplayItem::Type type,
scoped_refptr<cc::Layer> layer,
const FloatPoint& offset,
- const base::Optional<PropertyTreeState>& properties) {
+ const PropertyTreeState* properties) {
RecordForeignLayerInternal(context, client, type, std::move(layer), offset,
nullptr, properties);
}
-void RecordGraphicsLayerAsForeignLayer(GraphicsContext& context,
- DisplayItem::Type type,
- const GraphicsLayer& graphics_layer) {
- // In pre-CompositeAfterPaint, the GraphicsLayer hierarchy is still built
- // during CompositingUpdate, and we have to clear them here to ensure no
- // extraneous layers are still attached. In future we will disable all
- // those layer hierarchy code so we won't need this line.
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- graphics_layer.CcLayer()->RemoveAllChildren();
-
- RecordForeignLayerInternal(
- context, graphics_layer, type, graphics_layer.CcLayer(),
- FloatPoint(graphics_layer.GetOffsetFromTransformNode()), &graphics_layer,
- graphics_layer.GetPropertyTreeState());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
index 95e3c4162f5..7e662a566ef 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
@@ -13,7 +13,6 @@
namespace blink {
class GraphicsContext;
-class GraphicsLayer;
class LayerAsJSONClient;
// Represents foreign content (produced outside Blink) which draws to a layer.
@@ -22,7 +21,7 @@ class LayerAsJSONClient;
//
// Before CAP, this content is not painted, but is instead inserted into the
// GraphicsLayer tree.
-class PLATFORM_EXPORT ForeignLayerDisplayItem final : public DisplayItem {
+class PLATFORM_EXPORT ForeignLayerDisplayItem : public DisplayItem {
public:
ForeignLayerDisplayItem(const DisplayItemClient& client,
Type,
@@ -36,9 +35,9 @@ class PLATFORM_EXPORT ForeignLayerDisplayItem final : public DisplayItem {
const LayerAsJSONClient* GetLayerAsJSONClient() const;
// DisplayItem
- bool Equals(const DisplayItem&) const override;
+ bool Equals(const DisplayItem&) const final;
#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
+ void PropertiesAsJSON(JSONObject&) const final;
#endif
FloatPoint Offset() const { return offset_; }
@@ -75,13 +74,7 @@ PLATFORM_EXPORT void RecordForeignLayer(
DisplayItem::Type type,
scoped_refptr<cc::Layer> layer,
const FloatPoint& offset,
- const base::Optional<PropertyTreeState>& = base::nullopt);
-
-// Records a graphics layer into a GraphicsContext.
-PLATFORM_EXPORT void RecordGraphicsLayerAsForeignLayer(
- GraphicsContext& context,
- DisplayItem::Type type,
- const GraphicsLayer& graphics_layer);
+ const PropertyTreeState* properties = nullptr);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
index 901ab3cfdfe..ba8f4937747 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
@@ -13,8 +13,10 @@ GeometryMapper::Translation2DOrMatrix
GeometryMapper::SourceToDestinationProjection(
const TransformPaintPropertyNode& source,
const TransformPaintPropertyNode& destination) {
- bool success;
- return SourceToDestinationProjectionInternal(source, destination, success);
+ bool has_animation = false;
+ bool success = false;
+ return SourceToDestinationProjectionInternal(source, destination,
+ has_animation, success);
}
// Returns flatten(destination_to_screen)^-1 * flatten(source_to_screen)
@@ -60,32 +62,35 @@ GeometryMapper::Translation2DOrMatrix
GeometryMapper::SourceToDestinationProjectionInternal(
const TransformPaintPropertyNode& source_arg,
const TransformPaintPropertyNode& destination_arg,
+ bool& has_animation,
bool& success) {
const auto& source = source_arg.Unalias();
const auto& destination = destination_arg.Unalias();
+ has_animation = false;
+ success = true;
- if (&source == &destination) {
- success = true;
+ if (&source == &destination)
return Translation2DOrMatrix();
- }
if (source.Parent() && &destination == &source.Parent()->Unalias()) {
if (source.IsIdentityOr2DTranslation()) {
- success = true;
+ // We always use full matrix for animating transforms.
+ DCHECK(!source.HasActiveTransformAnimation());
return Translation2DOrMatrix(source.Translation2D());
}
// The result will be translate(origin)*matrix*translate(-origin) which
// equals to matrix if the origin is zero or if the matrix is just
// identity or 2d translation.
if (source.Origin().IsZero()) {
- success = true;
+ has_animation = source.HasActiveTransformAnimation();
return Translation2DOrMatrix(source.Matrix());
}
}
if (destination.IsIdentityOr2DTranslation() && destination.Parent() &&
&source == &destination.Parent()->Unalias()) {
- success = true;
+ // We always use full matrix for animating transforms.
+ DCHECK(!destination.HasActiveTransformAnimation());
return Translation2DOrMatrix(-destination.Translation2D());
}
@@ -96,7 +101,7 @@ GeometryMapper::SourceToDestinationProjectionInternal(
// the same 2d translation root.
if (source_cache.root_of_2d_translation() ==
destination_cache.root_of_2d_translation()) {
- success = true;
+ // We always use full matrix for animating transforms.
return Translation2DOrMatrix(source_cache.to_2d_translation_root() -
destination_cache.to_2d_translation_root());
}
@@ -105,7 +110,8 @@ GeometryMapper::SourceToDestinationProjectionInternal(
// Even if destination may have invertible screen projection,
// this formula is likely to be numerically more stable.
if (source_cache.plane_root() == destination_cache.plane_root()) {
- success = true;
+ has_animation = source_cache.has_animation_to_plane_root() ||
+ destination_cache.has_animation_to_plane_root();
if (&source == destination_cache.plane_root()) {
return Translation2DOrMatrix(destination_cache.from_plane_root());
}
@@ -124,6 +130,8 @@ GeometryMapper::SourceToDestinationProjectionInternal(
// Screen transform data are updated lazily because they are rarely used.
source.UpdateScreenTransform();
destination.UpdateScreenTransform();
+ has_animation = source_cache.has_animation_to_screen() ||
+ destination_cache.has_animation_to_screen();
if (!destination_cache.projection_from_screen_is_valid()) {
success = false;
return Translation2DOrMatrix();
@@ -132,7 +140,6 @@ GeometryMapper::SourceToDestinationProjectionInternal(
// Case 3: Compute:
// flatten(destination_to_screen)^-1 * flatten(source_to_screen)
const auto& root = TransformPaintPropertyNode::Root();
- success = true;
if (&source == &root)
return Translation2DOrMatrix(destination_cache.projection_from_screen());
TransformationMatrix matrix;
@@ -147,11 +154,12 @@ bool GeometryMapper::LocalToAncestorVisualRect(
const PropertyTreeState& ancestor_state,
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior clip_behavior,
- InclusiveIntersectOrNot inclusive_behavior) {
+ InclusiveIntersectOrNot inclusive_behavior,
+ ExpandVisualRectForAnimationOrNot expand_for_animation) {
bool success = false;
- bool result = LocalToAncestorVisualRectInternal(local_state, ancestor_state,
- mapping_rect, clip_behavior,
- inclusive_behavior, success);
+ bool result = LocalToAncestorVisualRectInternal(
+ local_state, ancestor_state, mapping_rect, clip_behavior,
+ inclusive_behavior, expand_for_animation, success);
DCHECK(success);
return result;
}
@@ -162,6 +170,7 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
FloatClipRect& rect_to_map,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
+ ExpandVisualRectForAnimationOrNot expand_for_animation,
bool& success) {
if (local_state == ancestor_state) {
success = true;
@@ -171,11 +180,13 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
if (&local_state.Effect().Unalias() != &ancestor_state.Effect().Unalias()) {
return SlowLocalToAncestorVisualRectWithEffects(
local_state, ancestor_state, rect_to_map, clip_behavior,
- inclusive_behavior, success);
+ inclusive_behavior, expand_for_animation, success);
}
+ bool has_animation = false;
const auto& translation_2d_or_matrix = SourceToDestinationProjectionInternal(
- local_state.Transform(), ancestor_state.Transform(), success);
+ local_state.Transform(), ancestor_state.Transform(), has_animation,
+ success);
if (!success) {
// A failure implies either source-to-plane or destination-to-plane being
// singular. A notable example of singular source-to-plane from valid CSS:
@@ -192,11 +203,19 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
rect_to_map = FloatClipRect(FloatRect());
return false;
}
- translation_2d_or_matrix.MapFloatClipRect(rect_to_map);
+
+ if (has_animation && expand_for_animation == kExpandVisualRectForAnimation) {
+ // Assume during the animation the transform can map |rect_to_map| to
+ // anywhere. Ancestor clips will still apply.
+ // TODO(crbug.com/1026653): Use animation bounds instead of infinite rect.
+ rect_to_map = InfiniteLooseFloatClipRect();
+ } else {
+ translation_2d_or_matrix.MapFloatClipRect(rect_to_map);
+ }
FloatClipRect clip_rect = LocalToAncestorClipRectInternal(
local_state.Clip(), ancestor_state.Clip(), ancestor_state.Transform(),
- clip_behavior, inclusive_behavior, success);
+ clip_behavior, inclusive_behavior, expand_for_animation, success);
if (success) {
// This is where we propagate the roundedness and tightness of |clip_rect|
// to |rect_to_map|.
@@ -225,6 +244,7 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
+ ExpandVisualRectForAnimationOrNot expand_for_animation,
bool& success) {
PropertyTreeState last_transform_and_clip_state(
local_state.Transform(), local_state.Clip(),
@@ -234,16 +254,26 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
for (const auto* effect = &local_state.Effect().Unalias();
effect && effect != &ancestor_effect;
effect = SafeUnalias(effect->Parent())) {
+ if (effect->HasActiveFilterAnimation() &&
+ expand_for_animation == kExpandVisualRectForAnimation) {
+ // Assume during the animation the filter can map |rect_to_map| to
+ // anywhere. Ancestor clips will still apply.
+ // TODO(crbug.com/1026653): Use animation bounds instead of infinite rect.
+ mapping_rect = InfiniteLooseFloatClipRect();
+ last_transform_and_clip_state.SetTransform(effect->LocalTransformSpace());
+ last_transform_and_clip_state.SetClip(*effect->OutputClip());
+ continue;
+ }
+
if (!effect->HasFilterThatMovesPixels())
continue;
- DCHECK(effect->OutputClip());
PropertyTreeState transform_and_clip_state(effect->LocalTransformSpace(),
*effect->OutputClip(),
EffectPaintPropertyNode::Root());
bool intersects = LocalToAncestorVisualRectInternal(
last_transform_and_clip_state, transform_and_clip_state, mapping_rect,
- clip_behavior, inclusive_behavior, success);
+ clip_behavior, inclusive_behavior, expand_for_animation, success);
if (!success || !intersects) {
success = true;
mapping_rect = FloatClipRect(FloatRect());
@@ -259,7 +289,8 @@ bool GeometryMapper::SlowLocalToAncestorVisualRectWithEffects(
EffectPaintPropertyNode::Root());
bool intersects = LocalToAncestorVisualRectInternal(
last_transform_and_clip_state, final_transform_and_clip_state,
- mapping_rect, clip_behavior, inclusive_behavior, success);
+ mapping_rect, clip_behavior, inclusive_behavior, expand_for_animation,
+ success);
// Many effects (e.g. filters, clip-paths) can make a clip rect not tight.
mapping_rect.ClearIsTight();
@@ -278,7 +309,7 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRect(
bool success = false;
auto result = LocalToAncestorClipRectInternal(
local_clip, ancestor_clip, ancestor_state.Transform(), clip_behavior,
- kNonInclusiveIntersect, success);
+ kNonInclusiveIntersect, kDontExpandVisualRectForAnimation, success);
DCHECK(success);
// Many effects (e.g. filters, clip-paths) can make a clip rect not tight.
@@ -293,8 +324,8 @@ static FloatClipRect GetClipRect(const ClipPaintPropertyNode& clip_node_arg,
const auto& clip_node = clip_node_arg.Unalias();
FloatClipRect clip_rect(
UNLIKELY(clip_behavior == kExcludeOverlayScrollbarSizeForHitTesting)
- ? clip_node.ClipRectExcludingOverlayScrollbars()
- : FloatClipRect(clip_node.ClipRect()));
+ ? clip_node.UnsnappedClipRectExcludingOverlayScrollbars()
+ : FloatClipRect(clip_node.UnsnappedClipRect()));
if (clip_node.ClipPath())
clip_rect.ClearIsTight();
return clip_rect;
@@ -306,6 +337,7 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
const TransformPaintPropertyNode& ancestor_transform_arg,
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior,
+ ExpandVisualRectForAnimationOrNot expand_for_animation,
bool& success) {
const auto& descendant_clip = descendant_clip_arg.Unalias();
const auto& ancestor_clip = ancestor_clip_arg.Unalias();
@@ -330,13 +362,19 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
// Iterate over the path from localState.clip to ancestor_state.clip. Stop if
// we've found a memoized (precomputed) clip for any particular node.
while (clip_node && clip_node != &ancestor_clip) {
- const FloatClipRect* cached_clip = nullptr;
+ const GeometryMapperClipCache::ClipCacheEntry* cached_clip = nullptr;
// Inclusive intersected clips are not cached at present.
if (inclusive_behavior != kInclusiveIntersect)
cached_clip = clip_node->GetClipCache().GetCachedClip(clip_and_transform);
+ if (cached_clip && cached_clip->has_transform_animation &&
+ expand_for_animation == kExpandVisualRectForAnimation) {
+ // Don't use cached clip if it's transformed by any animating transform.
+ cached_clip = nullptr;
+ }
+
if (cached_clip) {
- clip = *cached_clip;
+ clip = cached_clip->clip_rect;
break;
}
@@ -354,23 +392,27 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
// Ignore it for SPv1 for now.
success = true;
}
- FloatClipRect loose_infinite;
- loose_infinite.ClearIsTight();
- return loose_infinite;
+ return InfiniteLooseFloatClipRect();
}
// Iterate down from the top intermediate node found in the previous loop,
// computing and memoizing clip rects as we go.
for (auto it = intermediate_nodes.rbegin(); it != intermediate_nodes.rend();
++it) {
+ bool has_animation = false;
const auto& translation_2d_or_matrix =
SourceToDestinationProjectionInternal((*it)->LocalTransformSpace(),
- ancestor_transform, success);
+ ancestor_transform, has_animation,
+ success);
if (!success) {
success = true;
return FloatClipRect(FloatRect());
}
+ // Don't apply this clip if it's transformed by any animating transform.
+ if (has_animation && expand_for_animation == kExpandVisualRectForAnimation)
+ continue;
+
// This is where we generate the roundedness and tightness of clip rect
// from clip and transform properties, and propagate them to |clip|.
FloatClipRect mapped_rect(GetClipRect(**it, clip_behavior));
@@ -380,13 +422,18 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
} else {
clip.Intersect(mapped_rect);
// Inclusive intersected clips are not cached at present.
- (*it)->GetClipCache().SetCachedClip(clip_and_transform, clip);
+ (*it)->GetClipCache().SetCachedClip(
+ GeometryMapperClipCache::ClipCacheEntry{clip_and_transform, clip,
+ has_animation});
}
}
- // Inclusive intersected clips are not cached at present.
+ // Clips that are inclusive intersected or expanded for animation are not
+ // cached at present.
DCHECK(inclusive_behavior == kInclusiveIntersect ||
- *descendant_clip.GetClipCache().GetCachedClip(clip_and_transform) ==
- clip);
+ expand_for_animation == kExpandVisualRectForAnimation ||
+ descendant_clip.GetClipCache()
+ .GetCachedClip(clip_and_transform)
+ ->clip_rect == clip);
success = true;
return clip;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
index 30c98a0280e..7a55af4fdb5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -18,6 +18,17 @@ namespace blink {
// Clips can use FloatRect::Intersect or FloatRect::InclusiveIntersect.
enum InclusiveIntersectOrNot { kNonInclusiveIntersect, kInclusiveIntersect };
+// Whether to expand the visual or clip rect to infinity when we meet any
+// animating transform or filter when walking from a descendant state to an
+// ancestor state, when mapping a visual rect or getting the accumulated clip
+// rect. After we expanded the rect, we will still apply ancestor clips when
+// continuing walking up the tree. TODO(crbug.com/1026653): Consider animation
+// bounds instead of using infinite rect.
+enum ExpandVisualRectForAnimationOrNot {
+ kDontExpandVisualRectForAnimation,
+ kExpandVisualRectForAnimation,
+};
+
// GeometryMapper is a helper class for fast computations of transformed and
// visual rects in different PropertyTreeStates. The design document has a
// number of details on use cases, algorithmic definitions, and running times.
@@ -100,7 +111,16 @@ class PLATFORM_EXPORT GeometryMapper {
return SkMatrix::MakeTrans(Translation2D().Width(),
Translation2D().Height());
}
- return TransformationMatrix::ToSkMatrix44(Matrix());
+ return SkMatrix(TransformationMatrix::ToSkMatrix44(Matrix()));
+ }
+
+ bool operator==(const Translation2DOrMatrix& other) {
+ return translation_2d_ == other.translation_2d_ &&
+ matrix_ == other.matrix_;
+ }
+
+ bool operator!=(const Translation2DOrMatrix& other) {
+ return !(*this == other);
}
private:
@@ -149,9 +169,10 @@ class PLATFORM_EXPORT GeometryMapper {
return;
}
+ bool has_animation = false;
bool success = false;
- const auto& source_to_destination =
- SourceToDestinationProjectionInternal(source, destination, success);
+ const auto& source_to_destination = SourceToDestinationProjectionInternal(
+ source, destination, has_animation, success);
if (!success)
mapping_rect = Rect();
else
@@ -164,6 +185,9 @@ class PLATFORM_EXPORT GeometryMapper {
// on contents of |local_state|, it's not affected by any effect nodes between
// |local_state| and |ancestor_state|.
//
+ // The UnsnappedClipRect of any clip nodes is used, *not* the
+ // PixelSnappedClipRect.
+ //
// Note that the clip of |ancestor_state| is *not* applied.
//
// The output FloatClipRect may contain false positives for rounded-ness
@@ -215,7 +239,8 @@ class PLATFORM_EXPORT GeometryMapper {
const PropertyTreeState& ancestor_state,
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize,
- InclusiveIntersectOrNot = kNonInclusiveIntersect);
+ InclusiveIntersectOrNot = kNonInclusiveIntersect,
+ ExpandVisualRectForAnimationOrNot = kDontExpandVisualRectForAnimation);
static void ClearCache();
@@ -228,6 +253,7 @@ class PLATFORM_EXPORT GeometryMapper {
static Translation2DOrMatrix SourceToDestinationProjectionInternal(
const TransformPaintPropertyNode& source,
const TransformPaintPropertyNode& destination,
+ bool& has_animation,
bool& success);
static FloatClipRect LocalToAncestorClipRectInternal(
@@ -236,6 +262,7 @@ class PLATFORM_EXPORT GeometryMapper {
const TransformPaintPropertyNode& ancestor_transform,
OverlayScrollbarClipBehavior,
InclusiveIntersectOrNot,
+ ExpandVisualRectForAnimationOrNot,
bool& success);
// The return value has the same meaning as that for
@@ -246,6 +273,7 @@ class PLATFORM_EXPORT GeometryMapper {
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior,
InclusiveIntersectOrNot,
+ ExpandVisualRectForAnimationOrNot,
bool& success);
// The return value has the same meaning as that for
@@ -256,6 +284,7 @@ class PLATFORM_EXPORT GeometryMapper {
FloatClipRect& mapping_rect,
OverlayScrollbarClipBehavior,
InclusiveIntersectOrNot,
+ ExpandVisualRectForAnimationOrNot,
bool& success);
static void MoveRect(FloatRect& rect, const FloatSize& delta) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.cc
index 374c7b41ad4..5feb0102cc1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.cc
@@ -31,28 +31,23 @@ void GeometryMapperClipCache::InvalidateCacheIfNeeded() {
}
}
-const FloatClipRect* GeometryMapperClipCache::GetCachedClip(
+const GeometryMapperClipCache::ClipCacheEntry*
+GeometryMapperClipCache::GetCachedClip(
const ClipAndTransform& clip_and_transform) {
InvalidateCacheIfNeeded();
for (const auto& entry : clip_cache_) {
if (entry.clip_and_transform == clip_and_transform) {
- return &entry.clip_rect;
+ return &entry;
}
}
return nullptr;
}
-void GeometryMapperClipCache::SetCachedClip(
- const ClipAndTransform& clip_and_transform,
- const FloatClipRect& clip) {
+void GeometryMapperClipCache::SetCachedClip(const ClipCacheEntry& entry) {
InvalidateCacheIfNeeded();
-#if DCHECK_IS_ON()
- for (const auto& entry : clip_cache_) {
- if (entry.clip_and_transform == clip_and_transform)
- DCHECK(false); // There should be no existing entry.
- }
-#endif
- clip_cache_.push_back(ClipCacheEntry(clip_and_transform, clip));
+ // There should be no existing entry.
+ DCHECK(!GetCachedClip(entry.clip_and_transform));
+ clip_cache_.push_back(entry);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
index 470b482e760..820475aca56 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
@@ -45,28 +45,29 @@ class PLATFORM_EXPORT GeometryMapperClipCache {
}
};
+ struct ClipCacheEntry {
+ const ClipAndTransform clip_and_transform;
+ // The clip visual rect of the associated clip node in the space of
+ // |clip_and_transform|.
+ const FloatClipRect clip_rect;
+ // Whether there is any transform animation between the transform space
+ // of the associated clip node and |clip_and_transform|.
+ const bool has_transform_animation;
+ };
+
// Returns the clip visual rect of the owning
// clip of |this| in the space of |ancestors|, if there is one cached.
// Otherwise returns null.
- const FloatClipRect* GetCachedClip(const ClipAndTransform& ancestors);
+ const ClipCacheEntry* GetCachedClip(const ClipAndTransform& ancestors);
- // Stores the "clip visual rect" of |this in the space of |ancestors|,
+ // Stores cached the "clip visual rect" of |this| in the space of |ancestors|,
// into a local cache.
- void SetCachedClip(const ClipAndTransform&, const FloatClipRect&);
+ void SetCachedClip(const ClipCacheEntry&);
static void ClearCache();
bool IsValid() const;
private:
- struct ClipCacheEntry {
- const ClipAndTransform clip_and_transform;
- const FloatClipRect clip_rect;
- ClipCacheEntry(const ClipAndTransform& clip_and_transform_arg,
- const FloatClipRect& clip_rect_arg)
- : clip_and_transform(clip_and_transform_arg),
- clip_rect(clip_rect_arg) {}
- };
-
void InvalidateCacheIfNeeded();
Vector<ClipCacheEntry> clip_cache_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
index fea4d4d387c..9e32de68f0c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -20,7 +20,7 @@ namespace blink {
class GeometryMapperTest : public testing::Test,
public PaintTestConfigurations {
public:
- const FloatClipRect* GetCachedClip(
+ const GeometryMapperClipCache::ClipCacheEntry* GetCachedClip(
const ClipPaintPropertyNode& descendant_clip,
const PropertyTreeState& ancestor_property_tree_state) {
GeometryMapperClipCache::ClipAndTransform clip_and_transform(
@@ -37,18 +37,28 @@ class GeometryMapperTest : public testing::Test,
bool& success) {
GeometryMapper::LocalToAncestorVisualRectInternal(
local_state, ancestor_state, mapping_rect,
- kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect, success);
+ kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect,
+ kDontExpandVisualRectForAnimation, success);
}
- // Variables required by CHECK_MAPPINGS(). The tests should set these
- // variables with proper values before calling CHECK_MAPPINGS().
+ void CheckMappings();
+ void CheckLocalToAncestorVisualRect();
+ void CheckLocalToAncestorClipRect();
+ void CheckSourceToDestinationRect();
+ void CheckSourceToDestinationProjection();
+ void CheckCachedClip();
+
+ // Variables required by CheckMappings(). The tests should set these
+ // variables with proper values before calling CheckMappings().
PropertyTreeState local_state = PropertyTreeState::Root();
PropertyTreeState ancestor_state = PropertyTreeState::Root();
FloatRect input_rect;
FloatClipRect expected_visual_rect;
+ base::Optional<FloatClipRect> expected_visual_rect_expanded_for_animation;
FloatSize expected_translation_2d;
base::Optional<TransformationMatrix> expected_transform;
FloatClipRect expected_clip;
+ bool expected_clip_has_transform_animation = false;
FloatRect expected_transformed_rect;
};
@@ -76,89 +86,88 @@ INSTANTIATE_PAINT_TEST_SUITE_P(GeometryMapperTest);
EXPECT_FLOAT_RECT_NEAR((expected).Rect(), (actual).Rect()); \
} while (false)
-#define CHECK_LOCAL_TO_ANCESTOR_VISUAL_RECT() \
- do { \
- SCOPED_TRACE("Check LocalToAncestorVisualRect"); \
- FloatClipRect actual_visual_rect(input_rect); \
- GeometryMapper::LocalToAncestorVisualRect(local_state, ancestor_state, \
- actual_visual_rect); \
- EXPECT_CLIP_RECT_EQ(expected_visual_rect, actual_visual_rect); \
- } while (false)
+void GeometryMapperTest::CheckLocalToAncestorVisualRect() {
+ FloatClipRect actual_visual_rect(input_rect);
+ GeometryMapper::LocalToAncestorVisualRect(local_state, ancestor_state,
+ actual_visual_rect);
+ EXPECT_CLIP_RECT_EQ(expected_visual_rect, actual_visual_rect);
-#define CHECK_LOCAL_TO_ANCESTOR_CLIP_RECT() \
- do { \
- SCOPED_TRACE("Check LocalToAncestorClipRect"); \
- FloatClipRect actual_clip_rect; \
- actual_clip_rect = \
- GeometryMapper::LocalToAncestorClipRect(local_state, ancestor_state); \
- EXPECT_CLIP_RECT_EQ(expected_clip, actual_clip_rect); \
- } while (false)
+ actual_visual_rect = FloatClipRect(input_rect);
+ GeometryMapper::LocalToAncestorVisualRect(
+ local_state, ancestor_state, actual_visual_rect,
+ kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect,
+ kExpandVisualRectForAnimation);
+ EXPECT_CLIP_RECT_EQ(expected_visual_rect_expanded_for_animation
+ ? *expected_visual_rect_expanded_for_animation
+ : expected_visual_rect,
+ actual_visual_rect);
+}
-#define CHECK_SOURCE_TO_DESTINATION_RECT() \
- do { \
- SCOPED_TRACE("Check SourceToDestinationRect"); \
- auto actual_transformed_rect = input_rect; \
- GeometryMapper::SourceToDestinationRect(local_state.Transform(), \
- ancestor_state.Transform(), \
- actual_transformed_rect); \
- EXPECT_FLOAT_RECT_NEAR(expected_transformed_rect, \
- actual_transformed_rect); \
- } while (false)
+void GeometryMapperTest::CheckLocalToAncestorClipRect() {
+ FloatClipRect actual_clip_rect =
+ GeometryMapper::LocalToAncestorClipRect(local_state, ancestor_state);
+ EXPECT_CLIP_RECT_EQ(expected_clip, actual_clip_rect);
+}
-#define CHECK_SOURCE_TO_DESTINATION_PROJECTION() \
- do { \
- SCOPED_TRACE("Check SourceToDestinationProjection"); \
- const auto& actual_transform_to_ancestor = \
- GeometryMapper::SourceToDestinationProjection( \
- local_state.Transform(), ancestor_state.Transform()); \
- if (expected_transform) { \
- EXPECT_EQ(*expected_transform, actual_transform_to_ancestor.Matrix()); \
- } else { \
- EXPECT_EQ(expected_translation_2d, \
- actual_transform_to_ancestor.Translation2D()); \
- } \
- } while (false)
+void GeometryMapperTest::CheckSourceToDestinationRect() {
+ auto actual_transformed_rect = input_rect;
+ GeometryMapper::SourceToDestinationRect(local_state.Transform(),
+ ancestor_state.Transform(),
+ actual_transformed_rect);
+ EXPECT_FLOAT_RECT_NEAR(expected_transformed_rect, actual_transformed_rect);
+}
-#define CHECK_CACHED_CLIP() \
- do { \
- if (&ancestor_state.Effect() != &local_state.Effect()) \
- break; \
- SCOPED_TRACE("Check cached clip"); \
- const auto& local_clip = local_state.Clip().Unalias(); \
- const auto* cached_clip = GetCachedClip(local_clip, ancestor_state); \
- if (&ancestor_state.Clip() == &local_clip || \
- (&ancestor_state.Clip() == local_clip.Parent() && \
- &ancestor_state.Transform() == &local_clip.LocalTransformSpace())) { \
- EXPECT_EQ(nullptr, cached_clip); \
- break; \
- } \
- ASSERT_NE(nullptr, cached_clip); \
- EXPECT_CLIP_RECT_EQ(expected_clip, *cached_clip); \
- } while (false)
+void GeometryMapperTest::CheckSourceToDestinationProjection() {
+ const auto& actual_transform_to_ancestor =
+ GeometryMapper::SourceToDestinationProjection(local_state.Transform(),
+ ancestor_state.Transform());
+ if (expected_transform) {
+ EXPECT_EQ(*expected_transform, actual_transform_to_ancestor.Matrix());
+ } else {
+ EXPECT_EQ(expected_translation_2d,
+ actual_transform_to_ancestor.Translation2D());
+ }
+}
+
+void GeometryMapperTest::CheckCachedClip() {
+ if (&ancestor_state.Effect() != &local_state.Effect())
+ return;
+ const auto& local_clip = local_state.Clip().Unalias();
+ const auto* cached_clip = GetCachedClip(local_clip, ancestor_state);
+ if (&ancestor_state.Clip() == &local_clip ||
+ (&ancestor_state.Clip() == local_clip.Parent() &&
+ &ancestor_state.Transform() == &local_clip.LocalTransformSpace())) {
+ EXPECT_EQ(nullptr, cached_clip);
+ return;
+ }
+ ASSERT_NE(nullptr, cached_clip);
+ EXPECT_CLIP_RECT_EQ(expected_clip, cached_clip->clip_rect);
+ EXPECT_EQ(expected_clip_has_transform_animation,
+ cached_clip->has_transform_animation);
+}
// See the data fields of GeometryMapperTest for variables that will be used in
// this macro.
-#define CHECK_MAPPINGS() \
- do { \
- CHECK_LOCAL_TO_ANCESTOR_VISUAL_RECT(); \
- CHECK_LOCAL_TO_ANCESTOR_CLIP_RECT(); \
- CHECK_SOURCE_TO_DESTINATION_RECT(); \
- CHECK_SOURCE_TO_DESTINATION_PROJECTION(); \
- { \
- SCOPED_TRACE("Repeated check to test caching"); \
- CHECK_LOCAL_TO_ANCESTOR_VISUAL_RECT(); \
- CHECK_LOCAL_TO_ANCESTOR_CLIP_RECT(); \
- CHECK_SOURCE_TO_DESTINATION_RECT(); \
- CHECK_SOURCE_TO_DESTINATION_PROJECTION(); \
- } \
- CHECK_CACHED_CLIP(); \
- } while (false)
+void GeometryMapperTest::CheckMappings() {
+ CheckLocalToAncestorVisualRect();
+ CheckLocalToAncestorClipRect();
+ CheckSourceToDestinationRect();
+ CheckSourceToDestinationProjection();
+ {
+ SCOPED_TRACE("Repeated check to test caching");
+ CheckLocalToAncestorVisualRect();
+ CheckLocalToAncestorClipRect();
+ CheckSourceToDestinationRect();
+ CheckSourceToDestinationProjection();
+ }
+ CheckCachedClip();
+}
TEST_P(GeometryMapperTest, Root) {
input_rect = FloatRect(0, 0, 100, 100);
expected_visual_rect = FloatClipRect(input_rect);
expected_transformed_rect = input_rect;
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, IdentityTransform) {
@@ -168,7 +177,7 @@ TEST_P(GeometryMapperTest, IdentityTransform) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = input_rect;
expected_visual_rect = FloatClipRect(input_rect);
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, TranslationTransform) {
@@ -180,7 +189,7 @@ TEST_P(GeometryMapperTest, TranslationTransform) {
expected_transformed_rect = input_rect;
expected_transformed_rect.Move(expected_translation_2d);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
- CHECK_MAPPINGS();
+ CheckMappings();
FloatRect rect = expected_transformed_rect;
GeometryMapper::SourceToDestinationRect(t0(), local_state.Transform(), rect);
@@ -197,7 +206,7 @@ TEST_P(GeometryMapperTest, TranslationTransformWithAlias) {
expected_transformed_rect = input_rect;
expected_transformed_rect.Move(expected_translation_2d);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
- CHECK_MAPPINGS();
+ CheckMappings();
FloatRect rect = expected_transformed_rect;
GeometryMapper::SourceToDestinationRect(t0(), local_state.Transform(), rect);
@@ -213,7 +222,7 @@ TEST_P(GeometryMapperTest, RotationAndScaleTransform) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, RotationAndScaleTransformWithAlias) {
@@ -226,7 +235,7 @@ TEST_P(GeometryMapperTest, RotationAndScaleTransformWithAlias) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, RotationAndScaleTransformWithTransformOrigin) {
@@ -240,7 +249,7 @@ TEST_P(GeometryMapperTest, RotationAndScaleTransformWithTransformOrigin) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, NestedTransforms) {
@@ -256,7 +265,7 @@ TEST_P(GeometryMapperTest, NestedTransforms) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, NestedTransformsFlattening) {
@@ -277,7 +286,7 @@ TEST_P(GeometryMapperTest, NestedTransformsFlattening) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, NestedTransformsScaleAndTranslation) {
@@ -295,7 +304,7 @@ TEST_P(GeometryMapperTest, NestedTransformsScaleAndTranslation) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, NestedTransformsIntermediateDestination) {
@@ -313,7 +322,7 @@ TEST_P(GeometryMapperTest, NestedTransformsIntermediateDestination) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, SimpleClip) {
@@ -322,9 +331,23 @@ TEST_P(GeometryMapperTest, SimpleClip) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = input_rect; // not clipped.
- expected_clip = FloatClipRect(clip->ClipRect());
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
+}
+
+TEST_P(GeometryMapperTest, SimpleClipPixelSnapped) {
+ auto clip = CreateClip(c0(), t0(), FloatRoundedRect(10, 10, 50.5, 50.5),
+ FloatRoundedRect(10, 10, 50, 51));
+ local_state.SetClip(*clip);
+
+ input_rect = FloatRect(0, 0, 100, 100);
+ expected_transformed_rect = input_rect; // not clipped.
+
+ // GeometryMapper does not use the PixelSnappedClipRect.
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
+ expected_visual_rect = expected_clip;
+ CheckMappings();
}
TEST_P(GeometryMapperTest, SimpleClipWithAlias) {
@@ -334,15 +357,14 @@ TEST_P(GeometryMapperTest, SimpleClipWithAlias) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = input_rect; // not clipped.
- expected_clip = FloatClipRect(clip->Unalias().ClipRect());
+ expected_clip = FloatClipRect(clip->Unalias().UnsnappedClipRect());
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, SimpleClipOverlayScrollbars) {
- ClipPaintPropertyNode::State clip_state;
- clip_state.local_transform_space = &t0();
- clip_state.clip_rect = FloatRoundedRect(10, 10, 50, 50);
+ ClipPaintPropertyNode::State clip_state(&t0(),
+ FloatRoundedRect(10, 10, 50, 50));
clip_state.clip_rect_excluding_overlay_scrollbars =
FloatClipRect(FloatRect(10, 10, 45, 43));
auto clip = ClipPaintPropertyNode::Create(c0(), std::move(clip_state));
@@ -439,10 +461,10 @@ TEST_P(GeometryMapperTest, RoundedClip) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = input_rect;
- expected_clip = FloatClipRect(clip->ClipRect());
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
EXPECT_TRUE(expected_clip.HasRadius());
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, ClipPath) {
@@ -457,7 +479,7 @@ TEST_P(GeometryMapperTest, ClipPath) {
expected_clip = FloatClipRect(FloatRect(10, 10, 50, 50));
expected_clip.ClearIsTight();
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, TwoClips) {
@@ -472,19 +494,19 @@ TEST_P(GeometryMapperTest, TwoClips) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = input_rect;
- expected_clip = FloatClipRect(clip1->ClipRect());
+ expected_clip = FloatClipRect(clip1->UnsnappedClipRect());
EXPECT_TRUE(expected_clip.HasRadius());
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
ancestor_state.SetClip(*clip1);
- expected_clip = FloatClipRect(clip2->ClipRect());
+ expected_clip = FloatClipRect(clip2->UnsnappedClipRect());
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, TwoClipsTransformAbove) {
- auto transform = CreateTransform(t0(), TransformationMatrix());
+ auto transform = Create2DTranslation(t0(), 0, 0);
FloatRoundedRect clip_rect1(
FloatRect(10, 10, 50, 50),
@@ -497,16 +519,16 @@ TEST_P(GeometryMapperTest, TwoClipsTransformAbove) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = input_rect;
- expected_clip = FloatClipRect(clip2->ClipRect());
+ expected_clip = FloatClipRect(clip2->UnsnappedClipRect());
expected_clip.SetHasRadius();
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
- expected_clip = FloatClipRect(clip1->ClipRect());
+ expected_clip = FloatClipRect(clip1->UnsnappedClipRect());
EXPECT_TRUE(expected_clip.HasRadius());
local_state.SetClip(*clip1);
expected_visual_rect = expected_clip;
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, ClipBeforeTransform) {
@@ -518,14 +540,36 @@ TEST_P(GeometryMapperTest, ClipBeforeTransform) {
input_rect = FloatRect(0, 0, 100, 100);
expected_visual_rect = FloatClipRect(input_rect);
- expected_visual_rect.Intersect(FloatClipRect(clip->ClipRect()));
+ expected_visual_rect.Intersect(FloatClipRect(clip->UnsnappedClipRect()));
+ expected_visual_rect.Map(*expected_transform);
+ EXPECT_FALSE(expected_visual_rect.IsTight());
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
+ expected_clip.Map(*expected_transform);
+ EXPECT_FALSE(expected_clip.IsTight());
+ expected_transformed_rect = expected_transform->MapRect(input_rect);
+ CheckMappings();
+}
+
+TEST_P(GeometryMapperTest, ExpandVisualRectWithClipBeforeAnimatingTransform) {
+ expected_transform = TransformationMatrix().Rotate(45);
+ auto transform = CreateAnimatingTransform(t0(), *expected_transform);
+ auto clip = CreateClip(c0(), *transform, FloatRoundedRect(10, 10, 50, 50));
+ local_state.SetClip(*clip);
+ local_state.SetTransform(*transform);
+
+ input_rect = FloatRect(0, 0, 100, 100);
+ expected_visual_rect = FloatClipRect(input_rect);
+ expected_visual_rect.Intersect(FloatClipRect(clip->UnsnappedClipRect()));
expected_visual_rect.Map(*expected_transform);
+ // The clip has animating transform, so it doesn't apply to the visual rect.
+ expected_visual_rect_expanded_for_animation = InfiniteLooseFloatClipRect();
EXPECT_FALSE(expected_visual_rect.IsTight());
- expected_clip = FloatClipRect(clip->ClipRect());
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
expected_clip.Map(*expected_transform);
EXPECT_FALSE(expected_clip.IsTight());
+ expected_clip_has_transform_animation = true;
expected_transformed_rect = expected_transform->MapRect(input_rect);
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, ClipAfterTransform) {
@@ -539,11 +583,33 @@ TEST_P(GeometryMapperTest, ClipAfterTransform) {
expected_transformed_rect = expected_transform->MapRect(input_rect);
expected_visual_rect = FloatClipRect(input_rect);
expected_visual_rect.Map(*expected_transform);
- expected_visual_rect.Intersect(FloatClipRect(clip->ClipRect()));
+ expected_visual_rect.Intersect(FloatClipRect(clip->UnsnappedClipRect()));
EXPECT_FALSE(expected_visual_rect.IsTight());
- expected_clip = FloatClipRect(clip->ClipRect());
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
EXPECT_TRUE(expected_clip.IsTight());
- CHECK_MAPPINGS();
+ CheckMappings();
+}
+
+TEST_P(GeometryMapperTest, ExpandVisualRectWithClipAfterAnimatingTransform) {
+ expected_transform = TransformationMatrix().Rotate(45);
+ auto transform = CreateAnimatingTransform(t0(), *expected_transform);
+ auto clip = CreateClip(c0(), t0(), FloatRoundedRect(10, 10, 200, 200));
+ local_state.SetClip(*clip);
+ local_state.SetTransform(*transform);
+
+ input_rect = FloatRect(0, 0, 100, 100);
+ expected_transformed_rect = expected_transform->MapRect(input_rect);
+ expected_visual_rect = FloatClipRect(input_rect);
+ expected_visual_rect.Map(*expected_transform);
+ expected_visual_rect.Intersect(FloatClipRect(clip->UnsnappedClipRect()));
+ EXPECT_FALSE(expected_visual_rect.IsTight());
+ expected_clip = FloatClipRect(clip->UnsnappedClipRect());
+ EXPECT_TRUE(expected_clip.IsTight());
+ // The visual rect is expanded first to infinity because of the transform
+ // animation, then clipped by the clip.
+ expected_visual_rect_expanded_for_animation = expected_clip;
+ expected_visual_rect_expanded_for_animation->ClearIsTight();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, TwoClipsWithTransformBetween) {
@@ -552,43 +618,58 @@ TEST_P(GeometryMapperTest, TwoClipsWithTransformBetween) {
auto transform = CreateTransform(t0(), *expected_transform);
auto clip2 =
CreateClip(*clip1, *transform, FloatRoundedRect(10, 10, 200, 200));
+ local_state.SetClip(*clip2);
+ local_state.SetTransform(*transform);
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = expected_transform->MapRect(input_rect);
- {
- local_state.SetClip(*clip1);
- local_state.SetTransform(*transform);
-
- expected_visual_rect = FloatClipRect(input_rect);
- expected_visual_rect.Map(*expected_transform);
- expected_visual_rect.Intersect(FloatClipRect(clip1->ClipRect()));
- EXPECT_FALSE(expected_visual_rect.IsTight());
- expected_clip = FloatClipRect(clip1->ClipRect());
- EXPECT_TRUE(expected_clip.IsTight());
- CHECK_MAPPINGS();
- }
+ expected_clip = FloatClipRect(clip2->UnsnappedClipRect());
+ expected_clip.Map(*expected_transform);
+ expected_clip.Intersect(FloatClipRect(clip1->UnsnappedClipRect()));
+ EXPECT_FALSE(expected_clip.IsTight());
- {
- local_state.SetClip(*clip2);
- local_state.SetTransform(*transform);
-
- expected_clip = FloatClipRect(clip2->ClipRect());
- expected_clip.Map(*expected_transform);
- expected_clip.Intersect(FloatClipRect(clip1->ClipRect()));
- EXPECT_FALSE(expected_clip.IsTight());
-
- // All clips are performed in the space of the ancestor. In cases such as
- // this, this means the clip is not tight.
- expected_visual_rect = FloatClipRect(input_rect);
- expected_visual_rect.Map(*expected_transform);
- // Intersect with all clips between local and ancestor, independently mapped
- // to ancestor space.
- expected_visual_rect.Intersect(expected_clip);
- EXPECT_FALSE(expected_visual_rect.IsTight());
-
- CHECK_MAPPINGS();
- }
+ // All clips are performed in the space of the ancestor. In cases such as
+ // this, this means the clip is not tight.
+ expected_visual_rect = FloatClipRect(input_rect);
+ expected_visual_rect.Map(*expected_transform);
+ // Intersect with all clips between local and ancestor, independently mapped
+ // to ancestor space.
+ expected_visual_rect.Intersect(expected_clip);
+ EXPECT_FALSE(expected_visual_rect.IsTight());
+
+ CheckMappings();
+}
+
+TEST_P(GeometryMapperTest,
+ ExpandVisualRectWithTwoClipsWithAnimatingTransformBetween) {
+ auto clip1 = CreateClip(c0(), t0(), FloatRoundedRect(10, 10, 200, 200));
+ expected_transform = TransformationMatrix().Rotate(45);
+ auto transform = CreateAnimatingTransform(t0(), *expected_transform);
+ auto clip2 =
+ CreateClip(*clip1, *transform, FloatRoundedRect(10, 10, 200, 200));
+ local_state.SetClip(*clip2);
+ local_state.SetTransform(*transform);
+
+ input_rect = FloatRect(0, 0, 100, 100);
+ expected_transformed_rect = expected_transform->MapRect(input_rect);
+
+ expected_clip = FloatClipRect(clip2->UnsnappedClipRect());
+ expected_clip.Map(*expected_transform);
+ expected_clip.Intersect(FloatClipRect(clip1->UnsnappedClipRect()));
+ EXPECT_FALSE(expected_clip.IsTight());
+ expected_clip_has_transform_animation = true;
+ expected_visual_rect = FloatClipRect(input_rect);
+ expected_visual_rect.Map(*expected_transform);
+ expected_visual_rect.Intersect(expected_clip);
+ EXPECT_FALSE(expected_visual_rect.IsTight());
+ // The visual rect is expanded to infinity because of the transform animation,
+ // then clipped by clip1. clip2 doesn't apply because it's below the animating
+ // transform.
+ expected_visual_rect_expanded_for_animation =
+ FloatClipRect(clip1->UnsnappedClipRect());
+ expected_visual_rect_expanded_for_animation->ClearIsTight();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, SiblingTransforms) {
@@ -701,13 +782,13 @@ TEST_P(GeometryMapperTest, FilterWithClipsAndTransforms) {
auto output = input_rect;
output.Move(transform_below_effect->Translation2D());
// 2. clipBelowEffect
- output.Intersect(clip_below_effect->ClipRect().Rect());
+ output.Intersect(clip_below_effect->UnsnappedClipRect().Rect());
EXPECT_EQ(FloatRect(20, 30, 90, 80), output);
// 3. effect (the outset is 3 times of blur amount).
output = filters.MapRect(output);
EXPECT_EQ(FloatRect(-40, -30, 210, 200), output);
// 4. clipAboveEffect
- output.Intersect(clip_above_effect->ClipRect().Rect());
+ output.Intersect(clip_above_effect->UnsnappedClipRect().Rect());
EXPECT_EQ(FloatRect(-40, -30, 140, 130), output);
// 5. transformAboveEffect
output.Move(transform_above_effect->Translation2D());
@@ -721,7 +802,7 @@ TEST_P(GeometryMapperTest, FilterWithClipsAndTransforms) {
expected_visual_rect.ClearIsTight();
expected_clip = FloatClipRect(FloatRect(50, 60, 90, 90));
expected_clip.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, FilterWithClipsAndTransformsWithAlias) {
@@ -751,13 +832,13 @@ TEST_P(GeometryMapperTest, FilterWithClipsAndTransformsWithAlias) {
auto output = input_rect;
output.Move(transform_below_effect->Translation2D());
// 2. clipBelowEffect
- output.Intersect(clip_below_effect->ClipRect().Rect());
+ output.Intersect(clip_below_effect->UnsnappedClipRect().Rect());
EXPECT_EQ(FloatRect(20, 30, 90, 80), output);
// 3. effect (the outset is 3 times of blur amount).
output = filters.MapRect(output);
EXPECT_EQ(FloatRect(-40, -30, 210, 200), output);
// 4. clipAboveEffect
- output.Intersect(clip_above_effect->ClipRect().Rect());
+ output.Intersect(clip_above_effect->UnsnappedClipRect().Rect());
EXPECT_EQ(FloatRect(-40, -30, 140, 130), output);
// 5. transformAboveEffect
output.Move(transform_above_effect->Translation2D());
@@ -771,7 +852,36 @@ TEST_P(GeometryMapperTest, FilterWithClipsAndTransformsWithAlias) {
expected_visual_rect.ClearIsTight();
expected_clip = FloatClipRect(FloatRect(50, 60, 90, 90));
expected_clip.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
+}
+
+TEST_P(GeometryMapperTest,
+ ExpandVisualRectWithTwoClipsWithAnimatingFilterBetween) {
+ auto clip1 = CreateClip(c0(), t0(), FloatRoundedRect(10, 10, 200, 200));
+ auto effect = CreateAnimatingFilterEffect(e0(), CompositorFilterOperations(),
+ clip1.get());
+ auto clip2 = CreateClip(*clip1, t0(), FloatRoundedRect(50, 0, 200, 50));
+ local_state.SetClip(*clip2);
+ local_state.SetEffect(*effect);
+
+ input_rect = FloatRect(0, 0, 100, 100);
+ expected_transformed_rect = input_rect;
+ auto output = input_rect;
+ output.Intersect(clip2->UnsnappedClipRect().Rect());
+ output.Intersect(clip1->UnsnappedClipRect().Rect());
+ EXPECT_EQ(FloatRect(50, 10, 50, 40), output);
+ expected_visual_rect = FloatClipRect(output);
+ expected_visual_rect.ClearIsTight();
+ expected_clip = FloatClipRect(clip2->UnsnappedClipRect());
+ expected_clip.Intersect(FloatClipRect(clip1->UnsnappedClipRect()));
+ expected_clip.ClearIsTight();
+ // The visual rect is expanded to infinity because of the filter animation,
+ // the clipped by clip1. clip2 doesn't apply because it's below the animating
+ // filter.
+ expected_visual_rect_expanded_for_animation =
+ FloatClipRect(clip1->UnsnappedClipRect());
+ expected_visual_rect_expanded_for_animation->ClearIsTight();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, ReflectionWithPaintOffset) {
@@ -787,7 +897,7 @@ TEST_P(GeometryMapperTest, ReflectionWithPaintOffset) {
expected_visual_rect = FloatClipRect(FloatRect(50, 100, 100, 50));
expected_visual_rect.ClearIsTight();
- CHECK_MAPPINGS();
+ CheckMappings();
}
TEST_P(GeometryMapperTest, InvertedClip) {
@@ -814,8 +924,8 @@ TEST_P(GeometryMapperTest, InvertedClip) {
TEST_P(GeometryMapperTest, Precision) {
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(32767));
auto t2 = CreateTransform(*t1, TransformationMatrix().Rotate(1));
- auto t3 = CreateTransform(*t2, TransformationMatrix());
- auto t4 = CreateTransform(*t3, TransformationMatrix());
+ auto t3 = Create2DTranslation(*t2, 0, 0);
+ auto t4 = Create2DTranslation(*t3, 0, 0);
EXPECT_TRUE(
GeometryMapper::SourceToDestinationProjection(*t4, *t4).IsIdentity());
EXPECT_TRUE(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
index e6bb3172f6f..1a8bdc3cb94 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
@@ -42,6 +42,8 @@ void GeometryMapperTransformCache::Update(
screen_transform_ = nullptr;
if (node.IsIdentityOr2DTranslation()) {
+ // We always use full matrix for animating transforms.
+ DCHECK(!node.HasActiveTransformAnimation());
root_of_2d_translation_ = parent.root_of_2d_translation_;
to_2d_translation_root_ = parent.to_2d_translation_root_;
const auto& translation = node.Translation2D();
@@ -57,6 +59,9 @@ void GeometryMapperTransformCache::Update(
plane_root_transform_->from_plane_root = parent.from_plane_root();
plane_root_transform_->from_plane_root.PostTranslate(
-translation.Width(), -translation.Height());
+ plane_root_transform_->has_animation =
+ parent.plane_root_transform_->has_animation ||
+ node.HasActiveTransformAnimation();
} else {
// The parent doesn't have plane_root_transform_ means that the parent's
// plane root is the same as the 2d translation root, so this node
@@ -86,6 +91,7 @@ void GeometryMapperTransformCache::Update(
plane_root_transform_->plane_root = &node;
plane_root_transform_->to_plane_root.MakeIdentity();
plane_root_transform_->from_plane_root.MakeIdentity();
+ plane_root_transform_->has_animation = false;
} else {
plane_root_transform_->plane_root = parent.plane_root();
plane_root_transform_->to_plane_root.MakeIdentity();
@@ -93,6 +99,9 @@ void GeometryMapperTransformCache::Update(
plane_root_transform_->to_plane_root.Multiply(local);
plane_root_transform_->from_plane_root = local.Inverse();
parent.ApplyFromPlaneRoot(plane_root_transform_->from_plane_root);
+ plane_root_transform_->has_animation =
+ parent.has_animation_to_plane_root() ||
+ node.HasActiveTransformAnimation();
}
}
@@ -130,6 +139,8 @@ void GeometryMapperTransformCache::UpdateScreenTransform(
to_screen_flattened.IsInvertible();
if (screen_transform_->projection_from_screen_is_valid)
screen_transform_->projection_from_screen = to_screen_flattened.Inverse();
+
+ screen_transform_->has_animation |= node.HasActiveTransformAnimation();
}
#if DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
index ec25d6d76cf..b722bbf64ab 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
@@ -71,6 +71,13 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
else
ApplyFromPlaneRoot(m);
}
+ bool has_animation_to_screen() const {
+#if DCHECK_IS_ON()
+ CheckScreenTransformUpdated();
+#endif
+ return UNLIKELY(screen_transform_) ? screen_transform_->has_animation
+ : has_animation_to_plane_root();
+ }
const TransformationMatrix& to_plane_root() const {
DCHECK(plane_root_transform_);
@@ -100,6 +107,10 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
return UNLIKELY(plane_root_transform_) ? plane_root_transform_->plane_root
: root_of_2d_translation();
}
+ bool has_animation_to_plane_root() const {
+ return UNLIKELY(plane_root_transform_) &&
+ plane_root_transform_->has_animation;
+ }
private:
friend class GeometryMapperTransformCacheTest;
@@ -180,6 +191,7 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
TransformationMatrix to_plane_root;
TransformationMatrix from_plane_root;
const TransformPaintPropertyNode* plane_root;
+ bool has_animation;
};
std::unique_ptr<PlaneRootTransform> plane_root_transform_;
@@ -187,6 +199,7 @@ class PLATFORM_EXPORT GeometryMapperTransformCache {
TransformationMatrix to_screen;
TransformationMatrix projection_from_screen;
bool projection_from_screen_is_valid;
+ bool has_animation;
};
std::unique_ptr<ScreenTransform> screen_transform_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache_test.cc
index f04c76e4759..90511afcc61 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache_test.cc
@@ -137,9 +137,9 @@ class GeometryMapperTransformCacheTest : public testing::Test {
};
TEST_F(GeometryMapperTransformCacheTest, All2dTranslations) {
- auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
- auto t2 = CreateTransform(*t1, TransformationMatrix());
- auto t3 = CreateTransform(*t2, TransformationMatrix().Translate(7, 8));
+ auto t1 = Create2DTranslation(t0(), 1, 2);
+ auto t2 = Create2DTranslation(*t1, 0, 0);
+ auto t3 = Create2DTranslation(*t2, 7, 8);
Check2dTranslationToRoot(t0(), 0, 0);
Check2dTranslationToRoot(*t1, 1, 2);
@@ -148,9 +148,9 @@ TEST_F(GeometryMapperTransformCacheTest, All2dTranslations) {
}
TEST_F(GeometryMapperTransformCacheTest, RootAsPlaneRootWithIntermediateScale) {
- auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
+ auto t1 = Create2DTranslation(t0(), 1, 2);
auto t2 = CreateTransform(*t1, TransformationMatrix().Scale(3));
- auto t3 = CreateTransform(*t2, TransformationMatrix().Translate(7, 8));
+ auto t3 = Create2DTranslation(*t2, 7, 8);
Check2dTranslationToRoot(t0(), 0, 0);
Check2dTranslationToRoot(*t1, 1, 2);
@@ -162,9 +162,9 @@ TEST_F(GeometryMapperTransformCacheTest, RootAsPlaneRootWithIntermediateScale) {
TEST_F(GeometryMapperTransformCacheTest,
IntermediatePlaneRootSameAs2dTranslationRoot) {
- auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
+ auto t1 = Create2DTranslation(t0(), 1, 2);
auto t2 = CreateTransform(*t1, TransformationMatrix().Rotate3d(0, 45, 0));
- auto t3 = CreateTransform(*t2, TransformationMatrix().Translate(7, 8));
+ auto t3 = Create2DTranslation(*t2, 7, 8);
Check2dTranslationToRoot(t0(), 0, 0);
Check2dTranslationToRoot(*t1, 1, 2);
@@ -176,10 +176,10 @@ TEST_F(GeometryMapperTransformCacheTest,
TEST_F(GeometryMapperTransformCacheTest,
IntermediatePlaneRootDifferent2dTranslationRoot) {
- auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
+ auto t1 = Create2DTranslation(t0(), 1, 2);
auto t2 = CreateTransform(*t1, TransformationMatrix().Rotate3d(0, 45, 0));
auto t3 = CreateTransform(*t2, TransformationMatrix().Scale(3));
- auto t4 = CreateTransform(*t3, TransformationMatrix().Translate(7, 8));
+ auto t4 = Create2DTranslation(*t3, 7, 8);
Check2dTranslationToRoot(t0(), 0, 0);
Check2dTranslationToRoot(*t1, 1, 2);
@@ -199,9 +199,9 @@ TEST_F(GeometryMapperTransformCacheTest,
}
TEST_F(GeometryMapperTransformCacheTest, TransformUpdate) {
- auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
- auto t2 = CreateTransform(*t1, TransformationMatrix());
- auto t3 = CreateTransform(*t2, TransformationMatrix().Translate(7, 8));
+ auto t1 = Create2DTranslation(t0(), 1, 2);
+ auto t2 = Create2DTranslation(*t1, 0, 0);
+ auto t3 = Create2DTranslation(*t2, 7, 8);
Check2dTranslationToRoot(t0(), 0, 0);
Check2dTranslationToRoot(*t1, 1, 2);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc
new file mode 100644
index 00000000000..5550c716901
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc
@@ -0,0 +1,63 @@
+// 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 "third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h"
+
+#include <utility>
+
+#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+namespace blink {
+
+GraphicsLayerDisplayItem::GraphicsLayerDisplayItem(
+ const GraphicsLayer& graphics_layer)
+ : DisplayItem(graphics_layer, kGraphicsLayerWrapper, sizeof(*this)),
+ graphics_layer_(graphics_layer) {}
+
+bool GraphicsLayerDisplayItem::Equals(const DisplayItem& other) const {
+ return GetType() == other.GetType() &&
+ GetGraphicsLayer() ==
+ static_cast<const GraphicsLayerDisplayItem&>(other)
+ .GetGraphicsLayer();
+}
+
+#if DCHECK_IS_ON()
+void GraphicsLayerDisplayItem::PropertiesAsJSON(JSONObject& json) const {
+ DisplayItem::PropertiesAsJSON(json);
+ json.SetInteger("layer", graphics_layer_.CcLayer()->id());
+ FloatPoint offset(graphics_layer_.GetOffsetFromTransformNode());
+ json.SetDouble("offset_x", offset.X());
+ json.SetDouble("offset_y", offset.Y());
+}
+#endif
+
+void RecordGraphicsLayer(GraphicsContext& context,
+ const GraphicsLayer& graphics_layer) {
+ // In pre-CompositeAfterPaint, the GraphicsLayer hierarchy is still built
+ // during CompositingUpdate, and we have to clear them here to ensure no
+ // extraneous layers are still attached. In future we will disable all
+ // those layer hierarchy code so we won't need this line.
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
+ graphics_layer.CcLayer()->RemoveAllChildren();
+
+ PaintController& paint_controller = context.GetPaintController();
+
+ // This is like ScopedPaintChunkProperties but uses null id because graphics
+ // layer chunk doesn't need an id nor a client.
+ const PropertyTreeState& properties = graphics_layer.GetPropertyTreeState();
+ PropertyTreeState previous_properties(
+ paint_controller.CurrentPaintChunkProperties());
+ paint_controller.UpdateCurrentPaintChunkProperties(nullptr, properties);
+ paint_controller.CreateAndAppend<GraphicsLayerDisplayItem>(graphics_layer);
+ paint_controller.UpdateCurrentPaintChunkProperties(nullptr,
+ previous_properties);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h
new file mode 100644
index 00000000000..2e468dd629c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h
@@ -0,0 +1,47 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GRAPHICS_LAYER_DISPLAY_ITEM_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GRAPHICS_LAYER_DISPLAY_ITEM_H_
+
+#include "cc/layers/layer.h"
+#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+class GraphicsContext;
+class GraphicsLayer;
+
+// Before CompositeAfterPaint, this is a placeholder for a GraphicsLayer
+// allocated before paint. With CompositeAfterPaint, this class will be
+// obsolete and should be removed.
+//
+// Before SquashAfterPaint, a cc::Layer will always be allocated to draw the
+// GraphicsLayer's contents. With SquashAfter Paint, that may not be true; the
+// GraphicsLayer may end up getting squashed by PaintArtifactCompositor.
+class PLATFORM_EXPORT GraphicsLayerDisplayItem final : public DisplayItem {
+ public:
+ GraphicsLayerDisplayItem(const GraphicsLayer&);
+
+ const GraphicsLayer& GetGraphicsLayer() const { return graphics_layer_; }
+
+ // DisplayItem
+ bool Equals(const DisplayItem&) const override;
+#if DCHECK_IS_ON()
+ void PropertiesAsJSON(JSONObject&) const override;
+#endif
+
+ private:
+ const GraphicsLayer& graphics_layer_;
+};
+
+// Records a graphics layer into a GraphicsContext.
+PLATFORM_EXPORT void RecordGraphicsLayer(GraphicsContext& context,
+ const GraphicsLayer& graphics_layer);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GRAPHICS_LAYER_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
index 6e5c25573ad..b5aee1a0c7c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
@@ -9,7 +9,7 @@
namespace blink {
-static String HitTestRectsAsString(const Vector<HitTestRect>& rects) {
+static String TouchActionRectsAsString(const Vector<TouchActionRect>& rects) {
StringBuilder sb;
sb.Append("[");
bool first = true;
@@ -32,22 +32,25 @@ String HitTestData::ToString() const {
bool printed_top_level_field = false;
if (!touch_action_rects.IsEmpty()) {
sb.Append("touch_action_rects: ");
- sb.Append(HitTestRectsAsString(touch_action_rects));
+ sb.Append(TouchActionRectsAsString(touch_action_rects));
printed_top_level_field = true;
}
- if (scroll_hit_test) {
+ if (!scroll_hit_test_rect.IsEmpty()) {
if (printed_top_level_field)
sb.Append(", ");
- sb.AppendFormat(
- "scroll_hit_test: \"%s\" with offset %p",
- scroll_hit_test->scroll_container_bounds.ToString().Utf8().data(),
- scroll_hit_test->scroll_offset);
+ sb.Append("scroll_hit_test_rect: ");
+ sb.Append(scroll_hit_test_rect.ToString());
printed_top_level_field = true;
}
- sb.Append("}");
+ if (scroll_translation) {
+ if (printed_top_level_field)
+ sb.Append(", ");
+ sb.AppendFormat("scroll_translation: %p", scroll_translation);
+ }
+ sb.Append("}");
return sb.ToString();
}
@@ -55,4 +58,8 @@ std::ostream& operator<<(std::ostream& os, const HitTestData& data) {
return os << data.ToString().Utf8();
}
+std::ostream& operator<<(std::ostream& os, const HitTestData* data) {
+ return os << (data ? data->ToString().Utf8() : "null");
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
index 824d9397133..cc785893ca5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
@@ -5,51 +5,35 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_
-#include "third_party/blink/renderer/platform/graphics/hit_test_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/touch_action_rect.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
struct PLATFORM_EXPORT HitTestData {
- Vector<HitTestRect> touch_action_rects;
- struct ScrollHitTest {
- const TransformPaintPropertyNode* scroll_offset;
- IntRect scroll_container_bounds;
- bool operator==(const ScrollHitTest& rhs) const {
- return scroll_offset == rhs.scroll_offset &&
- scroll_container_bounds == rhs.scroll_container_bounds;
- }
- };
- base::Optional<ScrollHitTest> scroll_hit_test;
-
- HitTestData() = default;
- HitTestData(const HitTestData& other)
- : touch_action_rects(other.touch_action_rects),
- scroll_hit_test(other.scroll_hit_test) {}
+ Vector<TouchActionRect> touch_action_rects;
+
+ // If scroll_translation is nullptr or in pre-CompositeAfterPaint, this marks
+ // a region in which composited scroll is not allowed. In CompositeAfterPaint
+ // when scroll_translation is not nullptr, this is the bounds of the scroll
+ // container, and whether the region allows composited scrolling depends
+ // whether the scroll_translation is composited.
+ IntRect scroll_hit_test_rect;
+ const TransformPaintPropertyNode* scroll_translation = nullptr;
bool operator==(const HitTestData& rhs) const {
return touch_action_rects == rhs.touch_action_rects &&
- scroll_hit_test == rhs.scroll_hit_test;
- }
-
- void AppendTouchActionRect(const HitTestRect& rect) {
- touch_action_rects.push_back(rect);
+ scroll_hit_test_rect == rhs.scroll_hit_test_rect &&
+ scroll_translation == rhs.scroll_translation;
}
-
- void SetScrollHitTest(const TransformPaintPropertyNode* scroll_offset,
- const IntRect& scroll_container_bounds) {
- DCHECK(!scroll_offset || scroll_offset->ScrollNode());
- scroll_hit_test = base::make_optional(
- ScrollHitTest{scroll_offset, scroll_container_bounds});
- }
-
bool operator!=(const HitTestData& rhs) const { return !(*this == rhs); }
String ToString() const;
};
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const HitTestData&);
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const HitTestData*);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc
deleted file mode 100644
index 679754ff661..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-void HitTestDisplayItem::Record(GraphicsContext& context,
- const DisplayItemClient& client,
- const HitTestRect& hit_test_rect) {
- auto& paint_controller = context.GetPaintController();
- if (paint_controller.DisplayItemConstructionIsDisabled())
- return;
-
- if (paint_controller.UseCachedItemIfPossible(client, DisplayItem::kHitTest))
- return;
-
- paint_controller.CreateAndAppend<HitTestDisplayItem>(client, hit_test_rect);
-}
-
-#if DCHECK_IS_ON()
-void HitTestDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetString("hitTestRect", hit_test_rect_.ToString());
-}
-#endif
-
-bool HitTestDisplayItem::Equals(const DisplayItem& other) const {
- return DisplayItem::Equals(other) &&
- hit_test_rect_ ==
- static_cast<const HitTestDisplayItem&>(other).hit_test_rect_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
deleted file mode 100644
index cd9a9676def..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-
-#include "third_party/blink/renderer/platform/graphics/hit_test_rect.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-// A special DisplayItem containing hit test data.
-class PLATFORM_EXPORT HitTestDisplayItem final : public DisplayItem {
- public:
- HitTestDisplayItem(const DisplayItemClient& client,
- const HitTestRect& hit_test_rect)
- : DisplayItem(client, kHitTest, sizeof(*this)),
- hit_test_rect_(hit_test_rect) {
- }
-
- const HitTestRect& GetHitTestRect() const { return hit_test_rect_; }
-
- static void Record(GraphicsContext&,
- const DisplayItemClient&,
- const HitTestRect&);
-
- bool Equals(const DisplayItem& other) const final;
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
-
- HitTestRect hit_test_rect_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index 58a1eaa2b76..648cba4ab0b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -7,98 +7,14 @@
#include "cc/paint/display_item_list.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
-#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/skia/include/core/SkRegion.h"
namespace blink {
namespace {
-static SkColor DisplayItemBackgroundColor(const DisplayItem& item) {
- if (item.GetType() != DisplayItem::kBoxDecorationBackground &&
- item.GetType() != DisplayItem::kDocumentBackground)
- return SK_ColorTRANSPARENT;
-
- const auto& drawing_item = static_cast<const DrawingDisplayItem&>(item);
- const auto record = drawing_item.GetPaintRecord();
- if (!record)
- return SK_ColorTRANSPARENT;
-
- for (cc::PaintOpBuffer::Iterator it(record.get()); it; ++it) {
- const auto* op = *it;
- if (op->GetType() == cc::PaintOpType::DrawRect ||
- op->GetType() == cc::PaintOpType::DrawRRect) {
- const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
- // Skip op with looper which may modify the color.
- if (!flags.getLooper() && flags.getStyle() == cc::PaintFlags::kFill_Style)
- return flags.getColor();
- }
- }
- return SK_ColorTRANSPARENT;
-}
-
-void ComputeChunkDerivedData(const DisplayItemList& display_items,
- PaintChunk& chunk) {
- // This happens in tests testing paint chunks without display items.
- if (!chunk.size())
- return;
-
- SkRegion known_to_be_opaque_region;
- auto items = display_items.ItemsInPaintChunk(chunk);
- for (const DisplayItem& item : items) {
- chunk.bounds.Unite(item.VisualRect());
- chunk.outset_for_raster_effects = std::max(chunk.outset_for_raster_effects,
- item.OutsetForRasterEffects());
-
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
- item.IsDrawing()) {
- const auto& drawing = static_cast<const DrawingDisplayItem&>(item);
- if (drawing.GetPaintRecord() && drawing.KnownToBeOpaque()) {
- known_to_be_opaque_region.op(SkIRect(drawing.VisualRect()),
- SkRegion::kUnion_Op);
- }
- }
-
- if (item.IsHitTest()) {
- const auto& hit_test = static_cast<const HitTestDisplayItem&>(item);
- if (!chunk.hit_test_data)
- chunk.hit_test_data = std::make_unique<HitTestData>();
- chunk.hit_test_data->AppendTouchActionRect(hit_test.GetHitTestRect());
- }
-
- // Because ScrollHitTestDisplayItems force new paint chunks (see:
- // PaintChunker::IncrementDisplayItemIndex), they should only be the first
- // item in a paint chunk.
- DCHECK(!item.IsScrollHitTest() || item.Equals(*items.begin()));
- }
-
- // Because ScrollHitTestDisplayItems force new paint chunks (see:
- // PaintChunker::IncrementDisplayItemIndex), they should only be the first
- // item in a paint chunk.
- if (items.begin()->IsScrollHitTest()) {
- const auto& scroll_hit_test_item =
- static_cast<const ScrollHitTestDisplayItem&>(*items.begin());
- if (!chunk.hit_test_data)
- chunk.hit_test_data = std::make_unique<HitTestData>();
- chunk.hit_test_data->SetScrollHitTest(
- scroll_hit_test_item.scroll_offset_node(),
- scroll_hit_test_item.scroll_container_bounds());
- }
-
- if (known_to_be_opaque_region.contains(chunk.bounds))
- chunk.known_to_be_opaque = true;
-
- if (items.begin() != items.end()) {
- chunk.safe_opaque_background_color =
- DisplayItemBackgroundColor(*items.begin());
- }
-}
-
// For PaintArtifact::AppendDebugDrawing().
class DebugDrawingClient final : public DisplayItemClient {
public:
@@ -114,8 +30,6 @@ PaintArtifact::PaintArtifact() : display_item_list_(0) {}
PaintArtifact::PaintArtifact(DisplayItemList display_items,
Vector<PaintChunk> chunks)
: display_item_list_(std::move(display_items)), chunks_(std::move(chunks)) {
- for (auto& chunk : chunks_)
- ComputeChunkDerivedData(display_item_list_, chunk);
}
PaintArtifact::~PaintArtifact() = default;
@@ -153,7 +67,8 @@ void PaintArtifact::AppendDebugDrawing(
// Create a PaintChunk for the debug drawing.
chunks_.emplace_back(display_item_list_.size() - 1, display_item_list_.size(),
display_item.GetId(), property_tree_state);
- ComputeChunkDerivedData(display_item_list_, chunks_.back());
+ chunks_.back().bounds = chunks_.back().drawable_bounds =
+ display_item_list_.Last().VisualRect();
}
void PaintArtifact::Replay(GraphicsContext& graphics_context,
@@ -179,6 +94,18 @@ sk_sp<PaintRecord> PaintArtifact::GetPaintRecord(
->ReleaseAsRecord();
}
+SkColor PaintArtifact::SafeOpaqueBackgroundColor(
+ const PaintChunkSubset& chunks) const {
+ // Find the background color from the first drawing display item.
+ for (const auto& chunk : chunks) {
+ for (const auto& item : display_item_list_.ItemsInPaintChunk(chunk)) {
+ if (item.IsDrawing() && item.DrawsContent())
+ return static_cast<const DrawingDisplayItem&>(item).BackgroundColor();
+ }
+ }
+ return SK_ColorTRANSPARENT;
+}
+
void PaintArtifact::FinishCycle() {
// Until CompositeAfterPaint, PaintController::ClearPropertyTreeChangedStateTo
// is used for clearing the property tree changed state at the end of paint
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
index ee3be027d50..e6b18b20343 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/skia/include/core/SkColor.h"
namespace cc {
class PaintCanvas;
@@ -60,11 +61,6 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
return PaintChunkSubset(PaintChunks(), subset_indices);
}
- Vector<PaintChunk>::const_iterator FindChunkByDisplayItemIndex(
- size_t index) const {
- return FindChunkInVectorByDisplayItemIndex(PaintChunks(), index);
- }
-
// Returns the approximate memory usage, excluding memory likely to be
// shared with the embedder after copying to cc::DisplayItemList.
size_t ApproximateUnsharedMemoryUsage() const;
@@ -86,6 +82,8 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
sk_sp<PaintRecord> GetPaintRecord(const PropertyTreeState& replay_state,
const IntPoint& offset = IntPoint()) const;
+ SkColor SafeOpaqueBackgroundColor(const PaintChunkSubset&) const;
+
// Called when the caller finishes updating a full document life cycle.
// Will cleanup data (e.g. raster invalidations) that will no longer be used
// for the next cycle, and update status to be ready for the next cycle.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
index c5926d2f284..2b14e465929 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
@@ -10,13 +10,13 @@
namespace blink {
struct SameSizeAsPaintChunk {
- size_t begin_index;
- size_t end_index;
+ wtf_size_t begin_index;
+ wtf_size_t end_index;
PaintChunk::Id id;
PropertyTreeState properties;
- FloatRect bounds;
+ IntRect bounds;
+ IntRect drawable_bounds;
float outset_for_raster_effects;
- SkColor safe_opaque_background_color;
unsigned bools; // known_to_be_opaque, is_cacheable, client_is_just_created
void* pointers[1]; // hit_test_data
};
@@ -24,10 +24,34 @@ struct SameSizeAsPaintChunk {
static_assert(sizeof(PaintChunk) == sizeof(SameSizeAsPaintChunk),
"PaintChunk should stay small");
+bool PaintChunk::EqualsForUnderInvalidationChecking(
+ const PaintChunk& other) const {
+ return size() == other.size() && id == other.id &&
+ properties == other.properties && bounds == other.bounds &&
+ drawable_bounds == other.drawable_bounds &&
+ outset_for_raster_effects == other.outset_for_raster_effects &&
+ ((!hit_test_data && !other.hit_test_data) ||
+ (hit_test_data && other.hit_test_data &&
+ *hit_test_data == *other.hit_test_data));
+ // known_to_be_opaque is not checked because it's updated when we create the
+ // next chunk or release chunks. We ensure its correctness with unit tests and
+ // under-invalidation checking of display items.
+}
+
+size_t PaintChunk::MemoryUsageInBytes() const {
+ size_t total_size = sizeof(*this);
+ if (hit_test_data) {
+ total_size += sizeof(*hit_test_data);
+ total_size +=
+ hit_test_data->touch_action_rects.capacity() * sizeof(TouchActionRect);
+ }
+ return total_size;
+}
+
String PaintChunk::ToString() const {
StringBuilder sb;
sb.AppendFormat(
- "PaintChunk(begin=%zu, end=%zu, id=%s cacheable=%d props=(%s) bounds=%s "
+ "PaintChunk(begin=%u, end=%u, id=%s cacheable=%d props=(%s) bounds=%s "
"known_to_be_opaque=%d",
begin_index, end_index, id.ToString().Utf8().c_str(), is_cacheable,
properties.ToString().Utf8().c_str(), bounds.ToString().Utf8().c_str(),
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
index 2024df32a40..277bc25e0cc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
@@ -28,8 +28,8 @@ struct PLATFORM_EXPORT PaintChunk {
using Id = DisplayItem::Id;
- PaintChunk(size_t begin,
- size_t end,
+ PaintChunk(wtf_size_t begin,
+ wtf_size_t end,
const Id& id,
const PropertyTreeState& props)
: begin_index(begin),
@@ -39,7 +39,27 @@ struct PLATFORM_EXPORT PaintChunk {
is_cacheable(id.client.IsCacheable()),
client_is_just_created(id.client.IsJustCreated()) {}
- size_t size() const {
+ // Move a paint chunk from a cached subsequence.
+ PaintChunk(wtf_size_t begin, PaintChunk&& other)
+ : begin_index(begin),
+ end_index(begin + other.size()),
+ id(other.id),
+ properties(other.properties),
+ hit_test_data(std::move(other.hit_test_data)),
+ bounds(other.bounds),
+ drawable_bounds(other.drawable_bounds),
+ outset_for_raster_effects(other.outset_for_raster_effects),
+ known_to_be_opaque(other.known_to_be_opaque),
+ is_cacheable(other.is_cacheable),
+ client_is_just_created(false),
+ is_moved_from_cached_subsequence(true) {
+#if DCHECK_IS_ON()
+ DCHECK(other.id.client.IsAlive());
+ DCHECK(!other.id.client.IsJustCreated());
+#endif
+ }
+
+ wtf_size_t size() const {
DCHECK_GE(end_index, begin_index);
return end_index - begin_index;
}
@@ -63,24 +83,24 @@ struct PLATFORM_EXPORT PaintChunk {
return !client_is_just_created;
}
- size_t MemoryUsageInBytes() const {
- size_t total_size = sizeof(*this);
- if (hit_test_data) {
- total_size += sizeof(*hit_test_data);
- total_size +=
- hit_test_data->touch_action_rects.capacity() * sizeof(HitTestRect);
- }
- return total_size;
+ bool EqualsForUnderInvalidationChecking(const PaintChunk& other) const;
+
+ HitTestData& EnsureHitTestData() {
+ if (!hit_test_data)
+ hit_test_data = std::make_unique<HitTestData>();
+ return *hit_test_data;
}
+ size_t MemoryUsageInBytes() const;
+
String ToString() const;
// Index of the first drawing in this chunk.
- size_t begin_index;
+ wtf_size_t begin_index;
// Index of the first drawing not in this chunk, so that there are
// |endIndex - beginIndex| drawings in the chunk.
- size_t end_index;
+ wtf_size_t end_index;
// Identifier of this chunk. It should be unique if |is_cacheable| is true.
// This is used to match a new chunk to a cached old chunk to track changes
@@ -90,23 +110,27 @@ struct PLATFORM_EXPORT PaintChunk {
// The paint properties which apply to this chunk.
RefCountedPropertyTreeState properties;
- // The following fields are not initialized when the chunk is created because
- // they depend on the display items in this chunk. They are updated by the
- // constructor of PaintArtifact.
-
std::unique_ptr<HitTestData> hit_test_data;
- // The total bounds of this paint chunk's contents, in the coordinate space of
- // the containing transform node.
+ // The following fields depend on the display items in this chunk.
+ // They are updated when a display item is added into the chunk.
+
+ // The total bounds of visual rects of all display items in this paint chunk,
+ // and extra bounds that are not from display items for e.g. hit test.
+ // It's in the coordinate space of the containing transform node. This can be
+ // larger than |drawble_bounds|, because of non-drawable display items and
+ // extra bounds.
IntRect bounds;
+ // The total bounds of visual rects of drawable display items in this paint
+ // chunk.
+ IntRect drawable_bounds;
+
// Some raster effects can exceed |bounds| in the rasterization space. This
// is the maximum DisplayItemClient::VisualRectOutsetForRasterEffects() of
// all clients of items in this chunk.
float outset_for_raster_effects = 0;
- SkColor safe_opaque_background_color = 0;
-
// True if the bounds are filled entirely with opaque contents.
bool known_to_be_opaque = false;
@@ -114,29 +138,9 @@ struct PLATFORM_EXPORT PaintChunk {
// The following fields are put here to avoid memory gap.
bool is_cacheable;
bool client_is_just_created;
+ bool is_moved_from_cached_subsequence = false;
};
-inline bool ChunkLessThanIndex(const PaintChunk& chunk, size_t index) {
- return chunk.end_index <= index;
-}
-
-inline Vector<PaintChunk>::iterator FindChunkInVectorByDisplayItemIndex(
- Vector<PaintChunk>& chunks,
- size_t index) {
- auto* chunk =
- std::lower_bound(chunks.begin(), chunks.end(), index, ChunkLessThanIndex);
- DCHECK(chunk == chunks.end() ||
- (index >= chunk->begin_index && index < chunk->end_index));
- return chunk;
-}
-
-inline Vector<PaintChunk>::const_iterator FindChunkInVectorByDisplayItemIndex(
- const Vector<PaintChunk>& chunks,
- size_t index) {
- return FindChunkInVectorByDisplayItemIndex(
- const_cast<Vector<PaintChunk>&>(chunks), index);
-}
-
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const PaintChunk&);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
index 7c9f1c75117..c28b7285818 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
@@ -42,7 +42,7 @@ class PaintChunkSubset {
}
// The index in the whole paint chunks set.
- size_t OriginalIndex() const { return subset_.OriginalIndex(offset_); }
+ wtf_size_t OriginalIndex() const { return subset_.OriginalIndex(offset_); }
private:
friend class PaintChunkSubset;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
index 67168a48af8..8766927440c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
@@ -4,11 +4,13 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunker.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
+
namespace blink {
PaintChunker::PaintChunker()
: current_properties_(PropertyTreeState::Uninitialized()),
- force_new_chunk_(false) {}
+ force_new_chunk_(true) {}
PaintChunker::~PaintChunker() = default;
@@ -23,7 +25,7 @@ bool PaintChunker::IsInInitialState() const {
#endif
void PaintChunker::UpdateCurrentPaintChunkProperties(
- const base::Optional<PaintChunk::Id>& chunk_id,
+ const PaintChunk::Id* chunk_id,
const PropertyTreeState& properties) {
// If properties are the same, continue to use the previously set
// |next_chunk_id_| because the id of the outer painting is likely to be
@@ -37,14 +39,14 @@ void PaintChunker::UpdateCurrentPaintChunkProperties(
current_properties_ = properties;
}
-void PaintChunker::ForceNewChunk() {
- force_new_chunk_ = true;
- // Always use a new chunk id for a force chunk which may be for a subsequence
- // which needs the chunk id to be independence with previous chunks.
- next_chunk_id_ = base::nullopt;
+void PaintChunker::AppendByMoving(PaintChunk&& chunk) {
+ UpdateLastChunkKnownToBeOpaque();
+ wtf_size_t next_chunk_begin_index =
+ chunks_.IsEmpty() ? 0 : LastChunk().end_index;
+ chunks_.emplace_back(next_chunk_begin_index, std::move(chunk));
}
-bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
+PaintChunk& PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) {
#if DCHECK_IS_ON()
// If this DCHECKs are hit we are missing a call to update the properties.
// See: ScopedPaintChunkProperties.
@@ -53,47 +55,118 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
DCHECK(current_properties_.IsInitialized());
#endif
- bool item_forces_new_chunk =
- item.IsForeignLayer() || item.IsScrollHitTest() || item.IsScrollbar();
+ if (WillForceNewChunk() || current_properties_ != LastChunk().properties) {
+ if (!next_chunk_id_)
+ next_chunk_id_.emplace(id);
+ UpdateLastChunkKnownToBeOpaque();
+ wtf_size_t begin = chunks_.IsEmpty() ? 0 : LastChunk().end_index;
+ chunks_.emplace_back(begin, begin, *next_chunk_id_, current_properties_);
+ next_chunk_id_ = base::nullopt;
+ force_new_chunk_ = false;
+ }
+ return LastChunk();
+}
+
+bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
+ bool item_forces_new_chunk = item.IsForeignLayer() ||
+ item.IsGraphicsLayerWrapper() ||
+ item.IsScrollbar();
+ if (item_forces_new_chunk)
+ SetForceNewChunk(true);
+
+ auto previous_size = size();
+ auto& chunk = EnsureCurrentChunk(item.GetId());
+ bool created_new_chunk = size() > previous_size;
+
+ chunk.bounds.Unite(item.VisualRect());
+ if (item.DrawsContent())
+ chunk.drawable_bounds.Unite(item.VisualRect());
+
+ constexpr wtf_size_t kMaxRegionComplexity = 10;
+ if (item.IsDrawing() &&
+ static_cast<const DrawingDisplayItem&>(item).KnownToBeOpaque() &&
+ last_chunk_known_to_be_opaque_region_.Complexity() < kMaxRegionComplexity)
+ last_chunk_known_to_be_opaque_region_.Unite(item.VisualRect());
+
+ chunk.outset_for_raster_effects =
+ std::max(chunk.outset_for_raster_effects, item.OutsetForRasterEffects());
+
+ chunk.end_index++;
+
+ // When forcing a new chunk, we still need to force new chunk for the next
+ // display item. Otherwise reset force_new_chunk_ to false.
+ DCHECK(!force_new_chunk_);
if (item_forces_new_chunk) {
- force_new_chunk_ = true;
- next_chunk_id_.emplace(item.GetId());
+ DCHECK(created_new_chunk);
+ SetForceNewChunk(true);
+ }
+
+ return created_new_chunk;
+}
+
+void PaintChunker::AddHitTestDataToCurrentChunk(const PaintChunk::Id& id,
+ const IntRect& rect,
+ TouchAction touch_action) {
+ // In CompositeAfterPaint, we ensure a paint chunk for correct composited
+ // hit testing. In pre-CompositeAfterPaint, this is unnecessary, except that
+ // there is special touch action, and that we have a non-root effect so that
+ // PaintChunksToCcLayer will emit paint operations for filters.
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ touch_action == TouchAction::kAuto &&
+ &current_properties_.Effect() == &EffectPaintPropertyNode::Root())
+ return;
+
+ auto& chunk = EnsureCurrentChunk(id);
+ chunk.bounds.Unite(rect);
+ if (touch_action != TouchAction::kAuto) {
+ chunk.EnsureHitTestData().touch_action_rects.push_back(
+ TouchActionRect{rect, touch_action});
}
+}
- size_t new_chunk_begin_index;
- if (chunks_.IsEmpty()) {
- new_chunk_begin_index = 0;
+void PaintChunker::CreateScrollHitTestChunk(
+ const PaintChunk::Id& id,
+ const TransformPaintPropertyNode* scroll_translation,
+ const IntRect& rect) {
+#if DCHECK_IS_ON()
+ if (id.type == DisplayItem::Type::kResizerScrollHitTest ||
+ id.type == DisplayItem::Type::kPluginScrollHitTest) {
+ // Resizer and plugin scroll hit tests are only used to prevent composited
+ // scrolling and should not have a scroll offset node.
+ DCHECK(!scroll_translation);
+ } else if (id.type == DisplayItem::Type::kScrollHitTest) {
+ DCHECK(scroll_translation);
+ // The scroll offset transform node should have an associated scroll node.
+ DCHECK(scroll_translation->ScrollNode());
} else {
- auto& last_chunk = LastChunk();
- if (!force_new_chunk_ && current_properties_ == last_chunk.properties) {
- // Continue the current chunk.
- last_chunk.end_index++;
- // We don't create a new chunk when UpdateCurrentPaintChunkProperties()
- // just changed |next_chunk_id_| but not |current_properties_|. Clear
- // |next_chunk_id_| which has been ignored.
- next_chunk_id_ = base::nullopt;
- return false;
- }
- new_chunk_begin_index = last_chunk.end_index;
+ NOTREACHED();
}
+#endif
- chunks_.emplace_back(new_chunk_begin_index, new_chunk_begin_index + 1,
- next_chunk_id_ ? *next_chunk_id_ : item.GetId(),
- current_properties_);
- next_chunk_id_ = base::nullopt;
+ SetForceNewChunk(true);
+ auto& chunk = EnsureCurrentChunk(id);
+ chunk.bounds.Unite(rect);
+ auto& hit_test_data = chunk.EnsureHitTestData();
+ hit_test_data.scroll_translation = scroll_translation;
+ hit_test_data.scroll_hit_test_rect = rect;
+ SetForceNewChunk(true);
+}
- // When forcing a new chunk, we still need to force new chunk for the next
- // display item. Otherwise reset force_new_chunk_ to false.
- if (!item_forces_new_chunk)
- force_new_chunk_ = false;
+void PaintChunker::UpdateLastChunkKnownToBeOpaque() {
+ if (chunks_.IsEmpty() || LastChunk().is_moved_from_cached_subsequence)
+ return;
- return true;
+ LastChunk().known_to_be_opaque =
+ last_chunk_known_to_be_opaque_region_.Contains(LastChunk().bounds);
+ last_chunk_known_to_be_opaque_region_ = Region();
}
Vector<PaintChunk> PaintChunker::ReleasePaintChunks() {
+ UpdateLastChunkKnownToBeOpaque();
next_chunk_id_ = base::nullopt;
current_properties_ = PropertyTreeState::Uninitialized();
chunks_.ShrinkToFit();
+ force_new_chunk_ = true;
return std::move(chunks_);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
index c65ebe79e87..2b2dcdb57be 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/optional.h"
+#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
@@ -34,38 +35,50 @@ class PLATFORM_EXPORT PaintChunker final {
const PropertyTreeState& CurrentPaintChunkProperties() const {
return current_properties_;
}
- void UpdateCurrentPaintChunkProperties(const base::Optional<PaintChunk::Id>&,
+ void UpdateCurrentPaintChunkProperties(const PaintChunk::Id*,
const PropertyTreeState&);
- void ForceNewChunk();
+ // Sets the forcing new chunk status on or off. If the status is on, even the
+ // properties haven't change, we'll force a new paint chunk for the next
+ // display item and then automatically resets the status. Some special display
+ // item (e.g. ForeignLayerDisplayItem) also automatically sets the status on
+ // before and after the item to force a dedicated paint chunk.
+ void SetForceNewChunk(bool force) {
+ force_new_chunk_ = force;
+ next_chunk_id_ = base::nullopt;
+ }
+ bool WillForceNewChunk() const {
+ return force_new_chunk_ || chunks_.IsEmpty();
+ }
+
+ void AppendByMoving(PaintChunk&&);
// Returns true if a new chunk is created.
bool IncrementDisplayItemIndex(const DisplayItem&);
const Vector<PaintChunk>& PaintChunks() const { return chunks_; }
+ wtf_size_t size() const { return chunks_.size(); }
- PaintChunk& PaintChunkAt(wtf_size_t i) { return chunks_[i]; }
- wtf_size_t LastChunkIndex() const {
- return chunks_.IsEmpty() ? kNotFound : chunks_.size() - 1;
- }
PaintChunk& LastChunk() { return chunks_.back(); }
-
- PaintChunk& FindChunkByDisplayItemIndex(size_t index) {
- auto* chunk = FindChunkInVectorByDisplayItemIndex(chunks_, index);
- DCHECK(chunk != chunks_.end());
- return *chunk;
- }
+ const PaintChunk& LastChunk() const { return chunks_.back(); }
+
+ // The id will be used when we need to create a new current chunk.
+ // Otherwise it's ignored.
+ void AddHitTestDataToCurrentChunk(const PaintChunk::Id&,
+ const IntRect&,
+ TouchAction);
+ void CreateScrollHitTestChunk(
+ const PaintChunk::Id&,
+ const TransformPaintPropertyNode* scroll_translation,
+ const IntRect&);
// Releases the generated paint chunk list and raster invalidations and
// resets the state of this object.
Vector<PaintChunk> ReleasePaintChunks();
private:
- size_t ChunkIndex(const PaintChunk& chunk) const {
- size_t index = &chunk - &chunks_.front();
- DCHECK_LT(index, chunks_.size());
- return index;
- }
+ PaintChunk& EnsureCurrentChunk(const PaintChunk::Id&);
+ void UpdateLastChunkKnownToBeOpaque();
Vector<PaintChunk> chunks_;
@@ -79,6 +92,8 @@ class PLATFORM_EXPORT PaintChunker final {
PropertyTreeState current_properties_;
+ Region last_chunk_known_to_be_opaque_region_;
+
// True when an item forces a new chunk (e.g., foreign display items), and for
// the item following a forced chunk. PaintController also forces new chunks
// before and after subsequences by calling ForceNewChunk().
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
index 38c19a5348b..d474d4ea698 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
@@ -6,8 +6,12 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
+#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
using testing::ElementsAre;
@@ -17,28 +21,43 @@ namespace {
class PaintChunkerTest : public testing::Test {
protected:
- class TestDisplayItemClient : public DisplayItemClient {
- String DebugName() const final { return "Test"; }
- IntRect VisualRect() const final { return IntRect(); }
- };
- TestDisplayItemClient client_;
+ FakeDisplayItemClient client_;
};
DisplayItem::Type DisplayItemType(int offset) {
- return static_cast<DisplayItem::Type>(DisplayItem::kDrawingFirst + offset);
+ auto type =
+ static_cast<DisplayItem::Type>(DisplayItem::kDrawingFirst + offset);
+ DCHECK(DisplayItem::IsDrawingType(type));
+ return type;
}
-class TestChunkerDisplayItem : public DisplayItem {
+class TestChunkerDisplayItem : public DrawingDisplayItem {
public:
- TestChunkerDisplayItem(const DisplayItemClient& client,
- DisplayItem::Type type = DisplayItem::kDrawingFirst)
- : DisplayItem(client, type, sizeof(*this)) {}
+ explicit TestChunkerDisplayItem(
+ const DisplayItemClient& client,
+ DisplayItem::Type type = DisplayItem::kDrawingFirst)
+ : DrawingDisplayItem(client, type, nullptr) {}
};
-class TestDisplayItemRequiringSeparateChunk : public TestChunkerDisplayItem {
+class TestChunkerOpaqueDisplayItem : public DrawingDisplayItem {
public:
- TestDisplayItemRequiringSeparateChunk(const DisplayItemClient& client)
- : TestChunkerDisplayItem(client, DisplayItem::kForeignLayerPlugin) {}
+ explicit TestChunkerOpaqueDisplayItem(
+ const DisplayItemClient& client,
+ DisplayItem::Type type = DisplayItem::kDrawingFirst)
+ : DrawingDisplayItem(client, type, nullptr) {
+ SetKnownToBeOpaqueForTesting();
+ }
+};
+
+class TestDisplayItemRequiringSeparateChunk : public ForeignLayerDisplayItem {
+ public:
+ explicit TestDisplayItemRequiringSeparateChunk(
+ const DisplayItemClient& client)
+ : ForeignLayerDisplayItem(client,
+ DisplayItem::kForeignLayerPlugin,
+ cc::Layer::Create(),
+ FloatPoint(),
+ nullptr) {}
};
TEST_F(PaintChunkerTest, Empty) {
@@ -52,7 +71,7 @@ TEST_F(PaintChunkerTest, Empty) {
TEST_F(PaintChunkerTest, SingleNonEmptyRange) {
PaintChunker chunker;
PaintChunk::Id id(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id, DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -69,10 +88,10 @@ TEST_F(PaintChunkerTest, SingleNonEmptyRange) {
TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk) {
PaintChunker chunker;
PaintChunk::Id id(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id, DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
- chunker.UpdateCurrentPaintChunkProperties(id, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id, DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
const auto& chunks = chunker.PaintChunks();
@@ -88,7 +107,8 @@ TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk) {
TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
PaintChunker chunker;
PaintChunk::Id id1(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -98,7 +118,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
simple_transform.SetTransform(*simple_transform_node);
PaintChunk::Id id2(client_, DisplayItemType(2));
- chunker.UpdateCurrentPaintChunkProperties(id2, simple_transform);
+ chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto another_transform_node = CreateTransform(
@@ -106,7 +126,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
auto another_transform = DefaultPaintChunkProperties();
another_transform.SetTransform(*another_transform_node);
PaintChunk::Id id3(client_, DisplayItemType(3));
- chunker.UpdateCurrentPaintChunkProperties(id3, another_transform);
+ chunker.UpdateCurrentPaintChunkProperties(&id3, another_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
EXPECT_THAT(
@@ -119,7 +139,8 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
PaintChunker chunker;
PaintChunk::Id id1(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto simple_transform_node = CreateTransform(
@@ -127,7 +148,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(*simple_transform_node);
PaintChunk::Id id2(client_, DisplayItemType(2));
- chunker.UpdateCurrentPaintChunkProperties(id2, simple_transform);
+ chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -136,7 +157,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
simple_transform_and_effect.SetTransform(*simple_transform_node);
simple_transform_and_effect.SetEffect(*simple_effect_node);
PaintChunk::Id id3(client_, DisplayItemType(3));
- chunker.UpdateCurrentPaintChunkProperties(id3, simple_transform_and_effect);
+ chunker.UpdateCurrentPaintChunkProperties(&id3, simple_transform_and_effect);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -151,13 +172,13 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
*new_effect_node);
PaintChunk::Id id4(client_, DisplayItemType(4));
chunker.UpdateCurrentPaintChunkProperties(
- id4, simple_transform_and_effect_with_updated_transform);
+ &id4, simple_transform_and_effect_with_updated_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
// Test that going back to a previous chunk property still creates a new
// chunk.
- chunker.UpdateCurrentPaintChunkProperties(base::nullopt,
+ chunker.UpdateCurrentPaintChunkProperties(nullptr,
simple_transform_and_effect);
TestChunkerDisplayItem item_after_restore(client_, DisplayItemType(10));
chunker.IncrementDisplayItemIndex(item_after_restore);
@@ -187,7 +208,8 @@ TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms) {
// </root xform>
PaintChunker chunker;
PaintChunk::Id id1(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto simple_transform_node = CreateTransform(
@@ -195,11 +217,11 @@ TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms) {
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(*simple_transform_node);
PaintChunk::Id id2(client_, DisplayItemType(2));
- chunker.UpdateCurrentPaintChunkProperties(id2, simple_transform);
+ chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
- chunker.UpdateCurrentPaintChunkProperties(base::nullopt,
+ chunker.UpdateCurrentPaintChunkProperties(nullptr,
DefaultPaintChunkProperties());
TestChunkerDisplayItem item_after_restore(client_, DisplayItemType(10));
chunker.IncrementDisplayItemIndex(item_after_restore);
@@ -216,7 +238,8 @@ TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems) {
// Test that properties can change without display items being generated.
PaintChunker chunker;
PaintChunk::Id id1(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto first_transform_node = CreateTransform(
@@ -224,14 +247,14 @@ TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems) {
auto first_transform = DefaultPaintChunkProperties();
first_transform.SetTransform(*first_transform_node);
PaintChunk::Id id2(client_, DisplayItemType(2));
- chunker.UpdateCurrentPaintChunkProperties(base::nullopt, first_transform);
+ chunker.UpdateCurrentPaintChunkProperties(nullptr, first_transform);
auto second_transform_node = CreateTransform(
t0(), TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
auto second_transform = DefaultPaintChunkProperties();
second_transform.SetTransform(*second_transform_node);
PaintChunk::Id id3(client_, DisplayItemType(3));
- chunker.UpdateCurrentPaintChunkProperties(id3, second_transform);
+ chunker.UpdateCurrentPaintChunkProperties(&id3, second_transform);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
EXPECT_THAT(
@@ -244,22 +267,24 @@ TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested) {
// Tests that the chunker creates a separate chunks for display items which
// require it.
PaintChunker chunker;
- TestDisplayItemClient client1;
+ FakeDisplayItemClient client1;
TestDisplayItemRequiringSeparateChunk i1(client1);
- TestDisplayItemClient client2;
+ FakeDisplayItemClient client2;
TestDisplayItemRequiringSeparateChunk i2(client2);
- TestDisplayItemClient client3;
+ FakeDisplayItemClient client3;
TestDisplayItemRequiringSeparateChunk i3(client3);
PaintChunk::Id id0(client_, DisplayItemType(0));
- chunker.UpdateCurrentPaintChunkProperties(id0, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id0,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(i1);
chunker.IncrementDisplayItemIndex(i2);
TestChunkerDisplayItem after_i2(client_, DisplayItemType(10));
chunker.IncrementDisplayItemIndex(after_i2);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
- chunker.UpdateCurrentPaintChunkProperties(id0, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id0,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(i3);
EXPECT_THAT(
@@ -275,20 +300,36 @@ TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested) {
TEST_F(PaintChunkerTest, ForceNewChunkWithNewId) {
PaintChunker chunker;
PaintChunk::Id id0(client_, DisplayItemType(0));
- chunker.UpdateCurrentPaintChunkProperties(id0, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id0,
+ DefaultPaintChunkProperties());
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ EXPECT_EQ(0u, chunker.size());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ EXPECT_FALSE(chunker.WillForceNewChunk());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ EXPECT_EQ(1u, chunker.size());
- chunker.ForceNewChunk();
- PaintChunk::Id id1(client_, DisplayItemType(10));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.SetForceNewChunk(true);
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ EXPECT_EQ(1u, chunker.size());
+ PaintChunk::Id id1(client_, DisplayItemType(1));
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ EXPECT_EQ(2u, chunker.size());
+ EXPECT_FALSE(chunker.WillForceNewChunk());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ EXPECT_EQ(2u, chunker.size());
- chunker.ForceNewChunk();
- PaintChunk::Id id2(client_, DisplayItemType(20));
- chunker.UpdateCurrentPaintChunkProperties(id2, DefaultPaintChunkProperties());
+ chunker.SetForceNewChunk(true);
+ PaintChunk::Id id2(client_, DisplayItemType(2));
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ chunker.UpdateCurrentPaintChunkProperties(&id2,
+ DefaultPaintChunkProperties());
+ EXPECT_EQ(2u, chunker.size());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+ EXPECT_EQ(3u, chunker.size());
+ EXPECT_FALSE(chunker.WillForceNewChunk());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
EXPECT_THAT(
@@ -301,25 +342,37 @@ TEST_F(PaintChunkerTest, ForceNewChunkWithNewId) {
TEST_F(PaintChunkerTest, ForceNewChunkWithoutNewId) {
PaintChunker chunker;
PaintChunk::Id id0(client_, DisplayItemType(0));
- chunker.UpdateCurrentPaintChunkProperties(base::nullopt,
+ chunker.UpdateCurrentPaintChunkProperties(nullptr,
DefaultPaintChunkProperties());
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ EXPECT_EQ(0u, chunker.size());
chunker.IncrementDisplayItemIndex(
TestChunkerDisplayItem(id0.client, id0.type));
+ EXPECT_FALSE(chunker.WillForceNewChunk());
+ EXPECT_EQ(1u, chunker.size());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
- chunker.ForceNewChunk();
- PaintChunk::Id id1(client_, DisplayItemType(10));
+ chunker.SetForceNewChunk(true);
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ EXPECT_EQ(1u, chunker.size());
+ PaintChunk::Id id1(client_, DisplayItemType(1));
chunker.IncrementDisplayItemIndex(
TestChunkerDisplayItem(id1.client, id1.type));
+ EXPECT_FALSE(chunker.WillForceNewChunk());
+ EXPECT_EQ(2u, chunker.size());
chunker.IncrementDisplayItemIndex(
- TestChunkerDisplayItem(client_, DisplayItemType(11)));
+ TestChunkerDisplayItem(client_, DisplayItemType(2)));
- chunker.ForceNewChunk();
- PaintChunk::Id id2(client_, DisplayItemType(20));
+ chunker.SetForceNewChunk(true);
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ EXPECT_EQ(2u, chunker.size());
+ PaintChunk::Id id2(client_, DisplayItemType(3));
chunker.IncrementDisplayItemIndex(
TestChunkerDisplayItem(id2.client, id2.type));
+ EXPECT_FALSE(chunker.WillForceNewChunk());
+ EXPECT_EQ(3u, chunker.size());
chunker.IncrementDisplayItemIndex(
- TestChunkerDisplayItem(client_, DisplayItemType(21)));
+ TestChunkerDisplayItem(client_, DisplayItemType(4)));
EXPECT_THAT(
chunker.PaintChunks(),
@@ -328,19 +381,48 @@ TEST_F(PaintChunkerTest, ForceNewChunkWithoutNewId) {
IsPaintChunk(4, 6, id2, DefaultPaintChunkProperties())));
}
+TEST_F(PaintChunkerTest, SetAndImmediatelyUnsetForceNewChunk) {
+ PaintChunker chunker;
+ PaintChunk::Id id0(client_, DisplayItemType(0));
+ chunker.UpdateCurrentPaintChunkProperties(nullptr,
+ DefaultPaintChunkProperties());
+ EXPECT_TRUE(chunker.WillForceNewChunk());
+ EXPECT_EQ(0u, chunker.size());
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(id0.client, id0.type));
+ EXPECT_FALSE(chunker.WillForceNewChunk());
+ EXPECT_EQ(1u, chunker.size());
+ chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
+
+ // This should not force a new chunk. Simulates a ScopedPaintChunkHint
+ // without any painting in the scope.
+ chunker.SetForceNewChunk(true);
+ chunker.SetForceNewChunk(false);
+ EXPECT_FALSE(chunker.WillForceNewChunk());
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client_, DisplayItemType(1)));
+ EXPECT_EQ(1u, chunker.size());
+
+ EXPECT_THAT(
+ chunker.PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 3, id0, DefaultPaintChunkProperties())));
+}
+
TEST_F(PaintChunkerTest, NoNewChunkForSamePropertyDifferentIds) {
PaintChunker chunker;
PaintChunk::Id id0(client_, DisplayItemType(0));
- chunker.UpdateCurrentPaintChunkProperties(id0, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id0,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
PaintChunk::Id id1(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
- chunker.UpdateCurrentPaintChunkProperties(base::nullopt,
+ chunker.UpdateCurrentPaintChunkProperties(nullptr,
DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -350,29 +432,24 @@ TEST_F(PaintChunkerTest, NoNewChunkForSamePropertyDifferentIds) {
ElementsAre(IsPaintChunk(0, 6, id0, DefaultPaintChunkProperties())));
}
-class TestScrollHitTestRequiringSeparateChunk : public TestChunkerDisplayItem {
- public:
- TestScrollHitTestRequiringSeparateChunk(const DisplayItemClient& client)
- : TestChunkerDisplayItem(client, DisplayItem::kScrollHitTest) {}
-};
-
// Ensure that items following a forced chunk begin using the next display
// item's id.
TEST_F(PaintChunkerTest, ChunksFollowingForcedChunk) {
PaintChunker chunker;
- TestDisplayItemClient client;
- TestChunkerDisplayItem before_forced1(client, DisplayItemType(9));
- TestChunkerDisplayItem before_forced2(client, DisplayItemType(10));
- TestScrollHitTestRequiringSeparateChunk forced(client);
- TestChunkerDisplayItem after_forced1(client, DisplayItemType(11));
- TestChunkerDisplayItem after_forced2(client, DisplayItemType(12));
-
- PaintChunk::Id id0(client, DisplayItemType(8));
- chunker.UpdateCurrentPaintChunkProperties(id0, DefaultPaintChunkProperties());
+ FakeDisplayItemClient client;
+ TestChunkerDisplayItem before_forced1(client, DisplayItemType(1));
+ TestChunkerDisplayItem before_forced2(client, DisplayItemType(2));
+ TestDisplayItemRequiringSeparateChunk forced(client);
+ TestChunkerDisplayItem after_forced1(client, DisplayItemType(3));
+ TestChunkerDisplayItem after_forced2(client, DisplayItemType(4));
+
+ PaintChunk::Id id0(client, DisplayItemType(5));
+ chunker.UpdateCurrentPaintChunkProperties(&id0,
+ DefaultPaintChunkProperties());
// Both before_forced items should be in a chunk together.
chunker.IncrementDisplayItemIndex(before_forced1);
chunker.IncrementDisplayItemIndex(before_forced2);
- // The forced scroll hit test item should be in its own chunk.
+ // |forced| forces a dedicted paint chunk.
chunker.IncrementDisplayItemIndex(forced);
// Both after_forced items should be in a chunk together.
chunker.IncrementDisplayItemIndex(after_forced1);
@@ -391,7 +468,8 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
PaintChunker chunker;
PaintChunk::Id id1(client_, DisplayItemType(1));
- chunker.UpdateCurrentPaintChunkProperties(id1, DefaultPaintChunkProperties());
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
@@ -400,10 +478,10 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(*simple_transform_node);
- TestDisplayItemClient uncacheable_client;
+ FakeDisplayItemClient uncacheable_client;
uncacheable_client.Invalidate(PaintInvalidationReason::kUncacheable);
PaintChunk::Id id2(uncacheable_client, DisplayItemType(2));
- chunker.UpdateCurrentPaintChunkProperties(id2, simple_transform);
+ chunker.UpdateCurrentPaintChunkProperties(&id2, simple_transform);
TestChunkerDisplayItem uncacheable_item(uncacheable_client);
chunker.IncrementDisplayItemIndex(uncacheable_item);
@@ -416,7 +494,7 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
TestChunkerDisplayItem after_separate_chunk(client_, DisplayItemType(3));
chunker.IncrementDisplayItemIndex(after_separate_chunk);
- chunker.UpdateCurrentPaintChunkProperties(base::nullopt,
+ chunker.UpdateCurrentPaintChunkProperties(nullptr,
DefaultPaintChunkProperties());
TestChunkerDisplayItem after_restore(client_, DisplayItemType(4));
chunker.IncrementDisplayItemIndex(after_restore);
@@ -439,5 +517,205 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
EXPECT_TRUE(chunks[4].is_cacheable);
}
+TEST_F(PaintChunkerTest, AddHitTestDataToCurrentChunk) {
+ PaintChunker chunker;
+ client_.SetVisualRect(IntRect(0, 0, 10, 10));
+
+ PaintChunk::Id id1(client_, DisplayItemType(1));
+
+ chunker.UpdateCurrentPaintChunkProperties(&id1,
+ DefaultPaintChunkProperties());
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client_, DisplayItemType(2)));
+
+ PaintChunk::Id id2(client_, DisplayItemType(3));
+ auto transform = Create2DTranslation(t0(), 10, 20);
+ PropertyTreeState properties(*transform, c0(), e0());
+ chunker.UpdateCurrentPaintChunkProperties(&id2, properties);
+ // This is not used as id of the chunk because we already have |id2|.
+ PaintChunk::Id hit_test_id(client_, DisplayItem::kHitTest);
+ chunker.AddHitTestDataToCurrentChunk(hit_test_id, IntRect(10, 20, 30, 40),
+ TouchAction::kAuto);
+ chunker.AddHitTestDataToCurrentChunk(hit_test_id, IntRect(20, 30, 40, 50),
+ TouchAction::kPan);
+
+ chunker.SetForceNewChunk(true);
+ PaintChunk::Id id3(client_, DisplayItemType(4));
+ chunker.AddHitTestDataToCurrentChunk(id3, IntRect(40, 50, 60, 70),
+ TouchAction::kAuto);
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client_, DisplayItemType(5)));
+
+ HitTestData hit_test_data;
+ hit_test_data.touch_action_rects = {
+ {IntRect(20, 30, 40, 50), TouchAction::kPan}};
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_THAT(
+ chunker.PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, id1, DefaultPaintChunkProperties(),
+ nullptr, IntRect(0, 0, 10, 10)),
+ IsPaintChunk(1, 1, id2, properties, &hit_test_data,
+ IntRect(10, 20, 50, 60)),
+ IsPaintChunk(1, 2, id3, properties, nullptr,
+ IntRect(0, 0, 100, 120))));
+ } else {
+ EXPECT_THAT(
+ chunker.PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 1, id1, DefaultPaintChunkProperties(), nullptr,
+ IntRect(0, 0, 10, 10)),
+ IsPaintChunk(1, 1, id2, properties, &hit_test_data,
+ IntRect(20, 30, 40, 50)),
+ IsPaintChunk(1, 2, PaintChunk::Id(client_, DisplayItemType(5)),
+ properties, nullptr, IntRect(0, 0, 10, 10))));
+ }
+}
+
+TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueAllOpaqueItems) {
+ ScopedCompositeAfterPaintForTest cap(true);
+ PaintChunker chunker;
+ FakeDisplayItemClient client1("client1", IntRect(0, 0, 100, 100));
+ FakeDisplayItemClient client2("client2", IntRect(0, 100, 100, 50));
+ FakeDisplayItemClient client3("client3", IntRect(50, 50, 100, 100));
+
+ auto properties = DefaultPaintChunkProperties();
+ chunker.UpdateCurrentPaintChunkProperties(nullptr, properties);
+ // Single opaque item.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(0)));
+ chunker.SetForceNewChunk(true);
+ // Two opaque items. No empty area in the united bounds.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(1)));
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client2, DisplayItemType(2)));
+ chunker.SetForceNewChunk(true);
+ // Two opaque items. Has empty area in the united bounds.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(3)));
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client3, DisplayItemType(4)));
+
+ Vector<PaintChunk> chunks = chunker.ReleasePaintChunks();
+ EXPECT_THAT(
+ chunks,
+ ElementsAre(
+ IsPaintChunk(0, 1, PaintChunk::Id(client1, DisplayItemType(0)),
+ properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(1, 3, PaintChunk::Id(client1, DisplayItemType(1)),
+ properties, nullptr, IntRect(0, 0, 100, 150)),
+ IsPaintChunk(3, 5, PaintChunk::Id(client1, DisplayItemType(3)),
+ properties, nullptr, IntRect(0, 0, 150, 150))));
+ ASSERT_EQ(3u, chunks.size());
+ EXPECT_TRUE(chunks[0].known_to_be_opaque);
+ EXPECT_TRUE(chunks[1].known_to_be_opaque);
+ EXPECT_FALSE(chunks[2].known_to_be_opaque);
+}
+
+TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueWithHitTest) {
+ ScopedCompositeAfterPaintForTest cap(true);
+ PaintChunker chunker;
+ FakeDisplayItemClient client1("client1", IntRect(0, 0, 100, 100));
+ FakeDisplayItemClient client2("client2", IntRect(0, 100, 100, 50));
+ FakeDisplayItemClient client3("client3", IntRect(50, 50, 100, 100));
+
+ auto properties = DefaultPaintChunkProperties();
+ chunker.UpdateCurrentPaintChunkProperties(nullptr, properties);
+ // Hit test rect only.
+ chunker.AddHitTestDataToCurrentChunk(
+ PaintChunk::Id(client1, DisplayItemType(0)), IntRect(10, 20, 30, 40),
+ TouchAction::kAuto);
+ chunker.SetForceNewChunk(true);
+ // Hit test rect is smaller than the opaque item.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(1)));
+ chunker.AddHitTestDataToCurrentChunk(
+ PaintChunk::Id(client1, DisplayItemType(2)), IntRect(0, 0, 50, 100),
+ TouchAction::kAuto);
+ chunker.SetForceNewChunk(true);
+ // Hit test rect is the same as the opaque item.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(3)));
+ chunker.AddHitTestDataToCurrentChunk(
+ PaintChunk::Id(client1, DisplayItemType(4)), IntRect(0, 0, 100, 100),
+ TouchAction::kAuto);
+ chunker.SetForceNewChunk(true);
+ // Hit test rect is bigger than the opaque item.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(5)));
+ chunker.AddHitTestDataToCurrentChunk(
+ PaintChunk::Id(client1, DisplayItemType(6)), IntRect(0, 100, 200, 100),
+ TouchAction::kAuto);
+
+ Vector<PaintChunk> chunks = chunker.ReleasePaintChunks();
+ EXPECT_THAT(
+ chunks,
+ ElementsAre(
+ IsPaintChunk(0, 0, PaintChunk::Id(client1, DisplayItemType(0)),
+ properties, nullptr, IntRect(10, 20, 30, 40)),
+ IsPaintChunk(0, 1, PaintChunk::Id(client1, DisplayItemType(1)),
+ properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(1, 2, PaintChunk::Id(client1, DisplayItemType(3)),
+ properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(2, 3, PaintChunk::Id(client1, DisplayItemType(5)),
+ properties, nullptr, IntRect(0, 0, 200, 200))));
+ ASSERT_EQ(4u, chunks.size());
+ EXPECT_FALSE(chunks[0].known_to_be_opaque);
+ EXPECT_TRUE(chunks[1].known_to_be_opaque);
+ EXPECT_TRUE(chunks[2].known_to_be_opaque);
+ EXPECT_FALSE(chunks[3].known_to_be_opaque);
+}
+
+TEST_F(PaintChunkerTest, ChunkBoundsAndKnownToBeOpaqueMixedOpaquenessItems) {
+ ScopedCompositeAfterPaintForTest cap(true);
+ PaintChunker chunker;
+ FakeDisplayItemClient client1("client1", IntRect(0, 0, 100, 100));
+ FakeDisplayItemClient client3("client2", IntRect(50, 50, 50, 50));
+
+ auto properties = DefaultPaintChunkProperties();
+ chunker.UpdateCurrentPaintChunkProperties(nullptr, properties);
+ // Single translucent item .
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client1, DisplayItemType(1)));
+ chunker.SetForceNewChunk(true);
+ // Two items, one translucent, one opaque. The opaque item doesn't contain
+ // the translucent item.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client1, DisplayItemType(2)));
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client3, DisplayItemType(3)));
+ chunker.SetForceNewChunk(true);
+ // Two items, one translucent, one opaque, with the same visual rect.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client1, DisplayItemType(4)));
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(5)));
+ chunker.SetForceNewChunk(true);
+ // Two items, one opaque, one translucent. The opaque item contains the
+ // translucent item.
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerOpaqueDisplayItem(client1, DisplayItemType(6)));
+ chunker.IncrementDisplayItemIndex(
+ TestChunkerDisplayItem(client3, DisplayItemType(7)));
+
+ Vector<PaintChunk> chunks = chunker.ReleasePaintChunks();
+ EXPECT_THAT(
+ chunks,
+ ElementsAre(
+ IsPaintChunk(0, 1, PaintChunk::Id(client1, DisplayItemType(1)),
+ properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(1, 3, PaintChunk::Id(client1, DisplayItemType(2)),
+ properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(3, 5, PaintChunk::Id(client1, DisplayItemType(4)),
+ properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(5, 7, PaintChunk::Id(client1, DisplayItemType(6)),
+ properties, nullptr, IntRect(0, 0, 100, 100))));
+ ASSERT_EQ(4u, chunks.size());
+ EXPECT_FALSE(chunks[0].known_to_be_opaque);
+ EXPECT_FALSE(chunks[1].known_to_be_opaque);
+ EXPECT_TRUE(chunks[2].known_to_be_opaque);
+ EXPECT_TRUE(chunks[3].known_to_be_opaque);
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
index ff52743090b..fa69422b443 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
@@ -31,15 +31,57 @@ PaintController::~PaintController() {
DCHECK(usage_ == kTransient || new_display_item_list_.IsEmpty());
}
+// For micro benchmarks of record time.
+static bool g_subsequence_caching_disabled = false;
+static bool g_partial_invalidation = false;
+static int g_partial_invalidation_display_item_count = 0;
+static int g_partial_invalidation_subsequence_count = 0;
+
+// This is used to invalidate one out of every |kInvalidateDisplayItemInterval|
+// display items for the micro benchmark of record time with partial
+// invalidation.
+static bool ShouldInvalidateDisplayItemForBenchmark() {
+ constexpr int kInvalidateDisplayItemInterval = 8;
+ return g_partial_invalidation &&
+ !(g_partial_invalidation_display_item_count++ %
+ kInvalidateDisplayItemInterval);
+}
+// Similar to the above, but for subsequences.
+static bool ShouldInvalidateSubsequenceForBenchmark() {
+ constexpr int kInvalidateSubsequenceInterval = 2;
+ return g_partial_invalidation &&
+ !(g_partial_invalidation_subsequence_count++ %
+ kInvalidateSubsequenceInterval);
+}
+
+void PaintController::SetSubsequenceCachingDisabledForBenchmark() {
+ g_subsequence_caching_disabled = true;
+}
+
+void PaintController::SetPartialInvalidationForBenchmark() {
+ g_partial_invalidation = true;
+ g_partial_invalidation_display_item_count = 0;
+ g_partial_invalidation_subsequence_count = 0;
+}
+
+bool PaintController::ShouldForcePaintForBenchmark() {
+ return g_subsequence_caching_disabled || g_partial_invalidation;
+}
+
+void PaintController::ClearFlagsForBenchmark() {
+ g_subsequence_caching_disabled = false;
+ g_partial_invalidation = false;
+}
+
bool PaintController::UseCachedItemIfPossible(const DisplayItemClient& client,
DisplayItem::Type type) {
if (usage_ == kTransient)
return false;
- if (DisplayItemConstructionIsDisabled())
+ if (!ClientCacheIsValid(client))
return false;
- if (!ClientCacheIsValid(client))
+ if (ShouldInvalidateDisplayItemForBenchmark())
return false;
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
@@ -49,7 +91,7 @@ bool PaintController::UseCachedItemIfPossible(const DisplayItemClient& client,
return false;
}
- size_t cached_item =
+ auto cached_item =
FindCachedItem(DisplayItem::Id(client, type, current_fragment_));
if (cached_item == kNotFound) {
// See FindOutOfOrderCachedItemForward() for explanation of the situation.
@@ -89,7 +131,10 @@ bool PaintController::UseCachedSubsequenceIfPossible(
if (usage_ == kTransient)
return false;
- if (DisplayItemConstructionIsDisabled() || SubsequenceCachingIsDisabled())
+ if (g_subsequence_caching_disabled)
+ return false;
+
+ if (ShouldInvalidateSubsequenceForBenchmark())
return false;
if (!ClientCacheIsValid(client))
@@ -109,7 +154,14 @@ bool PaintController::UseCachedSubsequenceIfPossible(
return false;
}
- if (current_paint_artifact_->GetDisplayItemList()[markers->start]
+ wtf_size_t start_item_index =
+ current_paint_artifact_->PaintChunks()[markers->start_chunk_index]
+ .begin_index;
+ wtf_size_t end_item_index =
+ current_paint_artifact_->PaintChunks()[markers->end_chunk_index - 1]
+ .end_index;
+ if (end_item_index > start_item_index &&
+ current_paint_artifact_->GetDisplayItemList()[start_item_index]
.IsTombstone()) {
// The subsequence has already been copied, indicating that the same client
// created multiple subsequences. If DCHECK_IS_ON(), then we should have
@@ -121,23 +173,23 @@ bool PaintController::UseCachedSubsequenceIfPossible(
EnsureNewDisplayItemListInitialCapacity();
- if (next_item_to_match_ == markers->start) {
+ if (next_item_to_match_ == start_item_index) {
// We are matching new and cached display items sequentially. Skip the
// subsequence for later sequential matching of individual display items.
- next_item_to_match_ = markers->end;
+ next_item_to_match_ = end_item_index;
// Items before |next_item_to_match_| have been copied so we don't need to
// index them.
if (next_item_to_match_ > next_item_to_index_)
next_item_to_index_ = next_item_to_match_;
}
- num_cached_new_items_ += markers->end - markers->start;
+ num_cached_new_items_ += end_item_index - start_item_index;
++num_cached_new_subsequences_;
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
DCHECK(!IsCheckingUnderInvalidation());
- under_invalidation_checking_begin_ = markers->start;
- under_invalidation_checking_end_ = markers->end;
+ under_invalidation_checking_begin_ = start_item_index;
+ under_invalidation_checking_end_ = end_item_index;
under_invalidation_message_prefix_ =
"(In cached subsequence for " + client.DebugName() + ")";
// Return false to let the painter actually paint. We will check if the new
@@ -145,9 +197,9 @@ bool PaintController::UseCachedSubsequenceIfPossible(
return false;
}
- size_t start = BeginSubsequence();
- CopyCachedSubsequence(markers->start, markers->end);
- EndSubsequence(client, start);
+ auto new_start_chunk_index = BeginSubsequence();
+ CopyCachedSubsequence(markers->start_chunk_index, markers->end_chunk_index);
+ EndSubsequence(client, new_start_chunk_index);
return true;
}
@@ -159,33 +211,50 @@ PaintController::SubsequenceMarkers* PaintController::GetSubsequenceMarkers(
return &result->value;
}
-size_t PaintController::BeginSubsequence() {
+wtf_size_t PaintController::BeginSubsequence() {
// Force new paint chunk which is required for subsequence caching.
- new_paint_chunks_.ForceNewChunk();
- return new_display_item_list_.size();
+ SetForceNewChunk(true);
+ return new_paint_chunks_.size();
}
void PaintController::EndSubsequence(const DisplayItemClient& client,
- size_t start) {
- size_t end = new_display_item_list_.size();
+ wtf_size_t start_chunk_index) {
+ auto end_chunk_index = new_paint_chunks_.size();
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
IsCheckingUnderInvalidation()) {
SubsequenceMarkers* markers = GetSubsequenceMarkers(client);
- if (!markers && start != end) {
- ShowSequenceUnderInvalidationError(
- "under-invalidation : unexpected subsequence", client, start, end);
- CHECK(false);
- }
- if (markers && markers->end - markers->start != end - start) {
- ShowSequenceUnderInvalidationError(
- "under-invalidation: new subsequence wrong length", client, start,
- end);
- CHECK(false);
+ if (!markers) {
+ if (start_chunk_index != end_chunk_index) {
+ ShowSequenceUnderInvalidationError(
+ "under-invalidation : unexpected subsequence", client);
+ CHECK(false);
+ }
+ } else {
+ if (markers->end_chunk_index - markers->start_chunk_index !=
+ end_chunk_index - start_chunk_index) {
+ ShowSequenceUnderInvalidationError(
+ "under-invalidation: new subsequence wrong length", client);
+ CHECK(false);
+ }
+ auto old_chunk_index = markers->start_chunk_index;
+ for (auto new_chunk_index = start_chunk_index;
+ new_chunk_index < end_chunk_index;
+ ++new_chunk_index, ++old_chunk_index) {
+ const auto& old_chunk =
+ current_paint_artifact_->PaintChunks()[old_chunk_index];
+ const auto& new_chunk =
+ new_paint_chunks_.PaintChunks()[new_chunk_index];
+ if (!old_chunk.EqualsForUnderInvalidationChecking(new_chunk)) {
+ ShowSequenceUnderInvalidationError(
+ "under-invalidation: chunk changed", client);
+ CHECK(false) << "Changed chunk: " << new_chunk;
+ }
+ }
}
}
- if (start == end) {
+ if (start_chunk_index == end_chunk_index) {
// Omit the empty subsequence. The forcing-new-chunk flag set by
// BeginSubsequence() still applies, but this not a big deal because empty
// subsequences are not common. Also we should not clear the flag because
@@ -194,35 +263,24 @@ void PaintController::EndSubsequence(const DisplayItemClient& client,
}
// Force new paint chunk which is required for subsequence caching.
- new_paint_chunks_.ForceNewChunk();
+ SetForceNewChunk(true);
DCHECK(!new_cached_subsequences_.Contains(&client))
<< "Multiple subsequences for client: " << client.DebugName();
- new_cached_subsequences_.insert(&client, SubsequenceMarkers(start, end));
+ new_cached_subsequences_.insert(
+ &client, SubsequenceMarkers{start_chunk_index, end_chunk_index});
}
-void PaintController::ProcessNewItem(DisplayItem& display_item) {
- DCHECK(!construction_disabled_);
-
- if (IsSkippingCache() && usage_ == kMultiplePaints) {
- display_item.Client().Invalidate(PaintInvalidationReason::kUncacheable);
- display_item.SetUncacheable();
- }
-
- bool chunk_added = new_paint_chunks_.IncrementDisplayItemIndex(display_item);
+void PaintController::DidAppendItem(DisplayItem& display_item) {
+ if (usage_ == kTransient)
+ return;
#if DCHECK_IS_ON()
- if (chunk_added && CurrentPaintChunk().is_cacheable) {
- AddToIndicesByClientMap(CurrentPaintChunk().id.client,
- new_paint_chunks_.LastChunkIndex(),
- new_paint_chunk_indices_by_client_);
- }
-
- if (usage_ == kMultiplePaints && display_item.IsCacheable()) {
- size_t index = FindMatchingItemFromIndex(
- display_item.GetId(), new_display_item_indices_by_client_,
- new_display_item_list_);
+ if (display_item.IsCacheable()) {
+ auto index = FindMatchingItemFromIndex(display_item.GetId(),
+ new_display_item_indices_by_client_,
+ new_display_item_list_);
if (index != kNotFound) {
ShowDebugData();
NOTREACHED() << "DisplayItem " << display_item.AsDebugString().Utf8()
@@ -234,13 +292,20 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) {
new_display_item_list_.size() - 1,
new_display_item_indices_by_client_);
}
-#else // DCHECK_IS_ON()
- std::ignore = chunk_added;
#endif
- if (usage_ == kMultiplePaints &&
- RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
CheckUnderInvalidation();
+}
+
+void PaintController::ProcessNewItem(DisplayItem& display_item) {
+ if (IsSkippingCache() && usage_ == kMultiplePaints) {
+ display_item.Client().Invalidate(PaintInvalidationReason::kUncacheable);
+ display_item.SetUncacheable();
+ }
+
+ if (new_paint_chunks_.IncrementDisplayItemIndex(display_item))
+ DidAppendChunk();
if (!frame_first_paints_.back().first_painted && display_item.IsDrawing() &&
// Here we ignore all document-background paintings because we don't
@@ -251,13 +316,26 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) {
display_item.DrawsContent()) {
SetFirstPainted();
}
+
+ DidAppendItem(display_item);
}
-DisplayItem& PaintController::MoveItemFromCurrentListToNewList(size_t index) {
+DisplayItem& PaintController::MoveItemFromCurrentListToNewList(
+ wtf_size_t index) {
return new_display_item_list_.AppendByMoving(
current_paint_artifact_->GetDisplayItemList()[index]);
}
+void PaintController::DidAppendChunk() {
+#if DCHECK_IS_ON()
+ if (new_paint_chunks_.LastChunk().is_cacheable) {
+ AddToIndicesByClientMap(new_paint_chunks_.LastChunk().id.client,
+ new_paint_chunks_.size() - 1,
+ new_paint_chunk_indices_by_client_);
+ }
+#endif
+}
+
void PaintController::InvalidateAll() {
DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
InvalidateAllInternal();
@@ -278,6 +356,25 @@ bool PaintController::CacheIsAllInvalid() const {
return cache_is_all_invalid_;
}
+void PaintController::UpdateCurrentPaintChunkProperties(
+ const PaintChunk::Id* id,
+ const PropertyTreeState& properties) {
+ if (id) {
+ PaintChunk::Id id_with_fragment(*id, current_fragment_);
+ new_paint_chunks_.UpdateCurrentPaintChunkProperties(&id_with_fragment,
+ properties);
+ CheckDuplicatePaintChunkId(id_with_fragment);
+ } else {
+ new_paint_chunks_.UpdateCurrentPaintChunkProperties(nullptr, properties);
+ }
+}
+
+void PaintController::AppendChunkByMoving(PaintChunk&& chunk) {
+ CheckDuplicatePaintChunkId(chunk.id);
+ new_paint_chunks_.AppendByMoving(std::move(chunk));
+ DidAppendChunk();
+}
+
bool PaintController::ClientCacheIsValid(
const DisplayItemClient& client) const {
#if DCHECK_IS_ON()
@@ -288,7 +385,7 @@ bool PaintController::ClientCacheIsValid(
return client.IsValid();
}
-size_t PaintController::FindMatchingItemFromIndex(
+wtf_size_t PaintController::FindMatchingItemFromIndex(
const DisplayItem::Id& id,
const IndicesByClientMap& display_item_indices_by_client,
const DisplayItemList& list) {
@@ -297,8 +394,7 @@ size_t PaintController::FindMatchingItemFromIndex(
if (it == display_item_indices_by_client.end())
return kNotFound;
- const Vector<size_t>& indices = it->value;
- for (size_t index : indices) {
+ for (auto index : it->value) {
const DisplayItem& existing_item = list[index];
if (existing_item.IsTombstone())
continue;
@@ -311,17 +407,17 @@ size_t PaintController::FindMatchingItemFromIndex(
}
void PaintController::AddToIndicesByClientMap(const DisplayItemClient& client,
- size_t index,
+ wtf_size_t index,
IndicesByClientMap& map) {
auto it = map.find(&client);
auto& indices =
it == map.end()
- ? map.insert(&client, Vector<size_t>()).stored_value->value
+ ? map.insert(&client, Vector<wtf_size_t>()).stored_value->value
: it->value;
indices.push_back(index);
}
-size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
+wtf_size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
DCHECK(ClientCacheIsValid(id.client));
if (next_item_to_match_ <
@@ -342,7 +438,7 @@ size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
}
}
- size_t found_index =
+ wtf_size_t found_index =
FindMatchingItemFromIndex(id, out_of_order_item_indices_,
current_paint_artifact_->GetDisplayItemList());
if (found_index != kNotFound) {
@@ -356,9 +452,9 @@ size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
}
// Find forward for the item and index all skipped indexable items.
-size_t PaintController::FindOutOfOrderCachedItemForward(
+wtf_size_t PaintController::FindOutOfOrderCachedItemForward(
const DisplayItem::Id& id) {
- for (size_t i = next_item_to_index_;
+ for (auto i = next_item_to_index_;
i < current_paint_artifact_->GetDisplayItemList().size(); ++i) {
const DisplayItem& item = current_paint_artifact_->GetDisplayItemList()[i];
if (item.IsTombstone())
@@ -398,64 +494,48 @@ size_t PaintController::FindOutOfOrderCachedItemForward(
// When paintUnderInvaldiationCheckingEnabled() we'll not actually
// copy the subsequence, but mark the begin and end of the subsequence for
// under-invalidation checking.
-void PaintController::CopyCachedSubsequence(size_t begin_index,
- size_t end_index) {
+void PaintController::CopyCachedSubsequence(wtf_size_t start_chunk_index,
+ wtf_size_t end_chunk_index) {
+#if DCHECK_IS_ON()
DCHECK(!RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
-
- const DisplayItem* cached_item =
- &current_paint_artifact_->GetDisplayItemList()[begin_index];
-
- auto* cached_chunk =
- current_paint_artifact_->FindChunkByDisplayItemIndex(begin_index);
- DCHECK(cached_chunk != current_paint_artifact_->PaintChunks().end());
auto properties_before_subsequence =
new_paint_chunks_.CurrentPaintChunkProperties();
- UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
- cached_chunk->id, cached_chunk->properties.GetPropertyTreeState());
-
- for (size_t current_index = begin_index; current_index < end_index;
- ++current_index) {
- cached_item = &current_paint_artifact_->GetDisplayItemList()[current_index];
- SECURITY_CHECK(!cached_item->IsTombstone());
-#if DCHECK_IS_ON()
- DCHECK(cached_item->Client().IsAlive());
#endif
- if (current_index == cached_chunk->end_index) {
- ++cached_chunk;
- DCHECK(cached_chunk != current_paint_artifact_->PaintChunks().end());
- new_paint_chunks_.ForceNewChunk();
- UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
- cached_chunk->id, cached_chunk->properties.GetPropertyTreeState());
- }
-
+ for (auto chunk_index = start_chunk_index; chunk_index < end_chunk_index;
+ ++chunk_index) {
+ auto& cached_chunk = current_paint_artifact_->PaintChunks()[chunk_index];
+ auto cached_item_index = cached_chunk.begin_index;
+ for (auto& cached_item :
+ current_paint_artifact_->GetDisplayItemList().ItemsInPaintChunk(
+ cached_chunk)) {
+ SECURITY_CHECK(!cached_item.IsTombstone());
#if DCHECK_IS_ON()
- // Visual rect change should not happen in a cached subsequence.
- // However, because of different method of pixel snapping in different
- // paths, there are false positives. Just log an error.
- if (cached_item->VisualRect() != cached_item->Client().VisualRect()) {
- DLOG(ERROR) << "Visual rect changed in a cached subsequence: "
- << cached_item->Client().DebugName()
- << " old=" << cached_item->VisualRect()
- << " new=" << cached_item->Client().VisualRect();
- }
+ DCHECK(cached_item.Client().IsAlive());
+ // Visual rect change should not happen in a cached subsequence.
+ // However, because of different method of pixel snapping in different
+ // paths, there are false positives. Just log an error.
+ if (cached_item.VisualRect() != cached_item.Client().VisualRect()) {
+ DLOG(ERROR) << "Visual rect changed in a cached subsequence: "
+ << cached_item.Client().DebugName()
+ << " old=" << cached_item.VisualRect()
+ << " new=" << cached_item.Client().VisualRect();
+ }
#endif
+ auto& item = MoveItemFromCurrentListToNewList(cached_item_index++);
+ item.SetMovedFromCachedSubsequence(true);
+ DidAppendItem(item);
+ }
- ProcessNewItem(MoveItemFromCurrentListToNewList(current_index));
- DCHECK((!CurrentPaintChunk().is_cacheable && !cached_chunk->is_cacheable) ||
- CurrentPaintChunk().Matches(*cached_chunk));
+ DCHECK_EQ(cached_item_index, cached_chunk.end_index);
+ AppendChunkByMoving(std::move(cached_chunk));
}
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
- under_invalidation_checking_end_ = end_index;
- DCHECK(IsCheckingUnderInvalidation());
- } else {
- // Restore properties and force new chunk for any trailing display items
- // after the cached subsequence without new properties.
- new_paint_chunks_.ForceNewChunk();
- UpdateCurrentPaintChunkProperties(base::nullopt,
- properties_before_subsequence);
- }
+ SetForceNewChunk(true);
+
+#if DCHECK_IS_ON()
+ DCHECK_EQ(properties_before_subsequence, CurrentPaintChunkProperties());
+#endif
}
void PaintController::ResetCurrentListIndices() {
@@ -527,13 +607,31 @@ void PaintController::FinishCycle() {
}
for (const auto& item : current_paint_artifact_->GetDisplayItemList()) {
const auto& client = item.Client();
+ if (item.IsMovedFromCachedSubsequence()) {
+ // We don't need to validate the clients of a display item that is
+ // copied from a cached subsequence, because it should be already
+ // valid. See http://crbug.com/1050090 for more details.
+#if DCHECK_IS_ON()
+ DCHECK(client.IsAlive());
+ DCHECK(client.IsValid() || !client.IsCacheable());
+#endif
+ continue;
+ }
client.ClearPartialInvalidationVisualRect();
if (client.IsCacheable())
client.Validate();
}
for (const auto& chunk : current_paint_artifact_->PaintChunks()) {
- if (chunk.id.client.IsCacheable())
- chunk.id.client.Validate();
+ const auto& client = chunk.id.client;
+ if (chunk.is_moved_from_cached_subsequence) {
+#if DCHECK_IS_ON()
+ DCHECK(client.IsAlive());
+ DCHECK(client.IsValid() || !client.IsCacheable());
+#endif
+ continue;
+ }
+ if (client.IsCacheable())
+ client.Validate();
}
}
@@ -638,9 +736,7 @@ void PaintController::ShowUnderInvalidationError(
void PaintController::ShowSequenceUnderInvalidationError(
const char* reason,
- const DisplayItemClient& client,
- int start,
- int end) {
+ const DisplayItemClient& client) {
LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason;
LOG(ERROR) << "Subsequence client: " << client.DebugName();
#if DCHECK_IS_ON()
@@ -669,7 +765,7 @@ void PaintController::CheckUnderInvalidation() {
}
const DisplayItem& new_item = new_display_item_list_.Last();
- size_t old_item_index = under_invalidation_checking_begin_;
+ auto old_item_index = under_invalidation_checking_begin_;
DisplayItem* old_item =
old_item_index < current_paint_artifact_->GetDisplayItemList().size()
? &current_paint_artifact_->GetDisplayItemList()[old_item_index]
@@ -720,19 +816,21 @@ FrameFirstPaint PaintController::EndFrame(const void* frame) {
return result;
}
-#if DCHECK_IS_ON()
void PaintController::CheckDuplicatePaintChunkId(const PaintChunk::Id& id) {
+#if DCHECK_IS_ON()
if (IsSkippingCache())
return;
- if (DisplayItem::IsForeignLayerType(id.type))
+ if (DisplayItem::IsGraphicsLayerWrapperType(id.type) ||
+ DisplayItem::IsForeignLayerType(id.type)) {
return;
+ }
auto it = new_paint_chunk_indices_by_client_.find(&id.client);
if (it != new_paint_chunk_indices_by_client_.end()) {
const auto& indices = it->value;
for (auto index : indices) {
- const auto& chunk = new_paint_chunks_.PaintChunkAt(index);
+ const auto& chunk = new_paint_chunks_.PaintChunks()[index];
if (chunk.id == id) {
ShowDebugData();
NOTREACHED() << "New paint chunk id " << id
@@ -740,8 +838,8 @@ void PaintController::CheckDuplicatePaintChunkId(const PaintChunk::Id& id) {
}
}
}
-}
#endif
+}
size_t PaintController::sum_num_items_ = 0;
size_t PaintController::sum_num_cached_items_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
index 118f538d49e..1aaea13fdda 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -28,7 +28,7 @@
namespace blink {
-static const size_t kInitialDisplayItemListCapacityBytes = 512;
+static constexpr wtf_size_t kInitialDisplayItemListCapacityBytes = 512;
// FrameFirstPaint stores first-paint, text or image painted for the
// corresponding frame. They are never reset to false. First-paint is defined in
@@ -73,33 +73,42 @@ class PLATFORM_EXPORT PaintController {
// These methods are called during painting.
// Provide a new set of paint chunk properties to apply to recorded display
- // items.
- void UpdateCurrentPaintChunkProperties(
- const base::Optional<PaintChunk::Id>& id,
- const PropertyTreeState& properties) {
- if (id) {
- PaintChunk::Id id_with_fragment(*id, current_fragment_);
- UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(id_with_fragment,
- properties);
-#if DCHECK_IS_ON()
- CheckDuplicatePaintChunkId(id_with_fragment);
-#endif
- } else {
- new_paint_chunks_.UpdateCurrentPaintChunkProperties(base::nullopt,
- properties);
- }
- }
-
+ // items. If id is nullptr, the id of the first display item will be used as
+ // the id of the paint chunk if needed.
+ void UpdateCurrentPaintChunkProperties(const PaintChunk::Id*,
+ const PropertyTreeState&);
const PropertyTreeState& CurrentPaintChunkProperties() const {
return new_paint_chunks_.CurrentPaintChunkProperties();
}
+ // See PaintChunker for documentation of the following methods.
+ wtf_size_t NumNewChunks() const { return new_paint_chunks_.size(); }
+ void SetForceNewChunk(bool force) {
+ new_paint_chunks_.SetForceNewChunk(force);
+ }
+ bool WillForceNewChunk() const {
+ return new_paint_chunks_.WillForceNewChunk();
+ }
+ const IntRect& LastChunkBounds() const {
+ return new_paint_chunks_.LastChunk().bounds;
+ }
- PaintChunk& CurrentPaintChunk() { return new_paint_chunks_.LastChunk(); }
-
- void ForceNewChunk(const DisplayItemClient& client, DisplayItem::Type type) {
- new_paint_chunks_.ForceNewChunk();
- new_paint_chunks_.UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(client, type), CurrentPaintChunkProperties());
+ void RecordHitTestData(const DisplayItemClient& client,
+ const IntRect& rect,
+ TouchAction touch_action) {
+ if (rect.IsEmpty())
+ return;
+ PaintChunk::Id id(client, DisplayItem::kHitTest, current_fragment_);
+ CheckDuplicatePaintChunkId(id);
+ new_paint_chunks_.AddHitTestDataToCurrentChunk(id, rect, touch_action);
+ }
+ void RecordScrollHitTestData(
+ const DisplayItemClient& client,
+ DisplayItem::Type type,
+ const TransformPaintPropertyNode* scroll_translation,
+ const IntRect& rect) {
+ PaintChunk::Id id(client, type, current_fragment_);
+ CheckDuplicatePaintChunkId(id);
+ new_paint_chunks_.CreateScrollHitTestChunk(id, scroll_translation, rect);
}
template <typename DisplayItemClass, typename... Args>
@@ -113,9 +122,6 @@ class PLATFORM_EXPORT PaintController {
"DisplayItem subclass alignment is not a factor of "
"kDisplayItemAlignment.");
- if (DisplayItemConstructionIsDisabled())
- return;
-
EnsureNewDisplayItemListInitialCapacity();
DisplayItemClass& display_item =
new_display_item_list_.AllocateAndConstruct<DisplayItemClass>(
@@ -134,10 +140,11 @@ class PLATFORM_EXPORT PaintController {
// true. Otherwise returns false.
bool UseCachedSubsequenceIfPossible(const DisplayItemClient&);
- size_t BeginSubsequence();
+ // Returns the index of the paint chunk that is forced for the subsequence.
+ wtf_size_t BeginSubsequence();
// The |start| parameter should be the return value of the corresponding
// BeginSubsequence().
- void EndSubsequence(const DisplayItemClient&, size_t start);
+ void EndSubsequence(const DisplayItemClient&, wtf_size_t start_chunk_index);
void BeginSkippingCache() {
if (usage_ == kTransient)
@@ -197,23 +204,11 @@ class PLATFORM_EXPORT PaintController {
return GetPaintArtifact().PaintChunks();
}
- // For micro benchmarking of record time. If true, display item construction
- // is disabled to isolate the costs of construction in performance metrics.
- bool DisplayItemConstructionIsDisabled() const {
- return construction_disabled_;
- }
- void SetDisplayItemConstructionIsDisabled(bool disable) {
- construction_disabled_ = disable;
- }
-
- // For micro benchmarking of record time. If true, subsequence caching is
- // disabled to test the cost of display item caching.
- bool SubsequenceCachingIsDisabled() const {
- return subsequence_caching_disabled_;
- }
- void SetSubsequenceCachingIsDisabled(bool disable) {
- subsequence_caching_disabled_ = disable;
- }
+ // For micro benchmarks of record time.
+ static void SetSubsequenceCachingDisabledForBenchmark();
+ static void SetPartialInvalidationForBenchmark();
+ static bool ShouldForcePaintForBenchmark();
+ static void ClearFlagsForBenchmark();
void SetFirstPainted();
void SetTextPainted();
@@ -278,30 +273,29 @@ class PLATFORM_EXPORT PaintController {
}
}
- // Set new item state (cache skipping, etc) for a new item.
+ // Set new item state (cache skipping, etc) for the last new display item.
void ProcessNewItem(DisplayItem&);
- DisplayItem& MoveItemFromCurrentListToNewList(size_t);
+
+ void DidAppendItem(DisplayItem&);
+ DisplayItem& MoveItemFromCurrentListToNewList(wtf_size_t);
+ void DidAppendChunk();
// Maps clients to indices of display items or chunks of each client.
- using IndicesByClientMap = HashMap<const DisplayItemClient*, Vector<size_t>>;
+ using IndicesByClientMap =
+ HashMap<const DisplayItemClient*, Vector<wtf_size_t>>;
- static size_t FindMatchingItemFromIndex(const DisplayItem::Id&,
- const IndicesByClientMap&,
- const DisplayItemList&);
+ static wtf_size_t FindMatchingItemFromIndex(const DisplayItem::Id&,
+ const IndicesByClientMap&,
+ const DisplayItemList&);
static void AddToIndicesByClientMap(const DisplayItemClient&,
- size_t index,
+ wtf_size_t index,
IndicesByClientMap&);
- size_t FindCachedItem(const DisplayItem::Id&);
- size_t FindOutOfOrderCachedItemForward(const DisplayItem::Id&);
- void CopyCachedSubsequence(size_t begin_index, size_t end_index);
-
- void UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
- const PaintChunk::Id& id_with_fragment,
- const PropertyTreeState& properties) {
- new_paint_chunks_.UpdateCurrentPaintChunkProperties(id_with_fragment,
- properties);
- }
+ wtf_size_t FindCachedItem(const DisplayItem::Id&);
+ wtf_size_t FindOutOfOrderCachedItemForward(const DisplayItem::Id&);
+ void CopyCachedSubsequence(wtf_size_t start_chunk_index,
+ wtf_size_t end_chunk_index);
+ void AppendChunkByMoving(PaintChunk&&);
// Resets the indices (e.g. next_item_to_match_) of
// current_paint_artifact_.GetDisplayItemList() to their initial values. This
@@ -316,9 +310,7 @@ class PLATFORM_EXPORT PaintController {
const DisplayItem* old_item) const;
void ShowSequenceUnderInvalidationError(const char* reason,
- const DisplayItemClient&,
- int start,
- int end);
+ const DisplayItemClient&);
void CheckUnderInvalidation();
bool IsCheckingUnderInvalidation() const {
@@ -327,19 +319,17 @@ class PLATFORM_EXPORT PaintController {
}
struct SubsequenceMarkers {
- SubsequenceMarkers() : start(0), end(0) {}
- SubsequenceMarkers(size_t start_arg, size_t end_arg)
- : start(start_arg), end(end_arg) {}
- // The start and end (not included) index within current_paint_artifact_
- // of this subsequence.
- size_t start;
- size_t end;
+ // The start and end (not included) index of paint chunks in this
+ // subsequence.
+ wtf_size_t start_chunk_index = 0;
+ wtf_size_t end_chunk_index = 0;
};
SubsequenceMarkers* GetSubsequenceMarkers(const DisplayItemClient&);
-#if DCHECK_IS_ON()
void CheckDuplicatePaintChunkId(const PaintChunk::Id&);
+
+#if DCHECK_IS_ON()
void ShowDebugDataInternal(DisplayItemList::JsonFlags) const;
#endif
@@ -355,9 +345,6 @@ class PLATFORM_EXPORT PaintController {
DisplayItemList new_display_item_list_;
PaintChunker new_paint_chunks_;
- bool construction_disabled_ = false;
- bool subsequence_caching_disabled_ = false;
-
bool cache_is_all_invalid_ = true;
bool committed_ = false;
@@ -366,8 +353,8 @@ class PLATFORM_EXPORT PaintController {
unsigned skipping_cache_count_ = 0;
- size_t num_cached_new_items_ = 0;
- size_t num_cached_new_subsequences_ = 0;
+ wtf_size_t num_cached_new_items_ = 0;
+ wtf_size_t num_cached_new_subsequences_ = 0;
// Stores indices to valid cacheable display items in
// current_paint_artifact_.GetDisplayItemList() that have not been matched by
@@ -381,16 +368,16 @@ class PLATFORM_EXPORT PaintController {
IndicesByClientMap out_of_order_item_indices_;
// The next item in the current list for sequential match.
- size_t next_item_to_match_ = 0;
+ wtf_size_t next_item_to_match_ = 0;
// The next item in the current list to be indexed for out-of-order cache
// requests.
- size_t next_item_to_index_ = 0;
+ wtf_size_t next_item_to_index_ = 0;
#if DCHECK_IS_ON()
- size_t num_indexed_items_ = 0;
- size_t num_sequential_matches_ = 0;
- size_t num_out_of_order_matches_ = 0;
+ wtf_size_t num_indexed_items_ = 0;
+ wtf_size_t num_sequential_matches_ = 0;
+ wtf_size_t num_out_of_order_matches_ = 0;
// This is used to check duplicated ids during CreateAndAppend().
IndicesByClientMap new_display_item_indices_by_client_;
@@ -404,8 +391,8 @@ class PLATFORM_EXPORT PaintController {
// end of the cached drawing or subsequence in the current list. The functions
// return false to let the client do actual painting, and PaintController will
// check if the actual painting results are the same as the cached.
- size_t under_invalidation_checking_begin_ = 0;
- size_t under_invalidation_checking_end_ = 0;
+ wtf_size_t under_invalidation_checking_begin_ = 0;
+ wtf_size_t under_invalidation_checking_end_ = 0;
String under_invalidation_message_prefix_;
@@ -413,7 +400,7 @@ class PLATFORM_EXPORT PaintController {
HashMap<const DisplayItemClient*, SubsequenceMarkers>;
CachedSubsequenceMap current_cached_subsequences_;
CachedSubsequenceMap new_cached_subsequences_;
- size_t last_cached_subsequence_end_ = 0;
+ wtf_size_t last_cached_subsequence_end_ = 0;
unsigned current_fragment_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
index 938214c8573..a0fe789b49b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
@@ -20,29 +20,25 @@ class PaintController::DisplayItemListAsJSON {
DisplayItemList::JsonFlags);
String ToString() {
- return SubsequenceAsJSONArrayRecursive(0, list_.size())
- ->ToPrettyJSONString();
+ return ChunksAsJSONArrayRecursive(0, chunks_.size())->ToPrettyJSONString();
}
private:
std::unique_ptr<JSONObject> SubsequenceAsJSONObjectRecursive();
- std::unique_ptr<JSONArray> SubsequenceAsJSONArrayRecursive(size_t, size_t);
- void AppendSubsequenceAsJSON(size_t, size_t, JSONArray&);
+ std::unique_ptr<JSONArray> ChunksAsJSONArrayRecursive(wtf_size_t, wtf_size_t);
+ void AppendChunksAsJSON(wtf_size_t, wtf_size_t, JSONArray&);
String ClientName(const DisplayItemClient&) const;
struct SubsequenceInfo {
- SubsequenceInfo(const DisplayItemClient* client, size_t start, size_t end)
- : client(client), start(start), end(end) {}
const DisplayItemClient* client;
- size_t start;
- size_t end;
+ wtf_size_t start_chunk_index;
+ wtf_size_t end_chunk_index;
};
const DisplayItemList& list_;
Vector<SubsequenceInfo> subsequences_;
Vector<SubsequenceInfo>::const_iterator current_subsequence_;
const Vector<PaintChunk>& chunks_;
- Vector<PaintChunk>::const_iterator current_chunk_;
DisplayItemList::JsonFlags flags_;
};
@@ -53,15 +49,16 @@ PaintController::DisplayItemListAsJSON::DisplayItemListAsJSON(
DisplayItemList::JsonFlags flags)
: list_(list),
chunks_(chunks),
- current_chunk_(chunks.begin()),
flags_(flags) {
for (const auto& item : subsequence_map) {
- subsequences_.push_back(
- SubsequenceInfo(item.key, item.value.start, item.value.end));
+ subsequences_.push_back(SubsequenceInfo{
+ item.key, item.value.start_chunk_index, item.value.end_chunk_index});
}
std::sort(subsequences_.begin(), subsequences_.end(),
[](const SubsequenceInfo& a, const SubsequenceInfo& b) {
- return a.start == b.start ? a.end > b.end : a.start < b.start;
+ return a.start_chunk_index == b.start_chunk_index
+ ? a.end_chunk_index > b.end_chunk_index
+ : a.start_chunk_index < b.start_chunk_index;
});
current_subsequence_ = subsequences_.begin();
@@ -77,70 +74,59 @@ PaintController::DisplayItemListAsJSON::SubsequenceAsJSONObjectRecursive() {
json_object->SetString("subsequence",
String::Format("client: %p ", subsequence.client) +
ClientName(*subsequence.client));
- json_object->SetArray("chunks", SubsequenceAsJSONArrayRecursive(
- subsequence.start, subsequence.end));
+ json_object->SetArray(
+ "chunks", ChunksAsJSONArrayRecursive(subsequence.start_chunk_index,
+ subsequence.end_chunk_index));
return json_object;
}
std::unique_ptr<JSONArray>
-PaintController::DisplayItemListAsJSON::SubsequenceAsJSONArrayRecursive(
- size_t start_item,
- size_t end_item) {
+PaintController::DisplayItemListAsJSON::ChunksAsJSONArrayRecursive(
+ wtf_size_t start_chunk_index,
+ wtf_size_t end_chunk_index) {
auto array = std::make_unique<JSONArray>();
- size_t item_index = start_item;
+ auto chunk_index = start_chunk_index;
while (current_subsequence_ != subsequences_.end() &&
- current_subsequence_->start < end_item) {
+ current_subsequence_->start_chunk_index < end_chunk_index) {
const auto& subsequence = *current_subsequence_;
- DCHECK(subsequence.start >= item_index);
- DCHECK(subsequence.end <= end_item);
+ DCHECK_GE(subsequence.start_chunk_index, chunk_index);
+ DCHECK_LE(subsequence.end_chunk_index, end_chunk_index);
- if (item_index < subsequence.start)
- AppendSubsequenceAsJSON(item_index, subsequence.start, *array);
+ if (chunk_index < subsequence.start_chunk_index)
+ AppendChunksAsJSON(chunk_index, subsequence.start_chunk_index, *array);
array->PushObject(SubsequenceAsJSONObjectRecursive());
- item_index = subsequence.end;
+ chunk_index = subsequence.end_chunk_index;
}
- if (item_index < end_item)
- AppendSubsequenceAsJSON(item_index, end_item, *array);
+ if (chunk_index < end_chunk_index)
+ AppendChunksAsJSON(chunk_index, end_chunk_index, *array);
return array;
}
-void PaintController::DisplayItemListAsJSON::AppendSubsequenceAsJSON(
- size_t start_item,
- size_t end_item,
+void PaintController::DisplayItemListAsJSON::AppendChunksAsJSON(
+ wtf_size_t start_chunk_index,
+ wtf_size_t end_chunk_index,
JSONArray& json_array) {
- DCHECK(end_item > start_item);
- if (current_chunk_ == chunks_.end()) {
- // We are in the middle of painting with incomplete chunks.
- auto json_object = std::make_unique<JSONObject>();
- json_object->SetString("chunk", "incomplete");
- json_object->SetArray(
- "displayItems", list_.SubsequenceAsJSON(start_item, end_item, flags_));
- json_array.PushObject(std::move(json_object));
- return;
- }
-
- DCHECK(current_chunk_->begin_index == start_item);
- while (current_chunk_ != chunks_.end() &&
- current_chunk_->end_index <= end_item) {
- const auto& chunk = *current_chunk_;
+ DCHECK_GT(end_chunk_index, start_chunk_index);
+ for (auto i = start_chunk_index; i < end_chunk_index; ++i) {
+ const auto& chunk = chunks_[i];
auto json_object = std::make_unique<JSONObject>();
json_object->SetString(
"chunk", ClientName(chunk.id.client) + " " + chunk.id.ToString());
json_object->SetString("state", chunk.properties.ToString());
+ json_object->SetString("bounds", chunk.bounds.ToString());
if (flags_ & DisplayItemList::kShowPaintRecords)
json_object->SetString("chunkData", chunk.ToString());
json_object->SetArray(
"displayItems",
- list_.SubsequenceAsJSON(chunk.begin_index, chunk.end_index, flags_));
+ list_.DisplayItemsAsJSON(chunk.begin_index, chunk.end_index, flags_));
json_array.PushObject(std::move(json_object));
- ++current_chunk_;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
index 098e3f3182e..cacaa2c7a95 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
@@ -565,7 +565,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
FakeDisplayItemClient root("root");
auto root_properties = DefaultPaintChunkProperties();
PaintChunk::Id root_id(root, DisplayItem::kCaret);
- GetPaintController().UpdateCurrentPaintChunkProperties(root_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
root_properties);
DrawRect(context, root, kBackgroundType, FloatRect(100, 100, 100, 100));
@@ -575,7 +575,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
{
SubsequenceRecorder r(context, container);
GetPaintController().UpdateCurrentPaintChunkProperties(
- container_id, container_properties);
+ &container_id, container_properties);
DrawRect(context, container, kBackgroundType,
FloatRect(100, 100, 100, 100));
DrawRect(context, container, kForegroundType,
@@ -595,7 +595,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
IsPaintChunk(3, 4, PaintChunk::Id(root, kForegroundType),
root_properties)));
- GetPaintController().UpdateCurrentPaintChunkProperties(root_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&root_id,
root_properties);
DrawRect(context, root, kBackgroundType, FloatRect(100, 100, 100, 100));
EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(container));
@@ -631,7 +631,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
{
GetPaintController().UpdateCurrentPaintChunkProperties(
- container1_id, container1_properties);
+ &container1_id, container1_properties);
SubsequenceRecorder r(context, container1);
DrawRect(context, container1, kBackgroundType,
@@ -643,7 +643,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
}
{
GetPaintController().UpdateCurrentPaintChunkProperties(
- container2_id, container2_properties);
+ &container2_id, container2_properties);
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType,
@@ -666,15 +666,10 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
IsSameId(&content2, kForegroundType),
IsSameId(&container2, kForegroundType)));
- auto* markers = GetSubsequenceMarkers(container1);
- CHECK(markers);
- EXPECT_EQ(0u, markers->start);
- EXPECT_EQ(4u, markers->end);
-
- markers = GetSubsequenceMarkers(container2);
- CHECK(markers);
- EXPECT_EQ(4u, markers->start);
- EXPECT_EQ(8u, markers->end);
+ EXPECT_SUBSEQUENCE(container1, 0, 1);
+ EXPECT_NO_SUBSEQUENCE(content1);
+ EXPECT_SUBSEQUENCE(container2, 1, 2);
+ EXPECT_NO_SUBSEQUENCE(content2);
EXPECT_THAT(
GetPaintController().PaintChunks(),
@@ -685,13 +680,13 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
// than that of |container2|.
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
// When under-invalidation-checking is enabled,
- // useCachedSubsequenceIfPossible is forced off, and the client is expected
+ // UseCachedSubsequenceIfPossible is forced off, and the client is expected
// to create the same painting as in the previous paint.
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container2));
{
GetPaintController().UpdateCurrentPaintChunkProperties(
- container2_id, container2_properties);
+ &container2_id, container2_properties);
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType,
@@ -707,7 +702,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
context, container1));
{
GetPaintController().UpdateCurrentPaintChunkProperties(
- container1_id, container1_properties);
+ &container1_id, container1_properties);
SubsequenceRecorder r(context, container1);
DrawRect(context, container1, kBackgroundType,
@@ -746,15 +741,10 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
IsSameId(&content1, kForegroundType),
IsSameId(&container1, kForegroundType)));
- markers = GetSubsequenceMarkers(container2);
- CHECK(markers);
- EXPECT_EQ(0u, markers->start);
- EXPECT_EQ(4u, markers->end);
-
- markers = GetSubsequenceMarkers(container1);
- CHECK(markers);
- EXPECT_EQ(4u, markers->start);
- EXPECT_EQ(8u, markers->end);
+ EXPECT_SUBSEQUENCE(container1, 1, 2);
+ EXPECT_NO_SUBSEQUENCE(content1);
+ EXPECT_SUBSEQUENCE(container2, 0, 1);
+ EXPECT_NO_SUBSEQUENCE(content2);
EXPECT_THAT(
GetPaintController().PaintChunks(),
@@ -763,12 +753,15 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
}
TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
- FakeDisplayItemClient root("root", IntRect(0, 0, 300, 300));
FakeDisplayItemClient content1("content1", IntRect(100, 100, 50, 200));
FakeDisplayItemClient container2("container2", IntRect(100, 200, 100, 100));
FakeDisplayItemClient content2("content2", IntRect(100, 200, 50, 200));
GraphicsContext context(GetPaintController());
+ PaintChunk::Id content1_id(content1, kBackgroundType);
+ PaintChunk::Id container2_id(container2, kBackgroundType);
+ PaintChunk::Id content2_id(content2, kBackgroundType);
+
InitRootChunk();
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
@@ -792,17 +785,26 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
IsSameId(&container2, kForegroundType),
IsSameId(&content1, kForegroundType)));
- auto* markers = GetSubsequenceMarkers(container2);
- CHECK(markers);
- EXPECT_EQ(1u, markers->start);
- EXPECT_EQ(5u, markers->end);
+ EXPECT_NO_SUBSEQUENCE(content1);
+ EXPECT_SUBSEQUENCE(container2, 1, 2);
+ EXPECT_NO_SUBSEQUENCE(content2);
+
+ EXPECT_THAT(
+ GetPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 1, DefaultRootChunkId(),
+ DefaultPaintChunkProperties()),
+ IsPaintChunk(1, 5, PaintChunk::Id(container2, kBackgroundType),
+ DefaultPaintChunkProperties()),
+ IsPaintChunk(5, 6, PaintChunk::Id(content1, kForegroundType),
+ DefaultPaintChunkProperties())));
// Simulate the situation when |container2| gets a z-index that is smaller
// than that of |content1|.
InitRootChunk();
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
// When under-invalidation-checking is enabled,
- // useCachedSubsequenceIfPossible is forced off, and the client is expected
+ // UseCachedSubsequenceIfPossible is forced off, and the client is expected
// to create the same painting as in the previous paint.
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container2));
@@ -846,22 +848,29 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
IsSameId(&content1, kBackgroundType),
IsSameId(&content1, kForegroundType)));
- markers = GetSubsequenceMarkers(container2);
- CHECK(markers);
- EXPECT_EQ(0u, markers->start);
- EXPECT_EQ(4u, markers->end);
+ EXPECT_NO_SUBSEQUENCE(content1);
+ EXPECT_SUBSEQUENCE(container2, 0, 1);
+ EXPECT_NO_SUBSEQUENCE(content2);
+
+ EXPECT_THAT(
+ GetPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 4, PaintChunk::Id(container2, kBackgroundType),
+ DefaultPaintChunkProperties()),
+ IsPaintChunk(4, 6, PaintChunk::Id(content1, kBackgroundType),
+ DefaultPaintChunkProperties())));
}
TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
GraphicsContext context(GetPaintController());
FakeDisplayItemClient root("root");
- constexpr size_t kFragmentCount = 3;
+ constexpr wtf_size_t kFragmentCount = 3;
FakeDisplayItemClient container("container");
// The first paint.
auto paint_container = [this, &context, &container]() {
SubsequenceRecorder r(context, container);
- for (size_t i = 0; i < kFragmentCount; ++i) {
+ for (wtf_size_t i = 0; i < kFragmentCount; ++i) {
ScopedDisplayItemFragment scoped_fragment(context, i);
ScopedPaintChunkProperties content_chunk_properties(
GetPaintController(), DefaultPaintChunkProperties(), container,
@@ -936,11 +945,11 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
auto container2_properties = DefaultPaintChunkProperties();
container2_properties.SetEffect(*container2_effect);
- GetPaintController().UpdateCurrentPaintChunkProperties(container1_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
container1_properties);
DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(container2_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
container2_properties);
DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
@@ -958,12 +967,12 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
IsPaintChunk(2, 4, container2_id, container2_properties)));
// Move content2 into container1, without invalidation.
- GetPaintController().UpdateCurrentPaintChunkProperties(container1_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container1_id,
container1_properties);
DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
- GetPaintController().UpdateCurrentPaintChunkProperties(container2_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&container2_id,
container2_properties);
DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
@@ -1051,34 +1060,34 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
{
SubsequenceRecorder r(context, container1);
GetPaintController().UpdateCurrentPaintChunkProperties(
- container1_background_id, container1_background_properties);
+ &container1_background_id, container1_background_properties);
DrawRect(context, container1, kBackgroundType,
FloatRect(100, 100, 100, 100));
{
SubsequenceRecorder r(context, content1);
GetPaintController().UpdateCurrentPaintChunkProperties(
- content1_id, content1_properties);
+ &content1_id, content1_properties);
DrawRect(context, content1, kBackgroundType,
FloatRect(100, 100, 50, 200));
DrawRect(context, content1, kForegroundType,
FloatRect(100, 100, 50, 200));
}
GetPaintController().UpdateCurrentPaintChunkProperties(
- container1_foreground_id, container1_foreground_properties);
+ &container1_foreground_id, container1_foreground_properties);
DrawRect(context, container1, kForegroundType,
FloatRect(100, 100, 100, 100));
}
{
SubsequenceRecorder r(context, container2);
GetPaintController().UpdateCurrentPaintChunkProperties(
- container2_background_id, container2_background_properties);
+ &container2_background_id, container2_background_properties);
DrawRect(context, container2, kBackgroundType,
FloatRect(100, 200, 100, 100));
{
SubsequenceRecorder r(context, content2);
GetPaintController().UpdateCurrentPaintChunkProperties(
- content2_id, content2_properties);
+ &content2_id, content2_properties);
DrawRect(context, content2, kBackgroundType,
FloatRect(100, 200, 50, 200));
}
@@ -1093,25 +1102,10 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
IsSameId(&container2, kBackgroundType),
IsSameId(&content2, kBackgroundType)));
- auto* markers = GetSubsequenceMarkers(container1);
- CHECK(markers);
- EXPECT_EQ(0u, markers->start);
- EXPECT_EQ(4u, markers->end);
-
- markers = GetSubsequenceMarkers(content1);
- CHECK(markers);
- EXPECT_EQ(1u, markers->start);
- EXPECT_EQ(3u, markers->end);
-
- markers = GetSubsequenceMarkers(container2);
- CHECK(markers);
- EXPECT_EQ(4u, markers->start);
- EXPECT_EQ(6u, markers->end);
-
- markers = GetSubsequenceMarkers(content2);
- CHECK(markers);
- EXPECT_EQ(5u, markers->start);
- EXPECT_EQ(6u, markers->end);
+ EXPECT_SUBSEQUENCE(container1, 0, 3);
+ EXPECT_SUBSEQUENCE(content1, 1, 2);
+ EXPECT_SUBSEQUENCE(container2, 3, 5);
+ EXPECT_SUBSEQUENCE(content2, 4, 5);
EXPECT_THAT(
GetPaintController().PaintChunks(),
@@ -1139,7 +1133,7 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
// Content2 now outputs foreground only.
{
SubsequenceRecorder r(context, content2);
- GetPaintController().UpdateCurrentPaintChunkProperties(content2_id,
+ GetPaintController().UpdateCurrentPaintChunkProperties(&content2_id,
content2_properties);
DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
}
@@ -1151,13 +1145,13 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
// Use cached subsequence of content1.
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
// When under-invalidation-checking is enabled,
- // useCachedSubsequenceIfPossible is forced off, and the client is
+ // UseCachedSubsequenceIfPossible is forced off, and the client is
// expected to create the same painting as in the previous paint.
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, content1));
SubsequenceRecorder r(context, content1);
GetPaintController().UpdateCurrentPaintChunkProperties(
- content1_id, content1_properties);
+ &content1_id, content1_properties);
DrawRect(context, content1, kBackgroundType,
FloatRect(100, 100, 50, 200));
DrawRect(context, content1, kForegroundType,
@@ -1167,7 +1161,7 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
context, content1));
}
GetPaintController().UpdateCurrentPaintChunkProperties(
- container1_foreground_id, container1_foreground_properties);
+ &container1_foreground_id, container1_foreground_properties);
DrawRect(context, container1, kForegroundType,
FloatRect(100, 100, 100, 100));
}
@@ -1188,20 +1182,10 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
IsSameId(&content1, kForegroundType),
IsSameId(&container1, kForegroundType)));
- markers = GetSubsequenceMarkers(content2);
- CHECK(markers);
- EXPECT_EQ(0u, markers->start);
- EXPECT_EQ(1u, markers->end);
-
- markers = GetSubsequenceMarkers(container1);
- CHECK(markers);
- EXPECT_EQ(1u, markers->start);
- EXPECT_EQ(4u, markers->end);
-
- markers = GetSubsequenceMarkers(content1);
- CHECK(markers);
- EXPECT_EQ(1u, markers->start);
- EXPECT_EQ(3u, markers->end);
+ EXPECT_NO_SUBSEQUENCE(container2);
+ EXPECT_SUBSEQUENCE(content2, 0, 1);
+ EXPECT_SUBSEQUENCE(container1, 1, 3);
+ EXPECT_SUBSEQUENCE(content1, 1, 2);
EXPECT_THAT(GetPaintController().PaintChunks(),
ElementsAre(IsPaintChunk(0, 1, content2_id, content2_properties),
@@ -1637,9 +1621,7 @@ TEST_P(PaintControllerTest, DuplicatedSubsequences) {
#if DCHECK_IS_ON()
EXPECT_DEATH(paint_duplicated_subsequences(),
"Multiple subsequences for client: \"test\"");
- return;
-#endif
-
+#else
// The following is for non-DCHECK path. No security CHECK should trigger.
paint_duplicated_subsequences();
// Paint again.
@@ -1658,6 +1640,37 @@ TEST_P(PaintControllerTest, DuplicatedSubsequences) {
DrawRect(context, client, kForegroundType, FloatRect(100, 100, 100, 100));
}
CommitAndFinishCycle();
+#endif
+}
+
+TEST_P(PaintControllerTest, DeletedClientInUnderInvaldiatedSubsequence) {
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
+ return;
+
+ FakeDisplayItemClient container("container");
+ auto content = std::make_unique<FakeDisplayItemClient>("content");
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ {
+ SubsequenceRecorder r(context, container);
+ DrawRect(context, *content, kBackgroundType, FloatRect(100, 100, 300, 300));
+ }
+ CommitAndFinishCycle();
+
+ content = nullptr;
+ InitRootChunk();
+ // Leave container not invalidated.
+#if DCHECK_IS_ON()
+ ASSERT_DEATH(
+ SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container),
+ "");
+#else
+ // This should not crash.
+ EXPECT_TRUE(
+ SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container));
+ CommitAndFinishCycle();
+#endif
}
class PaintControllerUnderInvalidationTest
@@ -1863,7 +1876,7 @@ TEST_F(PaintControllerUnderInvalidationTest, MoreDrawingInSubsequence) {
TEST_F(PaintControllerUnderInvalidationTest, LessDrawingInSubsequence) {
EXPECT_DEATH(TestLessDrawingInSubsequence(),
"In cached subsequence for first.*"
- "under-invalidation: new subsequence wrong length");
+ "under-invalidation: chunk changed");
}
TEST_F(PaintControllerUnderInvalidationTest, InvalidationInSubsequence) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
index 11f903de4e0..3f1b1142cce 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
@@ -8,6 +8,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
@@ -47,7 +48,7 @@ class PaintControllerTestBase : public testing::Test {
void InitRootChunk() { InitRootChunk(GetPaintController()); }
void InitRootChunk(PaintController& paint_controller) {
paint_controller.UpdateCurrentPaintChunkProperties(
- root_paint_chunk_id_, DefaultPaintChunkProperties());
+ &root_paint_chunk_id_, DefaultPaintChunkProperties());
}
const PaintChunk::Id DefaultRootChunkId() const {
return root_paint_chunk_id_;
@@ -55,20 +56,20 @@ class PaintControllerTestBase : public testing::Test {
PaintController& GetPaintController() { return *paint_controller_; }
- size_t NumCachedNewItems() const {
+ wtf_size_t NumCachedNewItems() const {
return paint_controller_->num_cached_new_items_;
}
- size_t NumCachedNewSubsequences() const {
+ wtf_size_t NumCachedNewSubsequences() const {
return paint_controller_->num_cached_new_subsequences_;
}
#if DCHECK_IS_ON()
- size_t NumIndexedItems() const {
+ wtf_size_t NumIndexedItems() const {
return paint_controller_->num_indexed_items_;
}
- size_t NumSequentialMatches() const {
+ wtf_size_t NumSequentialMatches() const {
return paint_controller_->num_sequential_matches_;
}
- size_t NumOutOfOrderMatches() const {
+ wtf_size_t NumOutOfOrderMatches() const {
return paint_controller_->num_out_of_order_matches_;
}
#endif
@@ -116,22 +117,42 @@ MATCHER_P2(IsSameId, client, type, "") {
// ELementsAre(IsPaintChunk(0, 1, id1, properties1),
// IsPaintChunk(1, 3, id2, properties2)));
inline bool CheckChunk(const PaintChunk& chunk,
- size_t begin,
- size_t end,
+ wtf_size_t begin,
+ wtf_size_t end) {
+ return chunk.begin_index == begin && chunk.end_index == end;
+}
+inline bool CheckChunk(const PaintChunk& chunk,
+ wtf_size_t begin,
+ wtf_size_t end,
const PaintChunk::Id& id,
const PropertyTreeState& properties,
- const HitTestData* hit_test_data = nullptr) {
+ const HitTestData* hit_test_data = nullptr,
+ const IntRect* bounds = nullptr) {
return chunk.begin_index == begin && chunk.end_index == end &&
chunk.id == id && chunk.properties == properties &&
((!chunk.hit_test_data && !hit_test_data) ||
(chunk.hit_test_data && hit_test_data &&
- *chunk.hit_test_data == *hit_test_data));
+ *chunk.hit_test_data == *hit_test_data)) &&
+ (!bounds || chunk.bounds == *bounds);
+}
+MATCHER_P2(IsPaintChunk, begin, end, "") {
+ return CheckChunk(arg, begin, end);
}
MATCHER_P4(IsPaintChunk, begin, end, id, properties, "") {
return CheckChunk(arg, begin, end, id, properties);
}
MATCHER_P5(IsPaintChunk, begin, end, id, properties, hit_test_data, "") {
- return CheckChunk(arg, begin, end, id, properties, &hit_test_data);
+ return CheckChunk(arg, begin, end, id, properties, hit_test_data);
+}
+MATCHER_P6(IsPaintChunk,
+ begin,
+ end,
+ id,
+ properties,
+ hit_test_data,
+ bounds,
+ "") {
+ return CheckChunk(arg, begin, end, id, properties, hit_test_data, &bounds);
}
// Shorter names for frequently used display item types in tests.
@@ -140,9 +161,22 @@ const DisplayItem::Type kForegroundType =
static_cast<DisplayItem::Type>(DisplayItem::kDrawingPaintPhaseFirst + 5);
const DisplayItem::Type kDocumentBackgroundType =
DisplayItem::kDocumentBackground;
-const DisplayItem::Type kScrollHitTestType = DisplayItem::kScrollHitTest;
const DisplayItem::Type kClipType = DisplayItem::kClipPaintPhaseFirst;
+#define EXPECT_SUBSEQUENCE(client, expected_start_chunk_index, \
+ expected_end_chunk_index) \
+ do { \
+ auto* subsequence = GetSubsequenceMarkers(client); \
+ ASSERT_NE(nullptr, subsequence); \
+ EXPECT_EQ(static_cast<wtf_size_t>(expected_start_chunk_index), \
+ subsequence->start_chunk_index); \
+ EXPECT_EQ(static_cast<wtf_size_t>(expected_end_chunk_index), \
+ subsequence->end_chunk_index); \
+ } while (false)
+
+#define EXPECT_NO_SUBSEQUENCE(client) \
+ EXPECT_EQ(nullptr, GetSubsequenceMarkers(client))
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CONTROLLER_TEST_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc
index 85133e1a387..3228623d6bd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc
@@ -32,16 +32,11 @@ class PaintPropertyNodeTest : public testing::Test {
// grandchild1 grandchild2
transform.root = &TransformPaintPropertyNode::Root();
- transform.ancestor =
- CreateTransform(*transform.root, TransformationMatrix());
- transform.child1 =
- CreateTransform(*transform.ancestor, TransformationMatrix());
- transform.child2 =
- CreateTransform(*transform.ancestor, TransformationMatrix());
- transform.grandchild1 =
- CreateTransform(*transform.child1, TransformationMatrix());
- transform.grandchild2 =
- CreateTransform(*transform.child2, TransformationMatrix());
+ transform.ancestor = Create2DTranslation(*transform.root, 0, 0);
+ transform.child1 = Create2DTranslation(*transform.ancestor, 0, 0);
+ transform.child2 = Create2DTranslation(*transform.ancestor, 0, 0);
+ transform.grandchild1 = Create2DTranslation(*transform.child1, 0, 0);
+ transform.grandchild2 = Create2DTranslation(*transform.child2, 0, 0);
clip.root = &ClipPaintPropertyNode::Root();
clip.ancestor =
@@ -321,8 +316,7 @@ TEST_F(PaintPropertyNodeTest, ChangeDirectCompositingReason) {
ResetAllChanged();
ExpectUnchangedState();
TransformPaintPropertyNode::State state;
- state.direct_compositing_reasons =
- CompositingReason::kActiveTransformAnimation;
+ state.direct_compositing_reasons = CompositingReason::kWillChangeTransform;
transform.child1->Update(*transform.ancestor, std::move(state));
EXPECT_CHANGE_EQ(PaintPropertyChangeType::kChangedOnlyNonRerasterValues,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
index b7b3241f107..58b6468fa91 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
@@ -16,11 +16,6 @@ PaintRecordBuilder::PaintRecordBuilder(
PaintController* paint_controller,
paint_preview::PaintPreviewTracker* tracker)
: paint_controller_(nullptr) {
- GraphicsContext::DisabledMode disabled_mode =
- GraphicsContext::kNothingDisabled;
- if (containing_context && containing_context->ContextDisabled())
- disabled_mode = GraphicsContext::kFullyDisabled;
-
if (paint_controller) {
paint_controller_ = paint_controller;
} else {
@@ -30,10 +25,10 @@ PaintRecordBuilder::PaintRecordBuilder(
}
paint_controller_->UpdateCurrentPaintChunkProperties(
- base::nullopt, PropertyTreeState::Root());
+ nullptr, PropertyTreeState::Root());
- context_ = std::make_unique<GraphicsContext>(
- *paint_controller_, disabled_mode, metafile, tracker);
+ context_ =
+ std::make_unique<GraphicsContext>(*paint_controller_, metafile, tracker);
if (containing_context) {
context_->SetDarkMode(containing_context->dark_mode_settings());
context_->SetDeviceScaleFactor(containing_context->DeviceScaleFactor());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
index 690447f4d70..94372310848 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
@@ -12,9 +12,11 @@ const PropertyTreeState& PropertyTreeState::Uninitialized() {
DEFINE_STATIC_REF(const TransformPaintPropertyNode, transform,
TransformPaintPropertyNode::Create(
TransformPaintPropertyNode::Root(), {}));
- DEFINE_STATIC_REF(const ClipPaintPropertyNode, clip,
- ClipPaintPropertyNode::Create(ClipPaintPropertyNode::Root(),
- {transform}));
+ DEFINE_STATIC_REF(
+ const ClipPaintPropertyNode, clip,
+ ClipPaintPropertyNode::Create(
+ ClipPaintPropertyNode::Root(),
+ ClipPaintPropertyNode::State(transform, FloatRoundedRect())));
DEFINE_STATIC_REF(const EffectPaintPropertyNode, effect,
EffectPaintPropertyNode::Create(
EffectPaintPropertyNode::Root(), {transform}));
@@ -49,6 +51,14 @@ String PropertyTreeState::ToTreeString() const {
#endif
+std::unique_ptr<JSONObject> PropertyTreeState::ToJSON() const {
+ std::unique_ptr<JSONObject> result = std::make_unique<JSONObject>();
+ result->SetObject("transform", transform_->ToJSON());
+ result->SetObject("clip", clip_->ToJSON());
+ result->SetObject("effect", effect_->ToJSON());
+ return result;
+}
+
size_t PropertyTreeState::CacheMemoryUsageInBytes() const {
return Clip().CacheMemoryUsageInBytes() +
Transform().CacheMemoryUsageInBytes();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
index 5fa7473122c..d8ac00926b3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
@@ -79,6 +79,7 @@ class PLATFORM_EXPORT PropertyTreeState {
// Dumps the tree from this state up to the root as a string.
String ToTreeString() const;
#endif
+ std::unique_ptr<JSONObject> ToJSON() const;
// Returns memory usage of the transform & clip caches of this state plus
// ancestors.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc
index 1a65460c14d..b987497e0fd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc
@@ -78,47 +78,48 @@ static bool CompareRasterInvalidationInfo(const RasterInvalidationInfo& a,
return a.reason < b.reason;
}
-void RasterInvalidationTracking::AsJSON(JSONObject* json) const {
+void RasterInvalidationTracking::AsJSON(JSONObject* json, bool detailed) const {
if (!invalidations_.IsEmpty()) {
// Sort to make the output more readable and easier to see the differences
// by a human.
- auto sorted_invalidations = invalidations_;
- std::sort(sorted_invalidations.begin(), sorted_invalidations.end(),
- &CompareRasterInvalidationInfo);
- auto paint_invalidations_json = std::make_unique<JSONArray>();
- for (auto& info : sorted_invalidations) {
- auto info_json = std::make_unique<JSONObject>();
- info_json->SetString("object", info.client_debug_name);
- if (!info.rect.IsEmpty()) {
- if (info.rect == LayoutRect::InfiniteIntRect())
- info_json->SetString("rect", "infinite");
- else
- info_json->SetArray("rect", RectAsJSONArray(info.rect));
+ auto sorted = invalidations_;
+ std::sort(sorted.begin(), sorted.end(), &CompareRasterInvalidationInfo);
+ auto invalidations_json = std::make_unique<JSONArray>();
+ IntRect last_rect;
+ for (auto* it = sorted.begin(); it != sorted.end(); it++) {
+ const auto& info = *it;
+ if (detailed) {
+ auto info_json = std::make_unique<JSONObject>();
+ info_json->SetArray("rect", RectAsJSONArray(info.rect));
+ info_json->SetString("object", info.client_debug_name);
+ info_json->SetString("reason",
+ PaintInvalidationReasonToString(info.reason));
+ invalidations_json->PushObject(std::move(info_json));
+ } else if (std::none_of(sorted.begin(), it, [&info](auto& previous) {
+ return previous.rect.Contains(info.rect);
+ })) {
+ invalidations_json->PushArray(RectAsJSONArray(info.rect));
+ last_rect = info.rect;
}
- info_json->SetString("reason",
- PaintInvalidationReasonToString(info.reason));
- paint_invalidations_json->PushObject(std::move(info_json));
}
- json->SetArray("paintInvalidations", std::move(paint_invalidations_json));
+ json->SetArray("invalidations", std::move(invalidations_json));
}
if (!under_invalidations_.IsEmpty()) {
- auto under_paint_invalidations_json = std::make_unique<JSONArray>();
- for (auto& under_paint_invalidation : under_invalidations_) {
- auto under_paint_invalidation_json = std::make_unique<JSONObject>();
- under_paint_invalidation_json->SetDouble("x", under_paint_invalidation.x);
- under_paint_invalidation_json->SetDouble("y", under_paint_invalidation.y);
- under_paint_invalidation_json->SetString(
+ auto under_invalidations_json = std::make_unique<JSONArray>();
+ for (auto& under_invalidation : under_invalidations_) {
+ auto under_invalidation_json = std::make_unique<JSONObject>();
+ under_invalidation_json->SetDouble("x", under_invalidation.x);
+ under_invalidation_json->SetDouble("y", under_invalidation.y);
+ under_invalidation_json->SetString(
"oldPixel",
- Color(under_paint_invalidation.old_pixel).NameForLayoutTreeAsText());
- under_paint_invalidation_json->SetString(
+ Color(under_invalidation.old_pixel).NameForLayoutTreeAsText());
+ under_invalidation_json->SetString(
"newPixel",
- Color(under_paint_invalidation.new_pixel).NameForLayoutTreeAsText());
- under_paint_invalidations_json->PushObject(
- std::move(under_paint_invalidation_json));
+ Color(under_invalidation.new_pixel).NameForLayoutTreeAsText());
+ under_invalidations_json->PushObject(std::move(under_invalidation_json));
}
- json->SetArray("underPaintInvalidations",
- std::move(under_paint_invalidations_json));
+ json->SetArray("underInvalidations", std::move(under_invalidations_json));
}
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
index 94bf0a526ce..29047835625 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
@@ -95,7 +95,7 @@ class PLATFORM_EXPORT RasterInvalidationTracking {
sk_sp<PaintRecord> new_record,
const IntRect& new_interest_rect);
- void AsJSON(JSONObject*) const;
+ void AsJSON(JSONObject*, bool detailed) const;
void AddToLayerDebugInfo(cc::LayerDebugInfo&) const;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
index a7033cf5adb..54f8b52e774 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
@@ -48,7 +48,7 @@ void RasterInvalidator::SetTracksRasterInvalidations(bool should_track) {
}
}
-const PaintChunk& RasterInvalidator::GetOldChunk(size_t index) const {
+const PaintChunk& RasterInvalidator::GetOldChunk(wtf_size_t index) const {
DCHECK(old_paint_artifact_);
const auto& old_chunk_info = old_paint_chunks_info_[index];
const auto& old_chunk =
@@ -60,13 +60,14 @@ const PaintChunk& RasterInvalidator::GetOldChunk(size_t index) const {
return old_chunk;
}
-size_t RasterInvalidator::MatchNewChunkToOldChunk(const PaintChunk& new_chunk,
- size_t old_index) const {
- for (size_t i = old_index; i < old_paint_chunks_info_.size(); i++) {
+wtf_size_t RasterInvalidator::MatchNewChunkToOldChunk(
+ const PaintChunk& new_chunk,
+ wtf_size_t old_index) const {
+ for (wtf_size_t i = old_index; i < old_paint_chunks_info_.size(); i++) {
if (new_chunk.Matches(GetOldChunk(i)))
return i;
}
- for (size_t i = 0; i < old_index; i++) {
+ for (wtf_size_t i = 0; i < old_index; i++) {
if (new_chunk.Matches(GetOldChunk(i)))
return i;
}
@@ -170,6 +171,7 @@ bool ShouldSkipForRasterInvalidation(const PaintArtifact& paint_artifact,
// common cases that most of the chunks can be matched in-order, the complexity
// is slightly larger than O(n).
void RasterInvalidator::GenerateRasterInvalidations(
+ RasterInvalidationFunction function,
const PaintArtifact& new_paint_artifact,
const PaintChunkSubset& new_chunks,
const PropertyTreeState& layer_state,
@@ -179,8 +181,8 @@ void RasterInvalidator::GenerateRasterInvalidations(
visual_rect_subpixel_offset);
Vector<bool> old_chunks_matched;
old_chunks_matched.resize(old_paint_chunks_info_.size());
- size_t old_index = 0;
- size_t max_matched_old_index = 0;
+ wtf_size_t old_index = 0;
+ wtf_size_t max_matched_old_index = 0;
for (auto it = new_chunks.begin(); it != new_chunks.end(); ++it) {
const auto& new_chunk = *it;
if (ShouldSkipForRasterInvalidation(new_paint_artifact, new_chunk))
@@ -189,23 +191,26 @@ void RasterInvalidator::GenerateRasterInvalidations(
mapper.SwitchToChunk(new_chunk);
auto& new_chunk_info = new_chunks_info.emplace_back(*this, mapper, it);
- // Foreign layers take care of raster invalidation by themselves.
- if (DisplayItem::IsForeignLayerType(new_chunk.id.type))
+ // Foreign layers and GraphicsLayers take care of raster invalidation by
+ // themselves.
+ if (DisplayItem::IsGraphicsLayerWrapperType(new_chunk.id.type) ||
+ DisplayItem::IsForeignLayerType(new_chunk.id.type)) {
continue;
+ }
if (!new_chunk.is_cacheable) {
- AddRasterInvalidation(new_chunk_info.bounds_in_layer, new_chunk.id.client,
- PaintInvalidationReason::kChunkUncacheable,
- kClientIsNew);
+ AddRasterInvalidation(
+ function, new_chunk_info.bounds_in_layer, new_chunk.id.client,
+ PaintInvalidationReason::kChunkUncacheable, kClientIsNew);
continue;
}
- size_t matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index);
+ auto matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index);
if (matched_old_index == kNotFound) {
// The new chunk doesn't match any old chunk.
- AddRasterInvalidation(new_chunk_info.bounds_in_layer, new_chunk.id.client,
- PaintInvalidationReason::kChunkAppeared,
- kClientIsNew);
+ AddRasterInvalidation(
+ function, new_chunk_info.bounds_in_layer, new_chunk.id.client,
+ PaintInvalidationReason::kChunkAppeared, kClientIsNew);
continue;
}
@@ -229,10 +234,10 @@ void RasterInvalidator::GenerateRasterInvalidations(
// Invalidate both old and new bounds of the chunk if the chunk's paint
// properties changed, or is moved backward and may expose area that was
// previously covered by it.
- AddRasterInvalidation(old_chunk_info.bounds_in_layer, new_chunk.id.client,
- reason, kClientIsNew);
+ AddRasterInvalidation(function, old_chunk_info.bounds_in_layer,
+ new_chunk.id.client, reason, kClientIsNew);
if (old_chunk_info.bounds_in_layer != new_chunk_info.bounds_in_layer) {
- AddRasterInvalidation(new_chunk_info.bounds_in_layer,
+ AddRasterInvalidation(function, new_chunk_info.bounds_in_layer,
new_chunk.id.client, reason, kClientIsNew);
}
// Ignore the display item raster invalidations because we have fully
@@ -246,12 +251,12 @@ void RasterInvalidator::GenerateRasterInvalidations(
old_chunk_info.chunk_to_layer_transform;
if (reason == PaintInvalidationReason::kIncremental) {
- IncrementallyInvalidateChunk(old_chunk_info, new_chunk_info,
+ IncrementallyInvalidateChunk(function, old_chunk_info, new_chunk_info,
new_chunk.id.client);
}
if (&new_paint_artifact != old_paint_artifact_) {
- DisplayItemRasterInvalidator(*this, *old_paint_artifact_,
+ DisplayItemRasterInvalidator(*this, function, *old_paint_artifact_,
new_paint_artifact, old_chunk, new_chunk,
mapper)
.Generate();
@@ -265,7 +270,7 @@ void RasterInvalidator::GenerateRasterInvalidations(
}
// Invalidate remaining unmatched (disappeared or uncacheable) old chunks.
- for (size_t i = 0; i < old_paint_chunks_info_.size(); ++i) {
+ for (wtf_size_t i = 0; i < old_paint_chunks_info_.size(); ++i) {
if (old_chunks_matched[i])
continue;
@@ -273,19 +278,20 @@ void RasterInvalidator::GenerateRasterInvalidations(
auto reason = old_chunk.is_cacheable
? PaintInvalidationReason::kChunkDisappeared
: PaintInvalidationReason::kChunkUncacheable;
- AddRasterInvalidation(old_paint_chunks_info_[i].bounds_in_layer,
+ AddRasterInvalidation(function, old_paint_chunks_info_[i].bounds_in_layer,
old_chunk.id.client, reason, kClientIsOld);
}
}
void RasterInvalidator::IncrementallyInvalidateChunk(
+ RasterInvalidationFunction function,
const PaintChunkInfo& old_chunk_info,
const PaintChunkInfo& new_chunk_info,
const DisplayItemClient& client) {
SkRegion diff(old_chunk_info.bounds_in_layer);
diff.op(new_chunk_info.bounds_in_layer, SkRegion::kXOR_Op);
for (SkRegion::Iterator it(diff); !it.done(); it.next()) {
- AddRasterInvalidation(IntRect(it.rect()), client,
+ AddRasterInvalidation(function, IntRect(it.rect()), client,
PaintInvalidationReason::kIncremental, kClientIsNew);
}
}
@@ -308,16 +314,19 @@ RasterInvalidationTracking& RasterInvalidator::EnsureTracking() {
}
void RasterInvalidator::Generate(
+ RasterInvalidationFunction raster_invalidation_function,
scoped_refptr<const PaintArtifact> new_paint_artifact,
const gfx::Rect& layer_bounds,
const PropertyTreeState& layer_state,
const FloatSize& visual_rect_subpixel_offset,
const DisplayItemClient* layer_client) {
- Generate(new_paint_artifact, new_paint_artifact->PaintChunks(), layer_bounds,
- layer_state, visual_rect_subpixel_offset, layer_client);
+ Generate(raster_invalidation_function, new_paint_artifact,
+ new_paint_artifact->PaintChunks(), layer_bounds, layer_state,
+ visual_rect_subpixel_offset, layer_client);
}
void RasterInvalidator::Generate(
+ RasterInvalidationFunction raster_invalidation_function,
scoped_refptr<const PaintArtifact> new_paint_artifact,
const PaintChunkSubset& paint_chunks,
const gfx::Rect& layer_bounds,
@@ -352,7 +361,8 @@ void RasterInvalidator::Generate(
layer_client ? *layer_client : paint_chunks[0].id.client);
}
} else {
- GenerateRasterInvalidations(*new_paint_artifact, paint_chunks, layer_state,
+ GenerateRasterInvalidations(raster_invalidation_function,
+ *new_paint_artifact, paint_chunks, layer_state,
visual_rect_subpixel_offset, new_chunks_info);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
index 55229e99ca1..35b7fabef0c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
@@ -27,10 +27,7 @@ class PLATFORM_EXPORT RasterInvalidator {
using RasterInvalidationFunction =
base::RepeatingCallback<void(const IntRect&)>;
- RasterInvalidator(RasterInvalidationFunction raster_invalidation_function)
- : raster_invalidation_function_(std::move(raster_invalidation_function)) {
- DCHECK(!raster_invalidation_function_.is_null());
- }
+ RasterInvalidator() = default;
void SetTracksRasterInvalidations(bool);
RasterInvalidationTracking* GetTracking() const {
@@ -41,7 +38,8 @@ class PLATFORM_EXPORT RasterInvalidator {
// Generate raster invalidations for all of the changed paint chunks and
// display items in the paint artifact.
- void Generate(scoped_refptr<const PaintArtifact>,
+ void Generate(RasterInvalidationFunction,
+ scoped_refptr<const PaintArtifact>,
const gfx::Rect& layer_bounds,
const PropertyTreeState& layer_state,
const FloatSize& visual_rect_subpixel_offset = FloatSize(),
@@ -49,7 +47,8 @@ class PLATFORM_EXPORT RasterInvalidator {
// Generate raster invalidations for a subset of the paint chunks in the
// paint artifact.
- void Generate(scoped_refptr<const PaintArtifact>,
+ void Generate(RasterInvalidationFunction,
+ scoped_refptr<const PaintArtifact>,
const PaintChunkSubset&,
const gfx::Rect& layer_bounds,
const PropertyTreeState& layer_state,
@@ -77,7 +76,7 @@ class PLATFORM_EXPORT RasterInvalidator {
id(chunk_it->id),
#endif
bounds_in_layer(invalidator.ClipByLayerBounds(
- mapper.MapVisualRect(chunk_it->bounds))),
+ mapper.MapVisualRect(chunk_it->drawable_bounds))),
chunk_to_layer_clip(mapper.ClipRect()),
chunk_to_layer_transform(mapper.Transform()) {
}
@@ -85,7 +84,7 @@ class PLATFORM_EXPORT RasterInvalidator {
// The index of the chunk in the PaintArtifact. It may be different from
// the index of this PaintChunkInfo in paint_chunks_info_ when a subset of
// the paint chunks is handled by the RasterInvalidator.
- size_t index_in_paint_artifact;
+ wtf_size_t index_in_paint_artifact;
#if DCHECK_IS_ON()
PaintChunk::Id id;
@@ -96,17 +95,19 @@ class PLATFORM_EXPORT RasterInvalidator {
SkMatrix chunk_to_layer_transform;
};
- void GenerateRasterInvalidations(const PaintArtifact&,
+ void GenerateRasterInvalidations(RasterInvalidationFunction,
+ const PaintArtifact&,
const PaintChunkSubset&,
const PropertyTreeState& layer_state,
const FloatSize& visual_rect_subpixel_offset,
Vector<PaintChunkInfo>& new_chunks_info);
- ALWAYS_INLINE const PaintChunk& GetOldChunk(size_t index) const;
- ALWAYS_INLINE size_t MatchNewChunkToOldChunk(const PaintChunk& new_chunk,
- size_t old_index) const;
+ ALWAYS_INLINE const PaintChunk& GetOldChunk(wtf_size_t index) const;
+ ALWAYS_INLINE wtf_size_t MatchNewChunkToOldChunk(const PaintChunk& new_chunk,
+ wtf_size_t old_index) const;
ALWAYS_INLINE void IncrementallyInvalidateChunk(
+ RasterInvalidationFunction,
const PaintChunkInfo& old_chunk_info,
const PaintChunkInfo& new_chunk_info,
const DisplayItemClient&);
@@ -115,13 +116,14 @@ class PLATFORM_EXPORT RasterInvalidator {
// get DebugName() directly or should get from |tracking_info_
// ->old_client_debug_names|.
enum ClientIsOldOrNew { kClientIsOld, kClientIsNew };
- void AddRasterInvalidation(const IntRect& rect,
+ void AddRasterInvalidation(RasterInvalidationFunction function,
+ const IntRect& rect,
const DisplayItemClient& client,
PaintInvalidationReason reason,
ClientIsOldOrNew old_or_new) {
if (rect.IsEmpty())
return;
- raster_invalidation_function_.Run(rect);
+ function.Run(rect);
if (tracking_info_)
TrackRasterInvalidation(rect, client, reason, old_or_new);
}
@@ -146,7 +148,6 @@ class PLATFORM_EXPORT RasterInvalidator {
void TrackImplicitFullLayerInvalidation(const DisplayItemClient&);
- RasterInvalidationFunction raster_invalidation_function_;
gfx::Rect layer_bounds_;
Vector<PaintChunkInfo> old_paint_chunks_info_;
scoped_refptr<const PaintArtifact> old_paint_artifact_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
index f4ad986d71a..d4598f77c81 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
@@ -6,6 +6,7 @@
#include <utility>
#include "base/bind_helpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
@@ -13,6 +14,8 @@
#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/test_paint_artifact.h"
+using testing::ElementsAre;
+
namespace blink {
static const IntRect kDefaultLayerBounds(-9999, -7777, 18888, 16666);
@@ -20,7 +23,7 @@ static const IntRect kDefaultLayerBounds(-9999, -7777, 18888, 16666);
class RasterInvalidatorTest : public testing::Test,
public PaintTestConfigurations {
public:
- RasterInvalidatorTest() : invalidator_(base::DoNothing()) {}
+ RasterInvalidatorTest() = default;
static PropertyTreeState DefaultPropertyTreeState() {
return PropertyTreeState::Root();
@@ -47,58 +50,60 @@ class RasterInvalidatorTest : public testing::Test,
return invalidator_.GetTracking()->Invalidations();
}
- using MapFunction = base::RepeatingCallback<void(IntRect&)>;
- static IntRect ChunkRectToLayer(
- const IntRect& rect,
- const IntPoint& layer_offset,
- const MapFunction& mapper = base::DoNothing()) {
- auto r = rect;
- mapper.Run(r);
- r.MoveBy(layer_offset);
- return r;
- }
-
RasterInvalidator invalidator_;
};
INSTANTIATE_PAINT_TEST_SUITE_P(RasterInvalidatorTest);
-#define EXPECT_CHUNK_INVALIDATION_CUSTOM( \
- invalidations, index, chunk, expected_reason, layer_offset, mapper) \
- do { \
- const auto& info = (invalidations)[index]; \
- EXPECT_EQ(ChunkRectToLayer((chunk).bounds, layer_offset, mapper), \
- info.rect); \
- EXPECT_EQ(&(chunk).id.client, info.client); \
- EXPECT_EQ(expected_reason, info.reason); \
- } while (false)
-
-#define EXPECT_CHUNK_INVALIDATION(invalidations, index, chunk, reason) \
- EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, index, chunk, reason, \
- -kDefaultLayerBounds.Location(), \
- base::DoNothing())
-
-#define EXPECT_INCREMENTAL_INVALIDATION(invalidations, index, chunk, \
- chunk_rect) \
- do { \
- const auto& info = (invalidations)[index]; \
- EXPECT_EQ(ChunkRectToLayer(chunk_rect, -kDefaultLayerBounds.Location()), \
- info.rect); \
- EXPECT_EQ(&(chunk).id.client, info.client); \
- EXPECT_EQ(PaintInvalidationReason::kIncremental, info.reason); \
- } while (false)
+using MapFunction = base::RepeatingCallback<void(IntRect&)>;
+static IntRect ChunkRectToLayer(const IntRect& rect,
+ const IntPoint& layer_offset,
+ const MapFunction& mapper = base::DoNothing()) {
+ auto r = rect;
+ mapper.Run(r);
+ r.MoveBy(layer_offset);
+ return r;
+}
+
+static bool CheckChunkInvalidation(
+ const RasterInvalidationInfo& info,
+ const PaintChunk& chunk,
+ const IntRect& chunk_rect,
+ PaintInvalidationReason reason,
+ const IntPoint& layer_offset,
+ const MapFunction& mapper = base::DoNothing()) {
+ return ChunkRectToLayer(chunk_rect, layer_offset, mapper) == info.rect &&
+ &chunk.id.client == info.client && reason == info.reason;
+}
+
+MATCHER_P4(ChunkInvalidation, chunk, reason, layer_offset, mapper, "") {
+ return CheckChunkInvalidation(arg, *chunk, chunk->drawable_bounds, reason,
+ layer_offset, mapper);
+}
+
+MATCHER_P2(ChunkInvalidation, chunk, reason, "") {
+ return CheckChunkInvalidation(arg, *chunk, chunk->drawable_bounds, reason,
+ -kDefaultLayerBounds.Location());
+}
+
+MATCHER_P2(IncrementalInvalidation, chunk, chunk_rect, "") {
+ return CheckChunkInvalidation(arg, *chunk, chunk_rect,
+ PaintInvalidationReason::kIncremental,
+ -kDefaultLayerBounds.Location());
+}
TEST_P(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
auto artifact = TestPaintArtifact().Chunk(0).Build();
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_EQ(IntRect(IntPoint(), kDefaultLayerBounds.Size()),
- invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFullLayer, invalidations[0].reason);
+ const auto& client = artifact->PaintChunks()[0].id.client;
+ EXPECT_THAT(TrackedRasterInvalidations(),
+ ElementsAre(RasterInvalidationInfo{
+ &client, client.DebugName(),
+ IntRect(IntPoint(), kDefaultLayerBounds.Size()),
+ PaintInvalidationReason::kFullLayer}));
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(false);
}
@@ -106,34 +111,35 @@ TEST_P(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
TEST_P(RasterInvalidatorTest, LayerBounds) {
auto artifact = TestPaintArtifact().Chunk(0).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
// No raster invalidations needed if layer origin doesn't change.
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
auto new_layer_bounds = kDefaultLayerBounds;
new_layer_bounds.Move(66, 77);
- invalidator_.Generate(artifact, new_layer_bounds, DefaultPropertyTreeState());
+ invalidator_.Generate(base::DoNothing(), artifact, new_layer_bounds,
+ DefaultPropertyTreeState());
// Change of layer origin causes change of chunk0's transform to layer.
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(2u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty);
- EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 1, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -new_layer_bounds.Location(),
- base::DoNothing());
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(
+ ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty),
+ ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -new_layer_bounds.Location(), base::DoNothing())));
FinishCycle(*artifact);
}
TEST_P(RasterInvalidatorTest, ReorderChunks) {
auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
FinishCycle(*artifact);
@@ -145,23 +151,23 @@ TEST_P(RasterInvalidatorTest, ReorderChunks) {
.Chunk(1)
.Bounds(IntRect(11, 22, 33, 44))
.Build();
- invalidator_.Generate(new_artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), new_artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(2u, invalidations.size());
// Invalidated new chunk 2's old (as artifact->PaintChunks()[1]) and new
// (as new_artifact->PaintChunks()[2]) bounds.
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[1],
- PaintInvalidationReason::kChunkReordered);
- EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[2],
- PaintInvalidationReason::kChunkReordered);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkReordered),
+ ChunkInvalidation(&new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkReordered)));
FinishCycle(*new_artifact);
}
TEST_P(RasterInvalidatorTest, ReorderChunkSubsequences) {
auto artifact =
TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Chunk(3).Chunk(4).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
FinishCycle(*artifact);
@@ -175,63 +181,98 @@ TEST_P(RasterInvalidatorTest, ReorderChunkSubsequences) {
.Bounds(IntRect(11, 22, 33, 44))
.Chunk(2)
.Build();
- invalidator_.Generate(new_artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), new_artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(3u, invalidations.size());
// Invalidated new chunk 3's old (as artifact->PaintChunks()[1] and new
// (as new_artifact->PaintChunks()[3]) bounds.
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[1],
- PaintInvalidationReason::kChunkReordered);
- EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[3],
- PaintInvalidationReason::kChunkReordered);
// Invalidated new chunk 4's new bounds. Didn't invalidate old bounds because
// it's the same as the new bounds.
- EXPECT_CHUNK_INVALIDATION(invalidations, 2, new_artifact->PaintChunks()[4],
- PaintInvalidationReason::kChunkReordered);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkReordered),
+ ChunkInvalidation(&new_artifact->PaintChunks()[3],
+ PaintInvalidationReason::kChunkReordered),
+ ChunkInvalidation(&new_artifact->PaintChunks()[4],
+ PaintInvalidationReason::kChunkReordered)));
FinishCycle(*new_artifact);
}
TEST_P(RasterInvalidatorTest, ChunkAppearAndDisappear) {
auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
FinishCycle(*artifact);
// Chunk 1 and 2 disappeared, 3 and 4 appeared.
invalidator_.SetTracksRasterInvalidations(true);
auto new_artifact = TestPaintArtifact().Chunk(0).Chunk(3).Chunk(4).Build();
- invalidator_.Generate(new_artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), new_artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(
+ ChunkInvalidation(&new_artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkAppeared),
+ ChunkInvalidation(&new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkAppeared),
+ ChunkInvalidation(&artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkDisappeared),
+ ChunkInvalidation(&artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkDisappeared)));
+ FinishCycle(*new_artifact);
+}
+
+TEST_P(RasterInvalidatorTest, InvalidateDrawableBounds) {
+ IntRect drawable_bounds(11, 22, 33, 44);
+ IntRect bounds(0, 0, 100, 100);
+ auto artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Chunk(1)
+ .Bounds(bounds)
+ .DrawableBounds(drawable_bounds)
+ .Build();
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ auto new_artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Chunk(2)
+ .Bounds(bounds)
+ .DrawableBounds(drawable_bounds)
+ .Build();
+ invalidator_.Generate(base::DoNothing(), new_artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(4u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact->PaintChunks()[1],
- PaintInvalidationReason::kChunkAppeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[2],
- PaintInvalidationReason::kChunkAppeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 2, artifact->PaintChunks()[1],
- PaintInvalidationReason::kChunkDisappeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 3, artifact->PaintChunks()[2],
- PaintInvalidationReason::kChunkDisappeared);
+ // ChunkInvalidation uses the drawable_bounds. We expect raster invalidations
+ // based on drawable_bounds instead of bounds.
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(
+ ChunkInvalidation(&new_artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkAppeared),
+ ChunkInvalidation(&artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkDisappeared)));
FinishCycle(*new_artifact);
}
TEST_P(RasterInvalidatorTest, ChunkAppearAtEnd) {
auto artifact = TestPaintArtifact().Chunk(0).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
auto new_artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
- invalidator_.Generate(new_artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), new_artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(2u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact->PaintChunks()[1],
- PaintInvalidationReason::kChunkAppeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[2],
- PaintInvalidationReason::kChunkAppeared);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&new_artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkAppeared),
+ ChunkInvalidation(&new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkAppeared)));
FinishCycle(*new_artifact);
}
@@ -239,21 +280,22 @@ TEST_P(RasterInvalidatorTest, UncacheableChunks) {
auto artifact =
TestPaintArtifact().Chunk(0).Chunk(1).Uncacheable().Chunk(2).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
auto new_artifact =
TestPaintArtifact().Chunk(0).Chunk(2).Chunk(1).Uncacheable().Build();
- invalidator_.Generate(new_artifact, kDefaultLayerBounds,
+ invalidator_.Generate(base::DoNothing(), new_artifact, kDefaultLayerBounds,
DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(2u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact->PaintChunks()[2],
- PaintInvalidationReason::kChunkUncacheable);
- EXPECT_CHUNK_INVALIDATION(invalidations, 1, artifact->PaintChunks()[1],
- PaintInvalidationReason::kChunkUncacheable);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(
+ ChunkInvalidation(&new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkUncacheable),
+ ChunkInvalidation(&artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkUncacheable)));
FinishCycle(*new_artifact);
}
@@ -275,7 +317,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
.Properties(t0(), *clip2, e0())
.Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change both clip0 and clip2.
@@ -288,13 +331,14 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
ClipPaintPropertyNode::State{&clip2->LocalTransformSpace(),
new_clip_rect});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
// Property change in the layer state should not trigger raster invalidation.
// |clip2| change should trigger raster invalidation.
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[2],
- PaintInvalidationReason::kPaintProperty);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[2],
+ PaintInvalidationReason::kPaintProperty)));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
@@ -309,11 +353,12 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
.Build();
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(new_artifact1, kDefaultLayerBounds, layer_state);
- const auto& invalidations1 = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations1.size());
- EXPECT_CHUNK_INVALIDATION(invalidations1, 0, new_artifact1->PaintChunks()[1],
- PaintInvalidationReason::kPaintProperty);
+ invalidator_.Generate(base::DoNothing(), new_artifact1, kDefaultLayerBounds,
+ layer_state);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&new_artifact1->PaintChunks()[1],
+ PaintInvalidationReason::kPaintProperty)));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*new_artifact1);
}
@@ -334,7 +379,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
.Bounds(EnclosingIntRect(clip_rect.Rect()))
.Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change clip1 to bigger, which is still bound by clip0, resulting no actual
@@ -345,7 +391,8 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
ClipPaintPropertyNode::State{&clip1->LocalTransformSpace(),
new_clip_rect1});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
@@ -355,18 +402,19 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
ClipPaintPropertyNode::State{&clip1->LocalTransformSpace(),
new_clip_rect2});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(4u, invalidations.size());
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
// |clip1| change should trigger incremental raster invalidation.
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 0, artifact->PaintChunks()[1],
- IntRect(-1000, -1000, 2000, 500));
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 1, artifact->PaintChunks()[1],
- IntRect(-1000, -500, 500, 1000));
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 2, artifact->PaintChunks()[1],
- IntRect(500, -500, 500, 1000));
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 3, artifact->PaintChunks()[1],
- IntRect(-1000, 500, 2000, 500));
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(IncrementalInvalidation(&artifact->PaintChunks()[1],
+ IntRect(-1000, -1000, 2000, 500)),
+ IncrementalInvalidation(&artifact->PaintChunks()[1],
+ IntRect(-1000, -500, 500, 1000)),
+ IncrementalInvalidation(&artifact->PaintChunks()[1],
+ IntRect(500, -500, 500, 1000)),
+ IncrementalInvalidation(&artifact->PaintChunks()[1],
+ IntRect(-1000, 500, 2000, 500))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
@@ -377,12 +425,12 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
new_clip_rect3});
invalidator_.SetTracksRasterInvalidations(true);
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations1 = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations1.size());
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
// |clip1| change should trigger incremental raster invalidation.
- EXPECT_INCREMENTAL_INVALIDATION(invalidations1, 0, artifact->PaintChunks()[1],
- IntRect(500, -500, 500, 1000));
+ EXPECT_THAT(TrackedRasterInvalidations(),
+ ElementsAre(IncrementalInvalidation(
+ &artifact->PaintChunks()[1], IntRect(500, -500, 500, 1000))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
}
@@ -402,21 +450,22 @@ TEST_P(RasterInvalidatorTest, ClipPropertyChangeWithOutsetForRasterEffects) {
.OutsetForRasterEffects(2)
.Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
FloatRoundedRect new_clip_rect(-2000, -2000, 4000, 4000);
clip->Update(c0(), ClipPaintPropertyNode::State{&t0(), new_clip_rect});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
auto mapper = [](IntRect& r) { r.Inflate(2); };
- EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(),
- base::BindRepeating(mapper));
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(
+ &artifact->PaintChunks()[0], PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(), base::BindRepeating(mapper))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
}
@@ -434,7 +483,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
auto artifact =
TestPaintArtifact().Chunk(0).Properties(*t2, *c1, e0()).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change both t1 and t2 but keep t1*t2 unchanged, to test change of
@@ -443,11 +493,12 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty)));
invalidator_.SetTracksRasterInvalidations(false);
}
@@ -468,7 +519,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
auto artifact =
TestPaintArtifact().Chunk(0).Properties(*t2, *c1, e0()).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change both t1 and t2 but keep t1*t2 unchanged.
@@ -476,7 +528,8 @@ TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
}
@@ -494,7 +547,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
.Properties(*transform1, c0(), e0())
.Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change layer_transform should not cause raster invalidation in the layer.
@@ -503,7 +557,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
*layer_transform->Parent(),
TransformPaintPropertyNode::State{TransformationMatrix().Scale(10)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
@@ -516,7 +571,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
transform0->Update(*new_layer_transform, TransformPaintPropertyNode::State{
transform0->Translation2D()});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
@@ -526,7 +582,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
transform0->Update(layer_state.Transform(), TransformPaintPropertyNode::State{
transform0->Translation2D()});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
@@ -540,19 +597,20 @@ TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
TransformPaintPropertyNode::State{
transform1->Translation2D() + FloatSize(-20, -30)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(2u, invalidations.size());
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
auto mapper0 = [](IntRect& r) { r.Move(10, 20); };
- EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(),
- base::BindRepeating(mapper0));
auto mapper1 = [](IntRect& r) { r.Move(30, 50); };
- EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 1, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(),
- base::BindRepeating(mapper1));
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(),
+ base::BindRepeating(mapper0)),
+ ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(),
+ base::BindRepeating(mapper1))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
}
@@ -567,7 +625,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
.Properties(*chunk_transform, c0(), e0())
.Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change chunk_transform by tiny difference, which should be ignored.
@@ -579,7 +638,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
.Scale(1.0000001)
.Rotate(0.0000001)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
@@ -593,7 +653,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
.Translate(0.0000001, -0.0000001)
.Scale(1.0000001)
.Rotate(0.0000001)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
invalidated = !TrackedRasterInvalidations().IsEmpty();
FinishCycle(*artifact);
}
@@ -613,7 +674,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
.Bounds(chunk_bounds)
.Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Scale change from 1e-6 to 2e-6 should be treated as significant.
@@ -622,7 +684,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
layer_state.Transform(),
TransformPaintPropertyNode::State{TransformationMatrix().Scale(2e-6)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_FALSE(TrackedRasterInvalidations().IsEmpty());
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
@@ -633,7 +696,8 @@ TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
TransformPaintPropertyNode::State{
TransformationMatrix().Scale(2e-6 + 1e-15)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
@@ -650,7 +714,8 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
auto artifact =
TestPaintArtifact().Chunk(0).Properties(*t2, c0(), *e1).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change both t1 and t2 but keep t1*t2 unchanged, to test change of
@@ -659,14 +724,14 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
auto mapper = [](IntRect& r) { r.Inflate(60); };
- EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location(),
- base::BindRepeating(mapper));
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(
+ &artifact->PaintChunks()[0], PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(), base::BindRepeating(mapper))));
invalidator_.SetTracksRasterInvalidations(false);
FinishCycle(*artifact);
}
@@ -686,7 +751,8 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
auto artifact =
TestPaintArtifact().Chunk(0).Properties(*t2, c0(), *e1).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
// Change both t1 and t2 but keep t1*t2 unchanged.
@@ -694,7 +760,8 @@ TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
t1->Update(t0(), TransformPaintPropertyNode::State{FloatSize(-10, -20)});
t2->Update(*t1, TransformPaintPropertyNode::State{FloatSize(10, 20)});
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
EXPECT_TRUE(TrackedRasterInvalidations().IsEmpty());
FinishCycle(*artifact);
}
@@ -711,7 +778,8 @@ TEST_P(RasterInvalidatorTest, AliasEffectParentChanges) {
PropertyTreeState chunk_state(t0(), c0(), *alias_effect);
auto artifact = TestPaintArtifact().Chunk(0).Properties(chunk_state).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
@@ -721,11 +789,12 @@ TEST_P(RasterInvalidatorTest, AliasEffectParentChanges) {
// We expect to get invalidations since the effect unaliased effect is
// actually different now.
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty)));
FinishCycle(*artifact);
}
@@ -742,7 +811,8 @@ TEST_P(RasterInvalidatorTest, NestedAliasEffectParentChanges) {
PropertyTreeState chunk_state(t0(), c0(), *alias_effect_2);
auto artifact = TestPaintArtifact().Chunk(0).Properties(chunk_state).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
@@ -753,11 +823,12 @@ TEST_P(RasterInvalidatorTest, NestedAliasEffectParentChanges) {
// We expect to get invalidations since the effect unaliased effect is
// actually different now.
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty)));
FinishCycle(*artifact);
}
@@ -775,7 +846,8 @@ TEST_P(RasterInvalidatorTest, EffectWithAliasTransformWhoseParentChanges) {
PropertyTreeState chunk_state(t0(), c0(), *e1);
auto artifact = TestPaintArtifact().Chunk(0).Properties(chunk_state).Build();
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
FinishCycle(*artifact);
invalidator_.SetTracksRasterInvalidations(true);
@@ -785,11 +857,12 @@ TEST_P(RasterInvalidatorTest, EffectWithAliasTransformWhoseParentChanges) {
// We expect to get invalidations since the effect unaliased effect is
// actually different now.
- invalidator_.Generate(artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations();
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty);
+ invalidator_.Generate(base::DoNothing(), artifact, kDefaultLayerBounds,
+ layer_state);
+ EXPECT_THAT(
+ TrackedRasterInvalidations(),
+ ElementsAre(ChunkInvalidation(&artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty)));
FinishCycle(*artifact);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h
index 334ca46377b..23ff52e3096 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h
@@ -13,7 +13,7 @@
namespace blink {
class ScopedDisplayItemFragment final {
- DISALLOW_NEW();
+ STACK_ALLOCATED();
public:
ScopedDisplayItemFragment(GraphicsContext& context, unsigned fragment)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_hint.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_hint.h
new file mode 100644
index 00000000000..5d4e7190e26
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_hint.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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_PAINT_CHUNK_HINT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_PAINT_CHUNK_HINT_H_
+
+#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
+
+namespace blink {
+
+// Hints for new paint chunks for a scope during paint. Will create new paint
+// chunks if we create any display items in the paint scope and
+// - paint chunk properties are different from the current chunk, or
+// - If the client's visual rect isn't fully contained by the current chunk's
+// bounds. This is a heuristic to create only paint chunks that are meaningful
+// to CompositeAfterPaint layerization, i.e. avoid unnecessary forced paint
+// chunks that will definitely be merged into the previous paint chunk.
+// Hinted paint chunks are never required for correctness and rendering should
+// be the same without this class. These hints are for performance: by causing
+// additional paint chunks (while avoiding some unnecessary ones) with explicit
+// ids, we can improve raster invalidation and layerization.
+class ScopedPaintChunkHint {
+ STACK_ALLOCATED();
+
+ public:
+ ScopedPaintChunkHint(PaintController& paint_controller,
+ const DisplayItemClient& client,
+ DisplayItem::Type type)
+ : ScopedPaintChunkHint(paint_controller,
+ paint_controller.CurrentPaintChunkProperties(),
+ client,
+ type) {}
+
+ ScopedPaintChunkHint(PaintController& paint_controller,
+ const PropertyTreeState& properties,
+ const DisplayItemClient& client,
+ DisplayItem::Type type)
+ : paint_controller_(paint_controller),
+ previous_num_chunks_(paint_controller_.NumNewChunks()),
+ previous_force_new_chunk_(paint_controller_.WillForceNewChunk()) {
+ if (!previous_force_new_chunk_ && previous_num_chunks_ &&
+ !paint_controller_.LastChunkBounds().Contains(client.VisualRect()))
+ paint_controller_.SetForceNewChunk(true);
+ // This is after SetForceNewChunk(true) so that the possible new chunk will
+ // use the specified id.
+ paint_chunk_properties_.emplace(paint_controller, properties, client, type);
+ }
+
+ ~ScopedPaintChunkHint() {
+ paint_chunk_properties_ = base::nullopt;
+ if (!HasCreatedPaintChunk())
+ paint_controller_.SetForceNewChunk(previous_force_new_chunk_);
+ }
+
+ bool HasCreatedPaintChunk() const {
+ DCHECK_GE(paint_controller_.NumNewChunks(), previous_num_chunks_);
+ return paint_controller_.NumNewChunks() > previous_num_chunks_;
+ }
+
+ private:
+ PaintController& paint_controller_;
+ // This is actually always emplaced, but is wrapped in base::Optional<> to
+ // control its lifetime related to SetForceNewChunk().
+ base::Optional<ScopedPaintChunkProperties> paint_chunk_properties_;
+ wtf_size_t previous_num_chunks_;
+ bool previous_force_new_chunk_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_PAINT_CHUNK_HINT_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
index 0b0b87f5456..4df836d70c6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_PAINT_CHUNK_PROPERTIES_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -16,7 +15,7 @@
namespace blink {
class ScopedPaintChunkProperties {
- DISALLOW_NEW();
+ STACK_ALLOCATED();
public:
// Use new PropertyTreeState for the scope.
@@ -26,8 +25,8 @@ class ScopedPaintChunkProperties {
DisplayItem::Type type)
: paint_controller_(paint_controller),
previous_properties_(paint_controller.CurrentPaintChunkProperties()) {
- paint_controller_.UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(client, type), properties);
+ PaintChunk::Id id(client, type);
+ paint_controller_.UpdateCurrentPaintChunkProperties(&id, properties);
}
// Use new transform state, and keep the current other properties.
@@ -69,7 +68,7 @@ class ScopedPaintChunkProperties {
// ScopedPaintChunkProperties. The painter should create another scope of
// paint properties with new id, or the new chunk will use the id of the
// first display item as its id.
- paint_controller_.UpdateCurrentPaintChunkProperties(base::nullopt,
+ paint_controller_.UpdateCurrentPaintChunkProperties(nullptr,
previous_properties_);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
deleted file mode 100644
index 3c8cd82d14a..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-
-ScrollHitTestDisplayItem::ScrollHitTestDisplayItem(
- const DisplayItemClient& client,
- DisplayItem::Type type,
- const TransformPaintPropertyNode* scroll_offset_node,
- const IntRect& scroll_container_bounds)
- : DisplayItem(client, type, sizeof(*this)),
- scroll_offset_node_(scroll_offset_node),
- scroll_container_bounds_(scroll_container_bounds) {
-#if DCHECK_IS_ON()
- if (type == DisplayItem::Type::kResizerScrollHitTest ||
- type == DisplayItem::Type::kPluginScrollHitTest) {
- // Resizer and plugin scroll hit tests are only used to prevent composited
- // scrolling and should not have a scroll offset node.
- DCHECK(!scroll_offset_node);
- } else if (type == DisplayItem::Type::kScrollHitTest) {
- DCHECK(scroll_offset_node);
- // The scroll offset transform node should have an associated scroll node.
- DCHECK(scroll_offset_node_->ScrollNode());
- } else {
- NOTREACHED();
- }
-#endif
-}
-
-ScrollHitTestDisplayItem::~ScrollHitTestDisplayItem() = default;
-
-bool ScrollHitTestDisplayItem::Equals(const DisplayItem& other) const {
- return DisplayItem::Equals(other) &&
- scroll_offset_node() ==
- static_cast<const ScrollHitTestDisplayItem&>(other)
- .scroll_offset_node() &&
- scroll_container_bounds() ==
- static_cast<const ScrollHitTestDisplayItem&>(other)
- .scroll_container_bounds();
-}
-
-#if DCHECK_IS_ON()
-void ScrollHitTestDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetString("scrollOffsetNode", String::Format("%p", scroll_offset_node_));
- json.SetString("scrollContainerBounds", scroll_container_bounds_.ToString());
-}
-#endif
-
-void ScrollHitTestDisplayItem::Record(
- GraphicsContext& context,
- const DisplayItemClient& client,
- DisplayItem::Type type,
- const TransformPaintPropertyNode* scroll_offset_node,
- const IntRect& scroll_container_bounds) {
- PaintController& paint_controller = context.GetPaintController();
-
- // The scroll hit test should be in the non-scrolled transform space and
- // therefore should not be scrolled by the associated scroll offset.
- DCHECK_NE(&paint_controller.CurrentPaintChunkProperties().Transform(),
- scroll_offset_node);
-
- if (paint_controller.DisplayItemConstructionIsDisabled())
- return;
-
- if (paint_controller.UseCachedItemIfPossible(client, type))
- return;
-
- paint_controller.CreateAndAppend<ScrollHitTestDisplayItem>(
- client, type, scroll_offset_node, scroll_container_bounds);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
deleted file mode 100644
index b2bfbe00b4d..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_HIT_TEST_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_HIT_TEST_DISPLAY_ITEM_H_
-
-#include "base/memory/ref_counted.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-// Display item for marking a region as scrollable. This should be emitted in
-// the non-scrolling paint property tree state (in other words, this item should
-// not scroll). A display item is needed because hit testing is in paint order.
-//
-// This serves three purposes:
-// 1. Creating non-fast scrollable regions for non-composited scrollers.
-// Scrollable areas create a non-fast scrollable region in the
-// non-scrolling paint property tree state. Pre-CompositeAfterPaint, we skip
-// painting these for composited scrollers. With CompositeAfterPaint, we
-// paint the non-fast item and later ignore it if the scroller was composited
-// (see: PaintArtifactCompositor::UpdateNonFastScrollableRegions).
-//
-// 2. Creating non-fast scrollable regions for plugins and resize handles.
-// Plugins that have blocking event handlers and resize handles both need to
-// prevent composited scrolling. A different display item type is used
-// (kPluginScrollHitTest and kResizerScrollHitTest) to disambiguate multiple
-// scroll hit test display items (e.g., if a scroller is non-composited and
-// has a resizer).
-//
-// 3. Creating cc::Layers marked as being scrollable.
-// (when CompositeAfterPaint is enabled).
-// A single cc::Layer must be marked as being "scrollable", and this display
-// item is used by PaintArtifactCompositor to create the scrollable cc::Layer.
-class PLATFORM_EXPORT ScrollHitTestDisplayItem final : public DisplayItem {
- public:
- ScrollHitTestDisplayItem(const DisplayItemClient&,
- DisplayItem::Type,
- const TransformPaintPropertyNode* scroll_offset_node,
- const IntRect& scroll_container_bounds);
- ~ScrollHitTestDisplayItem() override;
-
- const TransformPaintPropertyNode* scroll_offset_node() const {
- return scroll_offset_node_;
- }
-
- const IntRect& scroll_container_bounds() const {
- return scroll_container_bounds_;
- }
-
- // DisplayItem
- bool Equals(const DisplayItem&) const override;
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
-
- // Create and append a ScrollHitTestDisplayItem onto the context. This is
- // similar to a recorder class (e.g., DrawingRecorder) but just emits a single
- // item. If no |scroll_offset_node| is passed in, this display item will only
- // be used for creating a non-fast-scrollable-region.
- static void Record(GraphicsContext&,
- const DisplayItemClient&,
- DisplayItem::Type,
- const TransformPaintPropertyNode* scroll_offset_node,
- const IntRect& scroll_container_bounds);
-
- const ScrollPaintPropertyNode* scroll_node() const {
- return scroll_offset_node_->ScrollNode();
- }
-
- private:
- // The scroll offset transform node if this ScrollHitTestDisplayItem could be
- // used for composited scrolling, or null if it is only used to prevent
- // composited scrolling.
- const TransformPaintPropertyNode* scroll_offset_node_;
- // The bounds of the scroll container, including scrollbars. We cannot use
- // scroll_node().container_rect() because it does not include scrollbars.
- const IntRect scroll_container_bounds_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_HIT_TEST_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc
index 4aa3435f851..a91ac0fa9d9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc
@@ -52,10 +52,6 @@ std::unique_ptr<JSONObject> ScrollPaintPropertyNode::ToJSON() const {
state_.main_thread_scrolling_reasons)
.c_str());
}
- if (state_.scrolls_inner_viewport)
- json->SetString("scrollsInnerViewport", "true");
- if (state_.scrolls_outer_viewport)
- json->SetString("scrollsOuterViewport", "true");
if (state_.max_scroll_offset_affected_by_page_scale)
json->SetString("maxScrollOffsetAffectedByPageScale", "true");
if (state_.compositor_element_id) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h
index c1ebe1b0f61..75e7b5c3d4b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h
@@ -43,8 +43,6 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
IntSize contents_size;
bool user_scrollable_horizontal = false;
bool user_scrollable_vertical = false;
- bool scrolls_inner_viewport = false;
- bool scrolls_outer_viewport = false;
// This bit tells the compositor whether the inner viewport should be
// scrolled using the full viewport mechanism (overscroll, top control
@@ -69,8 +67,6 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
contents_size != other.contents_size ||
user_scrollable_horizontal != other.user_scrollable_horizontal ||
user_scrollable_vertical != other.user_scrollable_vertical ||
- scrolls_inner_viewport != other.scrolls_inner_viewport ||
- scrolls_outer_viewport != other.scrolls_outer_viewport ||
prevent_viewport_scrolling_from_inner !=
other.prevent_viewport_scrolling_from_inner ||
max_scroll_offset_affected_by_page_scale !=
@@ -145,8 +141,6 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
bool UserScrollableVertical() const {
return state_.user_scrollable_vertical;
}
- bool ScrollsInnerViewport() const { return state_.scrolls_inner_viewport; }
- bool ScrollsOuterViewport() const { return state_.scrolls_outer_viewport; }
bool PreventViewportScrollingFromInner() const {
return state_.prevent_viewport_scrolling_from_inner;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
index 72d3fb4c053..eeb5932afc5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
@@ -34,6 +34,9 @@ ScrollbarDisplayItem::ScrollbarDisplayItem(
}
sk_sp<const PaintRecord> ScrollbarDisplayItem::Paint() const {
+ // We are painting a non-composited scrollbar, so we don't need layer_.
+ layer_ = nullptr;
+
if (record_) {
DCHECK(!scrollbar_->NeedsRepaintPart(cc::TRACK_BUTTONS_TICKMARKS));
DCHECK(!scrollbar_->NeedsRepaintPart(cc::THUMB));
@@ -52,7 +55,27 @@ sk_sp<const PaintRecord> ScrollbarDisplayItem::Paint() const {
return record_;
}
-scoped_refptr<cc::Layer> ScrollbarDisplayItem::CreateLayer() const {
+scoped_refptr<cc::ScrollbarLayerBase> ScrollbarDisplayItem::GetLayer() const {
+ // This function is called when the scrollbar is composited. We don't need
+ // record_ which is for non-composited scrollbars.
+ record_ = nullptr;
+
+ if (!layer_ || layer_->is_left_side_vertical_scrollbar() !=
+ scrollbar_->IsLeftSideVerticalScrollbar())
+ layer_ = CreateLayer();
+
+ layer_->SetOffsetToTransformParent(
+ gfx::Vector2dF(FloatPoint(rect_.Location())));
+ layer_->SetBounds(gfx::Size(rect_.Size()));
+
+ if (scrollbar_->NeedsRepaintPart(cc::THUMB) ||
+ scrollbar_->NeedsRepaintPart(cc::TRACK_BUTTONS_TICKMARKS))
+ layer_->SetNeedsDisplay();
+ return layer_;
+}
+
+scoped_refptr<cc::ScrollbarLayerBase> ScrollbarDisplayItem::CreateLayer()
+ const {
scoped_refptr<cc::ScrollbarLayerBase> layer;
if (scrollbar_->IsSolidColor()) {
DCHECK(scrollbar_->IsOverlay());
@@ -74,10 +97,10 @@ scoped_refptr<cc::Layer> ScrollbarDisplayItem::CreateLayer() const {
layer->SetIsDrawable(true);
layer->SetElementId(element_id_);
- if (scroll_translation_) {
- layer->SetScrollElementId(
- scroll_translation_->ScrollNode()->GetCompositorElementId());
- }
+ layer->SetScrollElementId(
+ scroll_translation_
+ ? scroll_translation_->ScrollNode()->GetCompositorElementId()
+ : CompositorElementId());
return layer;
}
@@ -114,9 +137,6 @@ void ScrollbarDisplayItem::Record(
const TransformPaintPropertyNode* scroll_translation,
CompositorElementId element_id) {
PaintController& paint_controller = context.GetPaintController();
- if (paint_controller.DisplayItemConstructionIsDisabled())
- return;
-
// Must check PaintController::UseCachedItemIfPossible before this function.
DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
!paint_controller.UseCachedItemIfPossible(client, type));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h
index c8e214c8007..1ddb96941c8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h
@@ -12,7 +12,7 @@
#include "third_party/skia/include/core/SkRefCnt.h"
namespace cc {
-class Layer;
+class ScrollbarLayerBase;
}
namespace blink {
@@ -35,8 +35,6 @@ class PLATFORM_EXPORT ScrollbarDisplayItem final : public DisplayItem {
const TransformPaintPropertyNode* scroll_translation,
CompositorElementId element_id);
- cc::Scrollbar* GetScrollbar() const { return scrollbar_.get(); }
- const IntRect& GetRect() const { return rect_; }
const TransformPaintPropertyNode* ScrollTranslation() const {
return scroll_translation_;
}
@@ -46,8 +44,8 @@ class PLATFORM_EXPORT ScrollbarDisplayItem final : public DisplayItem {
// scrollbar.
sk_sp<const PaintRecord> Paint() const;
- // Creates cc layer for composited scrollbar.
- scoped_refptr<cc::Layer> CreateLayer() const;
+ // Create or reuse the cc scrollbar layer, for composited scrollbar.
+ scoped_refptr<cc::ScrollbarLayerBase> GetLayer() const;
// DisplayItem
bool Equals(const DisplayItem&) const override;
@@ -67,12 +65,16 @@ class PLATFORM_EXPORT ScrollbarDisplayItem final : public DisplayItem {
CompositorElementId element_id);
private:
+ scoped_refptr<cc::ScrollbarLayerBase> CreateLayer() const;
+
scoped_refptr<cc::Scrollbar> scrollbar_;
IntRect rect_;
const TransformPaintPropertyNode* scroll_translation_;
CompositorElementId element_id_;
// This is lazily created for non-composited scrollbar.
mutable sk_sp<const PaintRecord> record_;
+ // This is lazily created for composited scrollbar.
+ mutable scoped_refptr<cc::ScrollbarLayerBase> layer_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc
new file mode 100644
index 00000000000..18148c28b3e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc
@@ -0,0 +1,155 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by node BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.h"
+
+#include "cc/layers/painted_overlay_scrollbar_layer.h"
+#include "cc/layers/painted_scrollbar_layer.h"
+#include "cc/layers/solid_color_scrollbar_layer.h"
+#include "cc/test/fake_scrollbar.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
+#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
+#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
+
+namespace blink {
+
+CompositorElementId ScrollbarElementId(const cc::Scrollbar& scrollbar) {
+ return CompositorElementIdFromUniqueObjectId(
+ 13579, scrollbar.Orientation() == cc::HORIZONTAL
+ ? CompositorElementIdNamespace::kHorizontalScrollbar
+ : CompositorElementIdNamespace::kVerticalScrollbar);
+}
+
+CompositorElementId ScrollElementId() {
+ return CompositorElementIdFromUniqueObjectId(
+ 24680, CompositorElementIdNamespace::kScroll);
+}
+
+scoped_refptr<TransformPaintPropertyNode> CreateScrollTranslation() {
+ ScrollPaintPropertyNode::State state{IntRect(0, 0, 100, 100),
+ IntSize(1000, 1000)};
+ state.compositor_element_id = ScrollElementId();
+ auto scroll = ScrollPaintPropertyNode::Create(ScrollPaintPropertyNode::Root(),
+ std::move(state));
+ return CreateScrollTranslation(t0(), 0, 0, *scroll);
+}
+
+TEST(ScrollbarDisplayItemTest, HorizontalSolidColorScrollbar) {
+ auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>();
+ scrollbar->set_orientation(cc::HORIZONTAL);
+ scrollbar->set_is_solid_color(true);
+ scrollbar->set_is_overlay(true);
+ scrollbar->set_track_rect(gfx::Rect(2, 90, 96, 10));
+ scrollbar->set_thumb_size(gfx::Size(30, 7));
+
+ FakeDisplayItemClient client;
+ IntRect scrollbar_rect(0, 90, 100, 10);
+ auto scroll_translation = CreateScrollTranslation();
+ auto element_id = ScrollbarElementId(*scrollbar);
+ ScrollbarDisplayItem display_item(client, DisplayItem::kScrollbarHorizontal,
+ scrollbar, scrollbar_rect,
+ scroll_translation.get(), element_id);
+ auto layer = display_item.GetLayer();
+ ASSERT_EQ(cc::ScrollbarLayerBase::kSolidColor,
+ layer->ScrollbarLayerTypeForTesting());
+ auto* scrollbar_layer =
+ static_cast<cc::SolidColorScrollbarLayer*>(layer.get());
+ EXPECT_EQ(cc::HORIZONTAL, scrollbar_layer->orientation());
+ EXPECT_EQ(7, scrollbar_layer->thumb_thickness());
+ EXPECT_EQ(2, scrollbar_layer->track_start());
+ EXPECT_EQ(element_id, scrollbar_layer->element_id());
+ EXPECT_EQ(ScrollElementId(), scrollbar_layer->scroll_element_id());
+
+ EXPECT_EQ(layer.get(), display_item.GetLayer().get());
+}
+
+TEST(ScrollbarDisplayItemTest, VerticalSolidColorScrollbar) {
+ auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>();
+ scrollbar->set_orientation(cc::VERTICAL);
+ scrollbar->set_is_solid_color(true);
+ scrollbar->set_is_overlay(true);
+ scrollbar->set_track_rect(gfx::Rect(90, 2, 10, 96));
+ scrollbar->set_thumb_size(gfx::Size(7, 30));
+
+ FakeDisplayItemClient client;
+ IntRect scrollbar_rect(90, 0, 10, 100);
+ auto scroll_translation = CreateScrollTranslation();
+ auto element_id = ScrollbarElementId(*scrollbar);
+ ScrollbarDisplayItem display_item(client, DisplayItem::kScrollbarHorizontal,
+ scrollbar, scrollbar_rect,
+ scroll_translation.get(), element_id);
+ auto layer = display_item.GetLayer();
+ ASSERT_EQ(cc::ScrollbarLayerBase::kSolidColor,
+ layer->ScrollbarLayerTypeForTesting());
+ auto* scrollbar_layer =
+ static_cast<cc::SolidColorScrollbarLayer*>(layer.get());
+ EXPECT_EQ(cc::VERTICAL, scrollbar_layer->orientation());
+ EXPECT_EQ(7, scrollbar_layer->thumb_thickness());
+ EXPECT_EQ(2, scrollbar_layer->track_start());
+ EXPECT_EQ(element_id, scrollbar_layer->element_id());
+ EXPECT_EQ(ScrollElementId(), scrollbar_layer->scroll_element_id());
+
+ EXPECT_EQ(layer.get(), display_item.GetLayer().get());
+}
+
+TEST(ScrollbarDisplayItemTest, PaintedColorScrollbar) {
+ auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>();
+
+ FakeDisplayItemClient client;
+ IntRect scrollbar_rect(0, 90, 100, 10);
+ auto scroll_translation = CreateScrollTranslation();
+ auto element_id = ScrollbarElementId(*scrollbar);
+ ScrollbarDisplayItem display_item(client, DisplayItem::kScrollbarHorizontal,
+ scrollbar, scrollbar_rect,
+ scroll_translation.get(), element_id);
+ auto layer = display_item.GetLayer();
+ ASSERT_EQ(cc::ScrollbarLayerBase::kPainted,
+ layer->ScrollbarLayerTypeForTesting());
+
+ EXPECT_EQ(layer.get(), display_item.GetLayer().get());
+}
+
+TEST(ScrollbarDisplayItemTest, PaintedColorScrollbarOverlayNonNinePatch) {
+ auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>();
+ scrollbar->set_has_thumb(true);
+ scrollbar->set_is_overlay(true);
+
+ FakeDisplayItemClient client;
+ IntRect scrollbar_rect(0, 90, 100, 10);
+ auto scroll_translation = CreateScrollTranslation();
+ auto element_id = ScrollbarElementId(*scrollbar);
+ ScrollbarDisplayItem display_item(client, DisplayItem::kScrollbarHorizontal,
+ scrollbar, scrollbar_rect,
+ scroll_translation.get(), element_id);
+ auto layer = display_item.GetLayer();
+ // We should create PaintedScrollbarLayer instead of
+ // PaintedOverlayScrollbarLayer for non-nine-patch overlay scrollbars.
+ ASSERT_EQ(cc::ScrollbarLayerBase::kPainted,
+ layer->ScrollbarLayerTypeForTesting());
+
+ EXPECT_EQ(layer.get(), display_item.GetLayer().get());
+}
+
+TEST(ScrollbarDisplayItemTest, PaintedColorScrollbarOverlayNinePatch) {
+ auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>();
+ scrollbar->set_has_thumb(true);
+ scrollbar->set_is_overlay(true);
+ scrollbar->set_uses_nine_patch_thumb_resource(true);
+
+ FakeDisplayItemClient client;
+ IntRect scrollbar_rect(0, 90, 100, 10);
+ auto scroll_translation = CreateScrollTranslation();
+ auto element_id = ScrollbarElementId(*scrollbar);
+ ScrollbarDisplayItem display_item(client, DisplayItem::kScrollbarHorizontal,
+ scrollbar, scrollbar_rect,
+ scroll_translation.get(), element_id);
+ auto layer = display_item.GetLayer();
+ ASSERT_EQ(cc::ScrollbarLayerBase::kPaintedOverlay,
+ layer->ScrollbarLayerTypeForTesting());
+
+ EXPECT_EQ(layer.get(), display_item.GetLayer().get());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h
index e2e6288cce1..1e1666c9e92 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h
@@ -21,13 +21,13 @@ class PaintController;
// of DisplayItems, and supports caching via a CachedDisplayItem with the
// CachedSubsequence DisplayItem type.
//
-// Also note that useCachedSubsequenceIfPossible is not sufficient to determine
+// Also note that UseCachedSubsequenceIfPossible is not sufficient to determine
// whether a CachedSubsequence can be used. In particular, the client is
// responsible for checking that none of the DisplayItemClients that contribute
// to the subsequence have been invalidated.
//
class SubsequenceRecorder final {
- DISALLOW_NEW();
+ STACK_ALLOCATED();
public:
static bool UseCachedSubsequenceIfPossible(GraphicsContext& context,
@@ -39,19 +39,15 @@ class SubsequenceRecorder final {
: paint_controller_(context.GetPaintController()),
client_(client),
start_(0) {
- if (!paint_controller_.DisplayItemConstructionIsDisabled())
- start_ = paint_controller_.BeginSubsequence();
+ start_ = paint_controller_.BeginSubsequence();
}
- ~SubsequenceRecorder() {
- if (!paint_controller_.DisplayItemConstructionIsDisabled())
- paint_controller_.EndSubsequence(client_, start_);
- }
+ ~SubsequenceRecorder() { paint_controller_.EndSubsequence(client_, start_); }
private:
PaintController& paint_controller_;
const DisplayItemClient& client_;
- size_t start_;
+ wtf_size_t start_;
DISALLOW_COPY_AND_ASSIGN(SubsequenceRecorder);
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
index 802a8acba3e..b44b2c24da8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
@@ -59,12 +59,8 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
// the transform is identity or a 2d translation, the translation_2d version
// should be used instead.
TransformAndOrigin(const TransformationMatrix& matrix,
- const FloatPoint3D& origin = FloatPoint3D(),
- bool disable_optimization = false) {
- if (!disable_optimization && matrix.IsIdentityOr2DTranslation())
- translation_2d_ = matrix.To2DTranslation();
- else
- matrix_and_origin_.reset(new MatrixAndOrigin{matrix, origin});
+ const FloatPoint3D& origin = FloatPoint3D()) {
+ matrix_and_origin_.reset(new MatrixAndOrigin{matrix, origin});
}
bool IsIdentityOr2DTranslation() const { return !matrix_and_origin_; }
@@ -381,6 +377,11 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
return state_.direct_compositing_reasons & CompositingReason::kRootScroller;
}
+ bool RequiresCompositingForWillChangeTransform() const {
+ return state_.direct_compositing_reasons &
+ CompositingReason::kWillChangeTransform;
+ }
+
const CompositorElementId& GetCompositorElementId() const {
return state_.compositor_element_id;
}
@@ -421,6 +422,7 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
// The scroll compositor element id should be stored on the scroll node.
DCHECK(!state_.compositor_element_id);
}
+ DCHECK(!HasActiveTransformAnimation() || !IsIdentityOr2DTranslation());
#endif
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc
index 45dbceb5bad..084304ea8cc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc
@@ -20,18 +20,16 @@ void PaintGeneratedImage::Draw(cc::PaintCanvas* canvas,
ImageDecodingMode) {
PaintCanvasAutoRestore ar(canvas, true);
canvas->clipRect(dest_rect);
- canvas->translate(dest_rect.X(), dest_rect.Y());
- if (dest_rect.Size() != src_rect.Size())
- canvas->scale(dest_rect.Width() / src_rect.Width(),
- dest_rect.Height() / src_rect.Height());
- canvas->translate(-src_rect.X(), -src_rect.Y());
+ canvas->concat(SkMatrix::MakeRectToRect(src_rect, dest_rect,
+ SkMatrix::kFill_ScaleToFit));
SkRect bounds = src_rect;
canvas->saveLayer(&bounds, &flags);
canvas->drawPicture(record_);
}
void PaintGeneratedImage::DrawTile(GraphicsContext& context,
- const FloatRect& src_rect) {
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum) {
context.DrawRecord(record_);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h
index 06fb89c4dd4..6978106580e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h
@@ -28,7 +28,9 @@ class PLATFORM_EXPORT PaintGeneratedImage : public GeneratedImage {
RespectImageOrientationEnum,
ImageClampingMode,
ImageDecodingMode) override;
- void DrawTile(GraphicsContext&, const FloatRect&) final;
+ void DrawTile(GraphicsContext&,
+ const FloatRect&,
+ RespectImageOrientationEnum) final;
PaintGeneratedImage(sk_sp<PaintRecord> record, const FloatSize& size)
: GeneratedImage(size), record_(std::move(record)) {}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
index 43a015c670f..ab027f02901 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
@@ -177,7 +177,6 @@ class PlaceholderImage::SharedFont : public RefCounted<SharedFont> {
explicit SharedFont(float scale_factor)
: font_(CreatePlaceholderFontDescription(scale_factor)),
scale_factor_(scale_factor) {
- font_.Update(nullptr);
}
~SharedFont() {
@@ -191,7 +190,6 @@ class PlaceholderImage::SharedFont : public RefCounted<SharedFont> {
scale_factor_ = scale_factor;
font_ = Font(CreatePlaceholderFontDescription(scale_factor_));
- font_.Update(nullptr);
}
const Font& font() const { return font_; }
@@ -252,8 +250,8 @@ PaintImage PlaceholderImage::PaintImageForCurrentFrame() {
PaintRecorder paint_recorder;
Draw(paint_recorder.beginRecording(FloatRect(dest_rect)), PaintFlags(),
- FloatRect(dest_rect), FloatRect(dest_rect),
- kDoNotRespectImageOrientation, kClampImageToSourceRect, kSyncDecode);
+ FloatRect(dest_rect), FloatRect(dest_rect), kRespectImageOrientation,
+ kClampImageToSourceRect, kSyncDecode);
paint_record_for_current_frame_ = paint_recorder.finishRecordingAsPicture();
paint_record_content_id_ = PaintImage::GetNextContentId();
@@ -359,13 +357,15 @@ void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
Font::kUseFallbackIfFontNotReady, 1.0f, flags);
}
-void PlaceholderImage::DrawPattern(GraphicsContext& context,
- const FloatRect& src_rect,
- const FloatSize& scale,
- const FloatPoint& phase,
- SkBlendMode mode,
- const FloatRect& dest_rect,
- const FloatSize& repeat_spacing) {
+void PlaceholderImage::DrawPattern(
+ GraphicsContext& context,
+ const FloatRect& src_rect,
+ const FloatSize& scale,
+ const FloatPoint& phase,
+ SkBlendMode mode,
+ const FloatRect& dest_rect,
+ const FloatSize& repeat_spacing,
+ RespectImageOrientationEnum respect_orientation) {
DCHECK(context.Canvas());
PaintFlags flags = context.FillFlags();
@@ -374,9 +374,8 @@ void PlaceholderImage::DrawPattern(GraphicsContext& context,
// Ignore the pattern specifications and just draw a single placeholder image
// over the whole |dest_rect|. This is done in order to prevent repeated icons
// from cluttering tiled background images.
- Draw(context.Canvas(), flags, dest_rect, src_rect,
- kDoNotRespectImageOrientation, kClampImageToSourceRect,
- kUnspecifiedDecode);
+ Draw(context.Canvas(), flags, dest_rect, src_rect, respect_orientation,
+ kClampImageToSourceRect, kUnspecifiedDecode);
}
void PlaceholderImage::DestroyDecodedData() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
index e6a2647bbba..e1e706801b4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
@@ -83,7 +83,8 @@ class PLATFORM_EXPORT PlaceholderImage final : public Image {
const FloatPoint& phase,
SkBlendMode,
const FloatRect& dest_rect,
- const FloatSize& repeat_spacing) override;
+ const FloatSize& repeat_spacing,
+ RespectImageOrientationEnum) override;
// SetData does nothing, and the passed in buffer is ignored.
SizeAvailability SetData(scoped_refptr<SharedBuffer>, bool) override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc
index 81fb9df438a..eb5c0622151 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc
@@ -75,9 +75,8 @@ void DrawImageExpectingGrayBoxOnly(PlaceholderImage& image,
EXPECT_CALL(canvas, drawTextBlob(_, _, _, _)).Times(0);
image.Draw(&canvas, PaintFlags(), dest_rect,
- FloatRect(0.0f, 0.0f, 100.0f, 100.0f),
- kDoNotRespectImageOrientation, Image::kClampImageToSourceRect,
- Image::kUnspecifiedDecode);
+ FloatRect(0.0f, 0.0f, 100.0f, 100.0f), kRespectImageOrientation,
+ Image::kClampImageToSourceRect, Image::kUnspecifiedDecode);
}
void DrawImageExpectingIconOnly(PlaceholderImage& image,
@@ -134,7 +133,6 @@ float GetExpectedPlaceholderTextWidth(const StringView& text,
description.SetWeight(FontSelectionValue(500));
Font font(description);
- font.Update(nullptr);
return font.Width(TextRun(text));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
index 1e8ae93ee66..a254d06c0cf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/skia/include/effects/SkCornerPathEffect.h"
#include "third_party/skia/include/third_party/skcms/skcms.h"
+#include "ui/base/ui_base_features.h"
#include <algorithm>
#include <cmath>
@@ -374,13 +375,19 @@ template <typename PrimitiveType>
void DrawPlatformFocusRing(const PrimitiveType& primitive,
cc::PaintCanvas* canvas,
SkColor color,
- float width) {
+ float width,
+ float border_radius) {
PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(PaintFlags::kStroke_Style);
flags.setColor(color);
flags.setStrokeWidth(width);
+ if (::features::IsFormControlsRefreshEnabled()) {
+ DrawFocusRingPrimitive(primitive, canvas, flags, border_radius);
+ return;
+ }
+
#if defined(OS_MACOSX)
flags.setAlpha(64);
const float corner_radius = (width - 1) * 0.5f;
@@ -398,14 +405,18 @@ void DrawPlatformFocusRing(const PrimitiveType& primitive,
#endif
}
-template void PLATFORM_EXPORT DrawPlatformFocusRing<SkRect>(const SkRect&,
- cc::PaintCanvas*,
- SkColor,
- float width);
-template void PLATFORM_EXPORT DrawPlatformFocusRing<SkPath>(const SkPath&,
- cc::PaintCanvas*,
- SkColor,
- float width);
+template void PLATFORM_EXPORT
+DrawPlatformFocusRing<SkRect>(const SkRect&,
+ cc::PaintCanvas*,
+ SkColor,
+ float width,
+ float border_radius);
+template void PLATFORM_EXPORT
+DrawPlatformFocusRing<SkPath>(const SkPath&,
+ cc::PaintCanvas*,
+ SkColor,
+ float width,
+ float border_radius);
sk_sp<SkData> TryAllocateSkData(size_t size) {
void* buffer = WTF::Partitions::BufferPartition()->AllocFlags(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
index b5f81ee0f40..b35b6ce5449 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
@@ -144,7 +144,8 @@ template <typename PrimitiveType>
void DrawPlatformFocusRing(const PrimitiveType&,
cc::PaintCanvas*,
SkColor,
- float width);
+ float width,
+ float border_radius);
// TODO(fmalita): remove in favor of direct SrcRectConstraint use.
inline cc::PaintCanvas::SrcRectConstraint
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
deleted file mode 100644
index f59034399e6..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/skia_texture_holder.h"
-
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
-#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
-#include "third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
-#include "third_party/skia/include/gpu/GrBackendSurface.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-
-namespace blink {
-
-namespace {
-bool IsSkImageOriginTopLeft(sk_sp<SkImage> image) {
- GrSurfaceOrigin origin;
- image->getBackendTexture(false, &origin);
- return origin == kTopLeft_GrSurfaceOrigin;
-}
-
-struct ReleaseContext {
- scoped_refptr<TextureHolder::MailboxRef> mailbox_ref;
- GLuint texture_id = 0u;
- bool is_shared_image = false;
- GrTexture* gr_texture = nullptr;
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper;
-};
-
-void ReleaseTexture(void* ctx) {
- auto* release_ctx = static_cast<ReleaseContext*>(ctx);
- if (release_ctx->context_provider_wrapper) {
- if (release_ctx->gr_texture) {
- release_ctx->context_provider_wrapper->Utils()->RemoveCachedMailbox(
- release_ctx->gr_texture);
- }
-
- if (release_ctx->texture_id) {
- auto* gl =
- release_ctx->context_provider_wrapper->ContextProvider()->ContextGL();
- if (release_ctx->is_shared_image)
- gl->EndSharedImageAccessDirectCHROMIUM(release_ctx->texture_id);
- gl->DeleteTextures(1u, &release_ctx->texture_id);
- }
- }
-
- delete release_ctx;
-}
-
-} // namespace
-
-SkiaTextureHolder::SkiaTextureHolder(
- sk_sp<SkImage> image,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper)
- : TextureHolder(std::move(context_provider_wrapper),
- base::MakeRefCounted<MailboxRef>(nullptr),
- IsSkImageOriginTopLeft(image)),
- image_(std::move(image)) {}
-
-SkiaTextureHolder::SkiaTextureHolder(
- const MailboxTextureHolder* mailbox_texture_holder,
- GLuint shared_image_texture_id)
- : TextureHolder(SharedGpuContext::ContextProviderWrapper(),
- mailbox_texture_holder->mailbox_ref(),
- mailbox_texture_holder->IsOriginTopLeft()) {
- const gpu::Mailbox mailbox = mailbox_texture_holder->GetMailbox();
- DCHECK(!shared_image_texture_id || mailbox.IsSharedImage());
- DCHECK(!shared_image_texture_id || !mailbox_texture_holder->IsCrossThread());
-
- const gpu::SyncToken sync_token = mailbox_texture_holder->GetSyncToken();
- const auto& sk_image_info = mailbox_texture_holder->sk_image_info();
- GLenum texture_target = mailbox_texture_holder->texture_target();
-
- if (!ContextProvider())
- return;
-
- gpu::gles2::GLES2Interface* shared_gl = ContextProvider()->ContextGL();
- GrContext* shared_gr_context = ContextProvider()->GetGrContext();
- DCHECK(shared_gl &&
- shared_gr_context); // context isValid already checked in callers
-
- GLuint shared_context_texture_id = 0u;
- bool should_delete_texture_on_release = true;
-
- if (shared_image_texture_id) {
- shared_context_texture_id = shared_image_texture_id;
- should_delete_texture_on_release = false;
- } else {
- shared_gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
- if (mailbox.IsSharedImage()) {
- shared_context_texture_id =
- shared_gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name);
- shared_gl->BeginSharedImageAccessDirectCHROMIUM(
- shared_context_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
- } else {
- shared_context_texture_id =
- shared_gl->CreateAndConsumeTextureCHROMIUM(mailbox.name);
- }
- }
-
- GrGLTextureInfo texture_info;
- texture_info.fTarget = texture_target;
- texture_info.fID = shared_context_texture_id;
- texture_info.fFormat =
- CanvasColorParams(sk_image_info).GLSizedInternalFormat();
- GrBackendTexture backend_texture(sk_image_info.width(),
- sk_image_info.height(), GrMipMapped::kNo,
- texture_info);
-
- GrSurfaceOrigin origin = IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin
- : kBottomLeft_GrSurfaceOrigin;
-
- auto* release_ctx = new ReleaseContext;
- release_ctx->mailbox_ref = mailbox_ref();
- if (should_delete_texture_on_release)
- release_ctx->texture_id = shared_context_texture_id;
- release_ctx->is_shared_image = mailbox.IsSharedImage();
- release_ctx->context_provider_wrapper = ContextProviderWrapper();
-
- image_ = SkImage::MakeFromTexture(
- shared_gr_context, backend_texture, origin, sk_image_info.colorType(),
- sk_image_info.alphaType(), sk_image_info.refColorSpace(), &ReleaseTexture,
- release_ctx);
- if (image_) {
- release_ctx->gr_texture = image_->getTexture();
- DCHECK(release_ctx->gr_texture);
- ContextProviderWrapper()->Utils()->RegisterMailbox(image_->getTexture(),
- mailbox);
- } else {
- ReleaseTexture(release_ctx);
- }
-}
-
-SkiaTextureHolder::~SkiaTextureHolder() {
- // Object must be destroyed on the same thread where it was created.
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-}
-
-bool SkiaTextureHolder::IsValid() const {
- return !!image_ && !!ContextProviderWrapper() &&
- image_->isValid(ContextProvider()->GetGrContext());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
deleted file mode 100644
index 4aa252996c0..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_TEXTURE_HOLDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_TEXTURE_HOLDER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "third_party/blink/renderer/platform/graphics/texture_holder.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-class MailboxTextureHolder;
-class WebGraphicsContext3DProviderWrapper;
-
-class PLATFORM_EXPORT SkiaTextureHolder final : public TextureHolder {
- public:
- ~SkiaTextureHolder() override;
-
- // TextureHolder impl.
- IntSize Size() const final {
- if (image_)
- return IntSize(image_->width(), image_->height());
- return IntSize();
- }
- bool IsValid() const final;
- bool CurrentFrameKnownToBeOpaque() const final {
- return image_ && image_->isOpaque();
- }
-
- const sk_sp<SkImage>& GetSkImage() const { return image_; }
-
- // When creating a AcceleratedStaticBitmap from a texture-backed SkImage, this
- // function will be called to create a TextureHolder object.
- SkiaTextureHolder(sk_sp<SkImage>,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&);
-
- // This function consumes the mailbox in the input parameter and turn it into
- // a texture-backed SkImage.
- // |shared_image_texture_id| is an optional texture bound to the
- // |texture_holder|'s mailbox and imported into its context. Note that if a
- // texture is provided it must:
- // 1) Be associated with a shared image mailbox.
- // 2) Stay alive and have a read lock on the shared image until the
- // |MailboxRef| is destroyed.
- SkiaTextureHolder(const MailboxTextureHolder* texture_holder,
- GLuint shared_image_texture_id);
-
- private:
- // The image_ should always be texture-backed.
- sk_sp<SkImage> image_;
-
- THREAD_CHECKER(thread_checker_);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_TEXTURE_HOLDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc
index 6605e4258a3..f1f66e3a6d3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc
@@ -56,10 +56,6 @@ constexpr SquashingDisallowedReasonStringMap
"squashingNearestFixedPositionMismatch",
"Cannot be squashed because this layer has a different nearest fixed "
"position layer than the squashing layer"},
- {SquashingDisallowedReason::kScrollChildWithCompositedDescendants,
- "scrollChildWithCompositedDescendants",
- "Squashing a scroll child with composited descendants is not "
- "supported."},
{SquashingDisallowedReason::kSquashingLayerIsAnimating,
"squashingLayerIsAnimating",
"Cannot squash into a layer that is animating."},
diff --git a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h
index 21357fae5cf..46b6e780942 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h
@@ -24,7 +24,6 @@ using SquashingDisallowedReasons = unsigned;
V(SquashingLayoutEmbeddedContentIsDisallowed) \
V(SquashingBlendingIsDisallowed) \
V(NearestFixedPositionMismatch) \
- V(ScrollChildWithCompositedDescendants) \
V(SquashingLayerIsAnimating) \
V(RenderingContextMismatch) \
V(FragmentedContent) \
diff --git a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
index ae6cb2afc46..fce932e5648 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
@@ -20,53 +20,64 @@
namespace blink {
-scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(PaintImage image) {
+scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
+ PaintImage image,
+ ImageOrientation orientation) {
DCHECK(!image.GetSkImage()->isTextureBacked());
- return UnacceleratedStaticBitmapImage::Create(std::move(image));
+ return UnacceleratedStaticBitmapImage::Create(std::move(image), orientation);
}
scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
sk_sp<SkData> data,
- const SkImageInfo& info) {
+ const SkImageInfo& info,
+ ImageOrientation orientation) {
return UnacceleratedStaticBitmapImage::Create(
- SkImage::MakeRasterData(info, std::move(data), info.minRowBytes()));
+ SkImage::MakeRasterData(info, std::move(data), info.minRowBytes()),
+ orientation);
+}
+
+IntSize StaticBitmapImage::SizeRespectingOrientation() const {
+ if (orientation_.UsesWidthAsHeight())
+ return Size().TransposedSize();
+ else
+ return Size();
}
-void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
- const PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- ImageClampingMode clamp_mode,
- const PaintImage& image) {
+void StaticBitmapImage::DrawHelper(
+ cc::PaintCanvas* canvas,
+ const PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ ImageClampingMode clamp_mode,
+ RespectImageOrientationEnum respect_orientation,
+ const PaintImage& image) {
FloatRect adjusted_src_rect = src_rect;
adjusted_src_rect.Intersect(SkRect::MakeWH(image.width(), image.height()));
if (dst_rect.IsEmpty() || adjusted_src_rect.IsEmpty())
return; // Nothing to draw.
- canvas->drawImageRect(image, adjusted_src_rect, dst_rect, &flags,
- WebCoreClampingModeToSkiaRectConstraint(clamp_mode));
-}
+ cc::PaintCanvasAutoRestore auto_restore(canvas, false);
+ FloatRect adjusted_dst_rect = dst_rect;
+ if (respect_orientation && orientation_ != kDefaultImageOrientation) {
+ canvas->save();
-scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
- sk_sp<SkColorSpace> color_space,
- SkColorType color_type) {
- DCHECK(color_space);
- sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
-
- // If we don't need to change the color type, use SkImage::makeColorSpace()
- if (skia_image->colorType() == color_type) {
- skia_image = skia_image->makeColorSpace(color_space);
- } else {
- skia_image =
- skia_image->makeColorTypeAndColorSpace(color_type, color_space);
- }
+ // ImageOrientation expects the origin to be at (0, 0)
+ canvas->translate(adjusted_dst_rect.X(), adjusted_dst_rect.Y());
+ adjusted_dst_rect.SetLocation(FloatPoint());
- if (skia_image->isTextureBacked()) {
- return AcceleratedStaticBitmapImage::CreateFromSkImage(
- skia_image, ContextProviderWrapper());
+ canvas->concat(AffineTransformToSkMatrix(
+ orientation_.TransformFromDefault(adjusted_dst_rect.Size())));
+
+ if (orientation_.UsesWidthAsHeight()) {
+ adjusted_dst_rect =
+ FloatRect(adjusted_dst_rect.X(), adjusted_dst_rect.Y(),
+ adjusted_dst_rect.Height(), adjusted_dst_rect.Width());
+ }
}
- return UnacceleratedStaticBitmapImage::Create(skia_image);
+
+ canvas->drawImageRect(image, adjusted_src_rect, adjusted_dst_rect, &flags,
+ WebCoreClampingModeToSkiaRectConstraint(clamp_mode));
}
base::CheckedNumeric<size_t> StaticBitmapImage::GetSizeInBytes(
@@ -120,9 +131,4 @@ bool StaticBitmapImage::CopyToByteArray(
return true;
}
-const gpu::SyncToken& StaticBitmapImage::GetSyncToken() const {
- static const gpu::SyncToken sync_token;
- return sync_token;
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
index 7366bdebcdc..f14b5b86cc3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
@@ -6,11 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_STATIC_BITMAP_IMAGE_H_
#include "base/memory/weak_ptr.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/command_buffer/common/mailbox_holder.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -22,23 +22,29 @@ class GLES2Interface;
namespace blink {
-class WebGraphicsContext3DProviderWrapper;
-
class PLATFORM_EXPORT StaticBitmapImage : public Image {
public:
- static scoped_refptr<StaticBitmapImage> Create(PaintImage);
- static scoped_refptr<StaticBitmapImage> Create(sk_sp<SkData> data,
- const SkImageInfo&);
+ // The ImageOrientation should be derived from the source of the image data.
+ static scoped_refptr<StaticBitmapImage> Create(
+ PaintImage,
+ ImageOrientation = kDefaultImageOrientation);
+ static scoped_refptr<StaticBitmapImage> Create(
+ sk_sp<SkData> data,
+ const SkImageInfo&,
+ ImageOrientation = kDefaultImageOrientation);
+
+ StaticBitmapImage(ImageOrientation orientation) : orientation_(orientation) {}
bool IsStaticBitmapImage() const override { return true; }
// Methods overridden by all sub-classes
~StaticBitmapImage() override = default;
- // Creates a gpu copy of the image using the given ContextProvider. Should
- // not be called if IsTextureBacked() is already true. May return null if the
- // conversion failed (for instance if the context had an error).
- virtual scoped_refptr<StaticBitmapImage> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_wrapper) = 0;
+
+ IntSize SizeRespectingOrientation() const override;
+
+ virtual scoped_refptr<StaticBitmapImage> ConvertToColorSpace(
+ sk_sp<SkColorSpace>,
+ SkColorType = kN32_SkColorType) = 0;
// Methods have common implementation for all sub-classes
bool CurrentFrameIsComplete() override { return true; }
@@ -46,9 +52,9 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
// Methods that have a default implementation, and overridden by only one
// sub-class
- virtual bool HasMailbox() const { return false; }
virtual bool IsValid() const { return true; }
virtual void Transfer() {}
+ virtual bool IsOriginTopLeft() const { return true; }
// Creates a non-gpu copy of the image, or returns this if image is already
// non-gpu.
@@ -68,37 +74,27 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
return false;
}
- // EnsureMailbox modifies the internal state of an accelerated static bitmap
- // image to make sure that it is represented by a Mailbox. This must be
- // called whenever the image is intende to be used in a differen GPU context.
- // It is important to use the correct MailboxSyncMode in order to achieve
- // optimal performance without compromising security or causeing graphics
- // glitches. Here is how to select the aprropriate mode:
- //
- // Case 1: Passing to a gpu context that is on a separate channel.
- // Note: a context in a separate process is necessarily on another channel.
- // Use kVerifiedSyncToken. Or use kUnverifiedSyncToken with a later call
- // to VerifySyncTokensCHROMIUM()
- // Case 2: Passing to a gpu context that is on the same channel but not the
- // same stream.
- // Use kUnverifiedSyncToken
- // Case 3: Passing to a gpu context on the same stream.
- // Use kOrderingBarrier
- virtual void EnsureMailbox(MailboxSyncMode, GLenum filter) { NOTREACHED(); }
- virtual const gpu::Mailbox& GetMailbox() const {
+ virtual void EnsureSyncTokenVerified() { NOTREACHED(); }
+ virtual gpu::MailboxHolder GetMailboxHolder() const {
NOTREACHED();
- static const gpu::Mailbox mailbox;
- return mailbox;
+ return gpu::MailboxHolder();
}
- virtual const gpu::SyncToken& GetSyncToken() const;
+ virtual void UpdateSyncToken(const gpu::SyncToken&) { NOTREACHED(); }
virtual bool IsPremultiplied() const { return true; }
// Methods have exactly the same implementation for all sub-classes
bool OriginClean() const { return is_origin_clean_; }
void SetOriginClean(bool flag) { is_origin_clean_ = flag; }
- scoped_refptr<StaticBitmapImage> ConvertToColorSpace(
- sk_sp<SkColorSpace>,
- SkColorType = kN32_SkColorType);
+
+ // StaticBitmapImage needs to store the orientation of the image itself,
+ // because the underlying representations do not. If the bitmap represents
+ // a non-default orientation it must be explicitly given in the constructor.
+ ImageOrientation CurrentFrameOrientation() const override {
+ return orientation_;
+ }
+ bool HasDefaultOrientation() const override {
+ return orientation_ == kDefaultImageOrientation;
+ }
static base::CheckedNumeric<size_t> GetSizeInBytes(
const IntRect& rect,
@@ -119,8 +115,15 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
const FloatRect&,
const FloatRect&,
ImageClampingMode,
+ RespectImageOrientationEnum,
const PaintImage&);
+ // The image orientation is stored here because it is only available when the
+ // static image is created and the underlying representations do not store
+ // the information. The property is set at construction based on the source of
+ // the image data.
+ ImageOrientation orientation_ = kDefaultImageOrientation;
+
// The following property is here because the SkImage API doesn't expose the
// info. It is applied to both UnacceleratedStaticBitmapImage and
// AcceleratedStaticBitmapImage. To change this property, the call site would
@@ -128,7 +131,12 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
bool is_origin_clean_ = true;
};
-DEFINE_IMAGE_TYPE_CASTS(StaticBitmapImage);
+template <>
+struct DowncastTraits<StaticBitmapImage> {
+ static bool AllowFrom(const Image& image) {
+ return image.IsStaticBitmapImage();
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
index 4f3d1cc74ec..5b851f0e695 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
@@ -14,8 +14,8 @@
#include "components/viz/common/surfaces/surface_info.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -33,7 +33,7 @@ SurfaceLayerBridge::SurfaceLayerBridge(
frame_sink_id_(Platform::Current()->GenerateFrameSinkId()),
parent_frame_sink_id_(parent_frame_sink_id) {
mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
provider.BindNewPipeAndPassReceiver());
// TODO(xlai): Ensure OffscreenCanvas commit() is still functional when a
// frame-less HTML canvas's document is reparenting under another frame.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h
deleted file mode 100644
index a1ba07e2056..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEXTURE_HOLDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEXTURE_HOLDER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "components/viz/common/resources/single_release_callback.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT TextureHolder {
- public:
- class MailboxRef : public ThreadSafeRefCounted<MailboxRef> {
- public:
- explicit MailboxRef(
- std::unique_ptr<viz::SingleReleaseCallback> release_callback)
- : release_callback_(std::move(release_callback)) {}
- ~MailboxRef() {
- if (release_callback_)
- release_callback_->Run(sync_token_, false /* resource_lost */);
- }
-
- void set_sync_token(gpu::SyncToken token) { sync_token_ = token; }
- const gpu::SyncToken& sync_token() const { return sync_token_; }
-
- private:
- gpu::SyncToken sync_token_;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback_;
- };
-
- virtual ~TextureHolder() = default;
-
- // Methods overridden by all sub-classes
- virtual IntSize Size() const = 0;
- virtual bool CurrentFrameKnownToBeOpaque() const = 0;
- virtual bool IsValid() const = 0;
-
- // Methods that have exactly the same impelmentation for all sub-classes
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
- const {
- return context_provider_wrapper_;
- }
-
- WebGraphicsContext3DProvider* ContextProvider() const {
- return context_provider_wrapper_
- ? context_provider_wrapper_->ContextProvider()
- : nullptr;
- }
-
- bool IsOriginTopLeft() const { return is_origin_top_left_; }
-
- const scoped_refptr<MailboxRef>& mailbox_ref() const { return mailbox_ref_; }
-
- protected:
- TextureHolder(base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
- context_provider_wrapper,
- scoped_refptr<MailboxRef> mailbox_ref,
- bool is_origin_top_left)
- : context_provider_wrapper_(std::move(context_provider_wrapper)),
- mailbox_ref_(std::move(mailbox_ref)),
- is_origin_top_left_(is_origin_top_left) {
- DCHECK(mailbox_ref_);
- }
-
- private:
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
- scoped_refptr<MailboxRef> mailbox_ref_;
- bool is_origin_top_left_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEXTURE_HOLDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.cc b/chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.cc
new file mode 100644
index 00000000000..1b18032e09f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.cc
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/touch_action_rect.h"
+
+#include "cc/base/region.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+String TouchActionRect::ToString() const {
+ return rect.ToString() + " " + cc::TouchActionToString(allowed_touch_action);
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const TouchActionRect& hit_test_rect) {
+ return os << hit_test_rect.ToString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.h b/chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.h
new file mode 100644
index 00000000000..578b2bbbe10
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/touch_action_rect.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TOUCH_ACTION_RECT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TOUCH_ACTION_RECT_H_
+
+#include "third_party/blink/renderer/platform/geometry/int_rect.h"
+#include "third_party/blink/renderer/platform/graphics/touch_action.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+struct PLATFORM_EXPORT TouchActionRect {
+ IntRect rect;
+ TouchAction allowed_touch_action = TouchAction::kNone;
+
+ bool operator==(const TouchActionRect& rhs) const {
+ return rect == rhs.rect && allowed_touch_action == rhs.allowed_touch_action;
+ }
+
+ bool operator!=(const TouchActionRect& rhs) const { return !(*this == rhs); }
+
+ String ToString() const;
+};
+
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const TouchActionRect&);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TOUCH_ACTION_RECT_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
index 01253176e58..5a0e96f8d48 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
@@ -17,13 +17,17 @@
namespace blink {
scoped_refptr<UnacceleratedStaticBitmapImage>
-UnacceleratedStaticBitmapImage::Create(sk_sp<SkImage> image) {
+UnacceleratedStaticBitmapImage::Create(sk_sp<SkImage> image,
+ ImageOrientation orientation) {
DCHECK(!image->isTextureBacked());
- return base::AdoptRef(new UnacceleratedStaticBitmapImage(std::move(image)));
+ return base::AdoptRef(
+ new UnacceleratedStaticBitmapImage(std::move(image), orientation));
}
UnacceleratedStaticBitmapImage::UnacceleratedStaticBitmapImage(
- sk_sp<SkImage> image) {
+ sk_sp<SkImage> image,
+ ImageOrientation orientation)
+ : StaticBitmapImage(orientation) {
CHECK(image);
DCHECK(!image->isLazyGenerated());
paint_image_ =
@@ -33,12 +37,16 @@ UnacceleratedStaticBitmapImage::UnacceleratedStaticBitmapImage(
}
scoped_refptr<UnacceleratedStaticBitmapImage>
-UnacceleratedStaticBitmapImage::Create(PaintImage image) {
- return base::AdoptRef(new UnacceleratedStaticBitmapImage(std::move(image)));
+UnacceleratedStaticBitmapImage::Create(PaintImage image,
+ ImageOrientation orientation) {
+ return base::AdoptRef(
+ new UnacceleratedStaticBitmapImage(std::move(image), orientation));
}
-UnacceleratedStaticBitmapImage::UnacceleratedStaticBitmapImage(PaintImage image)
- : paint_image_(std::move(image)) {
+UnacceleratedStaticBitmapImage::UnacceleratedStaticBitmapImage(
+ PaintImage image,
+ ImageOrientation orientation)
+ : StaticBitmapImage(orientation), paint_image_(std::move(image)) {
CHECK(paint_image_.GetSkImage());
}
@@ -66,40 +74,21 @@ bool UnacceleratedStaticBitmapImage::IsPremultiplied() const {
SkAlphaType::kPremul_SkAlphaType;
}
-scoped_refptr<StaticBitmapImage>
-UnacceleratedStaticBitmapImage::MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_wrapper) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- if (!context_wrapper)
- return nullptr; // Can happen if the context is lost.
-
- GrContext* grcontext = context_wrapper->ContextProvider()->GetGrContext();
- if (!grcontext)
- return nullptr; // Can happen if the context is lost.
-
- sk_sp<SkImage> sk_image = paint_image_.GetSkImage();
- sk_sp<SkImage> gpu_skimage = sk_image->makeTextureImage(grcontext);
- if (!gpu_skimage)
- return nullptr;
-
- return AcceleratedStaticBitmapImage::CreateFromSkImage(
- std::move(gpu_skimage), std::move(context_wrapper));
-}
-
bool UnacceleratedStaticBitmapImage::CurrentFrameKnownToBeOpaque() {
return paint_image_.GetSkImage()->isOpaque();
}
-void UnacceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
- const cc::PaintFlags& flags,
- const FloatRect& dst_rect,
- const FloatRect& src_rect,
- RespectImageOrientationEnum,
- ImageClampingMode clamp_mode,
- ImageDecodingMode) {
+void UnacceleratedStaticBitmapImage::Draw(
+ cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum should_respect_image_orientation,
+ ImageClampingMode clamp_mode,
+ ImageDecodingMode) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect, clamp_mode,
+ should_respect_image_orientation,
PaintImageForCurrentFrame());
}
@@ -114,4 +103,21 @@ void UnacceleratedStaticBitmapImage::Transfer() {
original_skia_image_task_runner_ = Thread::Current()->GetTaskRunner();
}
+scoped_refptr<StaticBitmapImage>
+UnacceleratedStaticBitmapImage::ConvertToColorSpace(
+ sk_sp<SkColorSpace> color_space,
+ SkColorType color_type) {
+ DCHECK(color_space);
+
+ sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
+ // If we don't need to change the color type, use SkImage::makeColorSpace()
+ if (skia_image->colorType() == color_type) {
+ skia_image = skia_image->makeColorSpace(color_space);
+ } else {
+ skia_image =
+ skia_image->makeColorTypeAndColorSpace(color_type, color_space);
+ }
+ return UnacceleratedStaticBitmapImage::Create(skia_image, orientation_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
index d5ec71b3c44..d7c50181397 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
@@ -17,15 +17,20 @@ class PLATFORM_EXPORT UnacceleratedStaticBitmapImage final
: public StaticBitmapImage {
public:
~UnacceleratedStaticBitmapImage() override;
- static scoped_refptr<UnacceleratedStaticBitmapImage> Create(sk_sp<SkImage>);
- static scoped_refptr<UnacceleratedStaticBitmapImage> Create(PaintImage);
+
+ // The ImageOrientation should be derived from the source of the image data.
+ static scoped_refptr<UnacceleratedStaticBitmapImage> Create(
+ sk_sp<SkImage>,
+ ImageOrientation orientation = kDefaultImageOrientation);
+ static scoped_refptr<UnacceleratedStaticBitmapImage> Create(
+ PaintImage,
+ ImageOrientation orientation = kDefaultImageOrientation);
bool CurrentFrameKnownToBeOpaque() override;
IntSize Size() const override;
bool IsPremultiplied() const override;
- scoped_refptr<StaticBitmapImage> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_wrapper)
- override;
+ scoped_refptr<StaticBitmapImage> ConvertToColorSpace(sk_sp<SkColorSpace>,
+ SkColorType) override;
void Draw(cc::PaintCanvas*,
const cc::PaintFlags&,
@@ -40,8 +45,8 @@ class PLATFORM_EXPORT UnacceleratedStaticBitmapImage final
void Transfer() final;
private:
- UnacceleratedStaticBitmapImage(sk_sp<SkImage>);
- UnacceleratedStaticBitmapImage(PaintImage);
+ UnacceleratedStaticBitmapImage(sk_sp<SkImage>, ImageOrientation);
+ UnacceleratedStaticBitmapImage(PaintImage, ImageOrientation);
PaintImage paint_image_;
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
index 38028ad0d5b..7fe9c308b58 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
@@ -36,8 +36,7 @@ void VideoFrameResourceProvider::Initialize(
viz::RasterContextProvider* media_context_provider,
viz::SharedBitmapReporter* shared_bitmap_reporter) {
context_provider_ = media_context_provider;
- resource_provider_ = std::make_unique<viz::ClientResourceProvider>(
- /*delegated_sync_points_required=*/true);
+ resource_provider_ = std::make_unique<viz::ClientResourceProvider>();
int max_texture_size;
if (context_provider_) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index 1f551556454..e0cb8886ddd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -10,6 +10,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "cc/metrics/video_playback_roughness_reporter.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/returned_resource.h"
#include "media/base/video_frame.h"
@@ -18,8 +19,8 @@
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h"
#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom-blink.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "ui/gfx/presentation_feedback.h"
@@ -28,10 +29,13 @@ namespace blink {
VideoFrameSubmitter::VideoFrameSubmitter(
WebContextProviderCallback context_provider_callback,
+ cc::PlaybackRoughnessReportingCallback roughness_reporting_callback,
std::unique_ptr<VideoFrameResourceProvider> resource_provider)
: context_provider_callback_(context_provider_callback),
resource_provider_(std::move(resource_provider)),
rotation_(media::VIDEO_ROTATION_0),
+ roughness_reporter_(std::make_unique<cc::VideoPlaybackRoughnessReporter>(
+ std::move(roughness_reporting_callback))),
frame_trackers_(false, nullptr) {
DETACH_FROM_THREAD(thread_checker_);
}
@@ -72,6 +76,7 @@ void VideoFrameSubmitter::StopRendering() {
is_rendering_ = false;
frame_trackers_.StopSequence(cc::FrameSequenceTrackerType::kVideo);
+ roughness_reporter_->Reset();
UpdateSubmissionState();
}
@@ -182,31 +187,39 @@ void VideoFrameSubmitter::OnBeginFrame(
if (viz::FrameTokenGT(pair.key, *next_frame_token_))
continue;
- if (base::Contains(frame_token_to_timestamp_map_, pair.key) &&
- !(pair.value->presentation_feedback->flags &
- gfx::PresentationFeedback::kFailure)) {
- if (!ignorable_submitted_frames_.contains(pair.key)) {
- frame_trackers_.NotifyFramePresented(
- pair.key, gfx::PresentationFeedback(
- pair.value->presentation_feedback->timestamp,
- pair.value->presentation_feedback->interval,
- pair.value->presentation_feedback->flags));
- }
- UMA_HISTOGRAM_TIMES("Media.VideoFrameSubmitter",
- pair.value->presentation_feedback->timestamp -
- frame_token_to_timestamp_map_[pair.key]);
- frame_token_to_timestamp_map_.erase(pair.key);
+#ifdef OS_LINUX
+ // TODO: On Linux failure flag is unreliable, and perfectly rendered frames
+ // are reported as failures all the time.
+ bool presentation_failure = false;
+#else
+ bool presentation_failure = !!(pair.value->presentation_feedback->flags &
+ gfx::PresentationFeedback::kFailure);
+#endif
+ if (!presentation_failure &&
+ !ignorable_submitted_frames_.contains(pair.key)) {
+ frame_trackers_.NotifyFramePresented(
+ pair.key, gfx::PresentationFeedback(
+ pair.value->presentation_feedback->timestamp,
+ pair.value->presentation_feedback->interval,
+ pair.value->presentation_feedback->flags));
+ roughness_reporter_->FramePresented(
+ pair.key, pair.value->presentation_feedback->timestamp);
}
ignorable_submitted_frames_.erase(pair.key);
-
- TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
- "media", "VideoFrameSubmitter", pair.key,
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
+ "media", "VideoFrameSubmitter", TRACE_ID_LOCAL(pair.key),
pair.value->presentation_feedback->timestamp);
}
-
frame_trackers_.NotifyBeginImplFrame(args);
+ base::ScopedClosureRunner end_frame(
+ base::BindOnce(&cc::FrameSequenceTrackerCollection::NotifyFrameEnd,
+ base::Unretained(&frame_trackers_), args, args));
+ base::ScopedClosureRunner roughness_processing(
+ base::BindOnce(&cc::VideoPlaybackRoughnessReporter::ProcessFrameWindow,
+ base::Unretained(roughness_reporter_.get())));
+
// Don't call UpdateCurrentFrame() for MISSED BeginFrames. Also don't call it
// after StopRendering() has been called (forbidden by API contract).
viz::BeginFrameAck current_begin_frame_ack(args, false);
@@ -274,6 +287,8 @@ void VideoFrameSubmitter::OnReceivedContextProvider(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!use_gpu_compositing) {
resource_provider_->Initialize(nullptr, this);
+ if (frame_sink_id_.is_valid())
+ StartSubmitting();
return;
}
@@ -317,7 +332,7 @@ void VideoFrameSubmitter::StartSubmitting() {
DCHECK(frame_sink_id_.is_valid());
mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
provider.BindNewPipeAndPassReceiver());
provider->CreateCompositorFrameSink(
@@ -437,8 +452,15 @@ bool VideoFrameSubmitter::SubmitFrame(
frame_size_ = frame_size;
}
- auto compositor_frame =
- CreateCompositorFrame(begin_frame_ack, std::move(video_frame));
+ auto frame_token = ++next_frame_token_;
+ auto source_id = begin_frame_ack.frame_id.source_id;
+ if (source_id != viz::BeginFrameArgs::kManualSourceId) {
+ // Roughness reporter only cares about true video frames.
+ roughness_reporter_->FrameSubmitted(frame_token, *video_frame.get(),
+ last_begin_frame_args_.interval);
+ }
+ auto compositor_frame = CreateCompositorFrame(frame_token, begin_frame_ack,
+ std::move(video_frame));
WebVector<viz::ResourceId> resources;
const auto& quad_list = compositor_frame.render_pass_list.back()->quad_list;
@@ -453,7 +475,6 @@ bool VideoFrameSubmitter::SubmitFrame(
// We can pass nullptr for the HitTestData as the CompositorFram will not
// contain any SurfaceDrawQuads.
- auto frame_token = compositor_frame.metadata.frame_token;
compositor_frame_sink_->SubmitCompositorFrame(
child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id(),
@@ -479,9 +500,10 @@ void VideoFrameSubmitter::SubmitEmptyFrame() {
last_frame_id_.reset();
auto begin_frame_ack = viz::BeginFrameAck::CreateManualAckWithDamage();
- auto compositor_frame = CreateCompositorFrame(begin_frame_ack, nullptr);
+ auto frame_token = ++next_frame_token_;
+ auto compositor_frame =
+ CreateCompositorFrame(frame_token, begin_frame_ack, nullptr);
- auto frame_token = compositor_frame.metadata.frame_token;
compositor_frame_sink_->SubmitCompositorFrame(
child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id(),
@@ -520,13 +542,14 @@ bool VideoFrameSubmitter::ShouldSubmit() const {
}
viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
+ uint32_t frame_token,
const viz::BeginFrameAck& begin_frame_ack,
scoped_refptr<media::VideoFrame> video_frame) {
DCHECK(!frame_size_.IsEmpty());
viz::CompositorFrame compositor_frame;
compositor_frame.metadata.begin_frame_ack = begin_frame_ack;
- compositor_frame.metadata.frame_token = ++next_frame_token_;
+ compositor_frame.metadata.frame_token = frame_token;
compositor_frame.metadata.preferred_frame_interval =
video_frame_provider_
? video_frame_provider_->GetPreferredRenderInterval()
@@ -535,22 +558,23 @@ viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
base::TimeTicks value;
if (video_frame && video_frame->metadata()->GetTimeTicks(
media::VideoFrameMetadata::DECODE_END_TIME, &value)) {
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0("media", "VideoFrameSubmitter",
- *next_frame_token_, value);
- TRACE_EVENT_ASYNC_STEP_PAST0("media", "VideoFrameSubmitter",
- *next_frame_token_, "Pre-submit buffering");
-
- frame_token_to_timestamp_map_[*next_frame_token_] = value;
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "media", "VideoFrameSubmitter", TRACE_ID_LOCAL(frame_token), value);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "media", "Pre-submit buffering", TRACE_ID_LOCAL(frame_token), value);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("media", "Pre-submit buffering",
+ TRACE_ID_LOCAL(frame_token));
- if (begin_frame_ack.source_id == viz::BeginFrameArgs::kManualSourceId)
- ignorable_submitted_frames_.insert(*next_frame_token_);
+ if (begin_frame_ack.frame_id.source_id ==
+ viz::BeginFrameArgs::kManualSourceId)
+ ignorable_submitted_frames_.insert(frame_token);
UMA_HISTOGRAM_TIMES("Media.VideoFrameSubmitter.PreSubmitBuffering",
base::TimeTicks::Now() - value);
} else {
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
- "media", "VideoFrameSubmitter", *next_frame_token_,
- base::TimeTicks::Now(), "empty video frame?", !video_frame);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("media", "VideoFrameSubmitter",
+ TRACE_ID_LOCAL(frame_token),
+ "empty video frame?", !video_frame);
}
// We don't assume that the ack is marked as having damage. However, we're
@@ -567,6 +591,8 @@ viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
gfx::Transform());
if (video_frame) {
+ compositor_frame.metadata.content_color_usage =
+ video_frame->ColorSpace().GetContentColorUsage();
const bool is_opaque = media::IsOpaque(video_frame->format());
resource_provider_->AppendQuads(render_pass.get(), std::move(video_frame),
rotation_, is_opaque);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
index 0953c624df4..90207762377 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -14,6 +14,7 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/video_playback_roughness_reporter.h"
#include "components/viz/client/shared_bitmap_reporter.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/shared_bitmap.h"
@@ -44,6 +45,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
public viz::mojom::blink::CompositorFrameSinkClient {
public:
VideoFrameSubmitter(WebContextProviderCallback,
+ cc::PlaybackRoughnessReportingCallback,
std::unique_ptr<VideoFrameResourceProvider>);
~VideoFrameSubmitter() override;
@@ -127,6 +129,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// Helper method for creating viz::CompositorFrame. If |video_frame| is null
// then the frame will be empty.
viz::CompositorFrame CreateCompositorFrame(
+ uint32_t frame_token,
const viz::BeginFrameAck& begin_frame_ack,
scoped_refptr<media::VideoFrame> video_frame);
@@ -172,9 +175,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
viz::FrameTokenGenerator next_frame_token_;
- // Timestamps indexed by frame token for histogram purposes.
- using FrameTokenType = decltype(*std::declval<viz::FrameTokenGenerator>());
- base::flat_map<FrameTokenType, base::TimeTicks> frame_token_to_timestamp_map_;
+ std::unique_ptr<cc::VideoPlaybackRoughnessReporter> roughness_reporter_;
base::OneShotTimer empty_frame_timer_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
index 742b9d0cc98..8a772fda9b0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -12,10 +12,12 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/read_only_shared_memory_region.h"
+#include "base/test/bind_test_util.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "cc/layers/video_frame_provider.h"
+#include "cc/metrics/video_playback_roughness_reporter.h"
#include "cc/test/layer_test_common.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/task_runner_provider.h"
@@ -37,6 +39,7 @@
using testing::_;
using testing::AnyNumber;
+using testing::Invoke;
using testing::Return;
using testing::StrictMock;
@@ -169,11 +172,13 @@ class VideoFrameSubmitterTest : public testing::Test {
task_environment_.RunUntilIdle();
}
- void MakeSubmitter() {
+ void MakeSubmitter() { MakeSubmitter(base::DoNothing()); }
+
+ void MakeSubmitter(cc::PlaybackRoughnessReportingCallback reporting_cb) {
resource_provider_ = new StrictMock<MockVideoFrameResourceProvider>(
context_provider_.get(), nullptr);
submitter_ = std::make_unique<VideoFrameSubmitter>(
- base::DoNothing(),
+ base::DoNothing(), reporting_cb,
base::WrapUnique<MockVideoFrameResourceProvider>(resource_provider_));
submitter_->Initialize(video_frame_provider_.get());
@@ -307,8 +312,8 @@ TEST_F(VideoFrameSubmitterTest, StopRenderingSkipsUpdateCurrentFrame) {
// No frames should be produced after StopRendering().
EXPECT_CALL(*sink_, DidNotProduceFrame(_));
- begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
- now_src_.get());
+ args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
+ now_src_.get());
submitter_->OnBeginFrame(args, {});
task_environment_.RunUntilIdle();
}
@@ -498,6 +503,8 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+ args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
+ now_src_.get());
submitter_->OnBeginFrame(args, {});
task_environment_.RunUntilIdle();
}
@@ -640,6 +647,27 @@ TEST_F(VideoFrameSubmitterTest, RecreateCompositorFrameSinkAfterContextLost) {
task_environment_.RunUntilIdle();
}
+// Test that after context is lost, the CompositorFrameSink is recreated but the
+// SurfaceEmbedder isn't even with software compositing.
+TEST_F(VideoFrameSubmitterTest,
+ RecreateCompositorFrameSinkAfterContextLostSoftwareCompositing) {
+ MockEmbeddedFrameSinkProvider mock_embedded_frame_sink_provider;
+ mojo::Receiver<mojom::blink::EmbeddedFrameSinkProvider>
+ embedded_frame_sink_provider_binding(&mock_embedded_frame_sink_provider);
+ auto override =
+ mock_embedded_frame_sink_provider.CreateScopedOverrideMojoInterface(
+ &embedded_frame_sink_provider_binding);
+
+ EXPECT_CALL(*resource_provider_, Initialize(_, _));
+ EXPECT_CALL(mock_embedded_frame_sink_provider, ConnectToEmbedder(_, _))
+ .Times(0);
+ EXPECT_CALL(mock_embedded_frame_sink_provider, CreateCompositorFrameSink_(_))
+ .Times(1);
+ submitter_->OnContextLost();
+ OnReceivedContextProvider(false, nullptr);
+ task_environment_.RunUntilIdle();
+}
+
// This test simulates a race condition in which the |video_frame_provider_| is
// destroyed before OnReceivedContextProvider returns.
TEST_F(VideoFrameSubmitterTest, StopUsingProviderDuringContextLost) {
@@ -662,7 +690,7 @@ TEST_F(VideoFrameSubmitterTest, StopUsingProviderDuringContextLost) {
}
// Test the behaviour of the ChildLocalSurfaceIdAllocator instance. It checks
-// that the LocalSurfaceId is propoerly set at creation and updated when the
+// that the LocalSurfaceId is properly set at creation and updated when the
// video frames change.
TEST_F(VideoFrameSubmitterTest, FrameSizeChangeUpdatesLocalSurfaceId) {
{
@@ -893,6 +921,8 @@ TEST_F(VideoFrameSubmitterTest, NoDuplicateFramesOnBeginFrame) {
.WillOnce(Return(true));
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
EXPECT_CALL(*sink_, DidNotProduceFrame(_));
+ args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
+ now_src_.get());
submitter_->OnBeginFrame(args, {});
task_environment_.RunUntilIdle();
}
@@ -928,4 +958,66 @@ TEST_F(VideoFrameSubmitterTest, ZeroSizedFramesAreNotSubmitted) {
task_environment_.RunUntilIdle();
}
+// Check that given enough frames with wallclock duration and enough
+// presentation feedback data, VideoFrameSubmitter will call the video roughness
+// reporting callback.
+TEST_F(VideoFrameSubmitterTest, ProcessTimingDetails) {
+ int fps = 24;
+ int reports = 0;
+ base::TimeDelta frame_duration = base::TimeDelta::FromSecondsD(1.0 / fps);
+ int frames_to_run =
+ (fps / 2) *
+ (cc::VideoPlaybackRoughnessReporter::kMinWindowsBeforeSubmit + 1);
+ WTF::HashMap<uint32_t, viz::mojom::blink::FrameTimingDetailsPtr>
+ timing_details;
+
+ MakeSubmitter(
+ base::BindLambdaForTesting([&](int frames, base::TimeDelta duration,
+ double roughness) { reports++; }));
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ submitter_->StartRendering();
+ task_environment_.RunUntilIdle();
+ EXPECT_TRUE(IsRendering());
+
+ auto sink_submit = [&](const viz::LocalSurfaceId&,
+ viz::CompositorFrame* frame) {
+ auto token = frame->metadata.frame_token;
+ viz::mojom::blink::FrameTimingDetailsPtr details =
+ viz::mojom::blink::FrameTimingDetails::New();
+ details->presentation_feedback =
+ gfx::mojom::blink::PresentationFeedback::New();
+ details->presentation_feedback->timestamp =
+ base::TimeTicks() + frame_duration * token;
+ timing_details.clear();
+ timing_details.Set(token, std::move(details));
+ };
+
+ EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame)
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*video_frame_provider_, PutCurrentFrame).Times(AnyNumber());
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame)
+ .WillRepeatedly(Invoke(sink_submit));
+ EXPECT_CALL(*resource_provider_, AppendQuads).Times(AnyNumber());
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent).Times(AnyNumber());
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources).Times(AnyNumber());
+
+ for (int i = 0; i < frames_to_run; i++) {
+ auto frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), i * frame_duration);
+ frame->metadata()->SetTimeDelta(
+ media::VideoFrameMetadata::WALLCLOCK_FRAME_DURATION, frame_duration);
+ EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
+ .WillRepeatedly(Return(frame));
+
+ auto args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
+ now_src_.get());
+ submitter_->OnBeginFrame(args, std::move(timing_details));
+ task_environment_.RunUntilIdle();
+ AckSubmittedFrame();
+ }
+ submitter_->StopRendering();
+ EXPECT_EQ(reports, 1);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
index c21068565d3..d868c461141 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -3,20 +3,39 @@
# found in the LICENSE file.
import("//build/buildflag_header.gni")
+import("//build/config/compiler/compiler.gni")
import("//build/config/jumbo.gni")
+import("//build/config/sanitizers/sanitizers.gni")
import("//testing/test.gni")
+import("//third_party/blink/public/public_features.gni")
import("//third_party/blink/renderer/platform/platform.gni")
-declare_args() {
- # Enables heap verification.
- enable_blink_heap_verification = false
-}
-
buildflag_header("blink_heap_buildflags") {
header = "heap_buildflags.h"
header_dir = "third_party/blink/renderer/platform/heap"
- flags = [ "BLINK_HEAP_VERIFICATION=$enable_blink_heap_verification" ]
+ flags = [
+ "BLINK_HEAP_VERIFICATION=$enable_blink_heap_verification",
+ "BLINK_HEAP_YOUNG_GENERATION=$enable_blink_heap_young_generation",
+ ]
+}
+
+jumbo_source_set("heap_unsanitized") {
+ if (is_asan) {
+ configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
+ }
+ configs +=
+ [ "//third_party/blink/renderer/platform:blink_platform_implementation" ]
+
+ sources = [
+ "unsanitized_atomic.cc",
+ "unsanitized_atomic.h",
+ ]
+
+ deps = [
+ "//base",
+ "//third_party/blink/renderer/platform/wtf",
+ ]
}
blink_platform_sources("heap") {
@@ -28,6 +47,9 @@ blink_platform_sources("heap") {
"blink_gc_memory_dump_provider.h",
"cancelable_task_scheduler.cc",
"cancelable_task_scheduler.h",
+ "collection_support/heap_hash_table_backing.h",
+ "collection_support/heap_linked_stack.h",
+ "collection_support/heap_vector_backing.h",
"disallow_new_wrapper.h",
"finalizer_traits.h",
"garbage_collected.h",
@@ -41,7 +63,6 @@ blink_platform_sources("heap") {
"heap_allocator.h",
"heap_compact.cc",
"heap_compact.h",
- "heap_linked_stack.h",
"heap_page.cc",
"heap_page.h",
"heap_stats_collector.cc",
@@ -83,10 +104,16 @@ blink_platform_sources("heap") {
":blink_heap_buildflags",
"//base",
"//third_party/blink/renderer/platform:make_platform_generated",
+ "//third_party/blink/renderer/platform/heap:heap_unsanitized",
"//third_party/blink/renderer/platform/heap/asm",
"//third_party/icu",
"//v8",
]
+
+ if (!is_debug && !optimize_for_size) {
+ configs -= [ "//build/config/compiler:default_optimization" ]
+ configs += [ "//build/config/compiler:optimize_max" ]
+ }
}
jumbo_source_set("test_support") {
@@ -98,6 +125,7 @@ jumbo_source_set("test_support") {
]
deps = [
+ ":blink_heap_buildflags",
"//testing/gtest",
"//third_party/blink/public/mojom:mojom_platform_blink_headers",
"//third_party/blink/renderer/platform:bindings_buildflags",
@@ -105,9 +133,7 @@ jumbo_source_set("test_support") {
}
test("blink_heap_unittests") {
- deps = [
- ":blink_heap_unittests_sources",
- ]
+ deps = [ ":blink_heap_unittests_sources" ]
if (is_android) {
deps += [
"//base:base_java",
@@ -124,6 +150,8 @@ jumbo_source_set("blink_heap_unittests_sources") {
"../testing/run_all_tests.cc",
"blink_gc_memory_dump_provider_test.cc",
"cancelable_task_scheduler_test.cc",
+ "card_table_test.cc",
+ "collection_support/heap_linked_stack_test.cc",
"concurrent_marking_test.cc",
"gc_info_test.cc",
"heap_compact_test.cc",
@@ -142,6 +170,10 @@ jumbo_source_set("blink_heap_unittests_sources") {
"write_barrier_perftest.cc",
]
+ if (enable_blink_heap_young_generation) {
+ sources += [ "minor_gc_test.cc" ]
+ }
+
configs += [
"//third_party/blink/renderer/platform/wtf:wtf_config",
"//third_party/blink/renderer:config",
diff --git a/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md b/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
index f1415c771a5..eb532cd733c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
+++ b/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
@@ -201,7 +201,7 @@ Especially, avoid defining a pre-finalizer in a class that can be allocated a lo
### STACK_ALLOCATED
-Class level annotation that should be used if the object is only stack allocated; it disallows use of `operator new`. Any fields holding garbage-collected objects should use `Member<T>` references, but you do not need to define a `Trace()` method as they are on the stack, and automatically traced and kept alive should a conservative GC be required.
+Class level annotation that should be used if the object is only stack allocated; it disallows use of `operator new`. Any fields holding garbage-collected objects should use regular pointers or references and you do not need to define a `Trace()` method as they are on the stack, and automatically traced and kept alive should a conservative GC be required.
Classes with this annotation do not need a `Trace()` method and must not inherit a on-heap garbage collected class.
@@ -275,7 +275,7 @@ You need to trace every `Member<T>` and `WeakMember<T>` in your class. See [Trac
Unlike 'Member<T>', 'UntracedMember<T>' will not keep an object alive. However, unlike 'WeakMember<T>', the reference will not be cleared (i.e. set to 'nullptr') if the referenced object dies.
Furthermore, class fields of type 'UntracedMember<T>' should not be traced by the class' tracing method.
-Users should use 'UntracedMember<T>' when implementing [custom weakness semantics](#Custom weak callbacks).
+Users should use 'UntracedMember<T>' when implementing [custom weakness semantics](#Custom-weak-callbacks).
### Persistent, WeakPersistent, CrossThreadPersistent, CrossThreadWeakPersistent
diff --git a/chromium/third_party/blink/renderer/platform/heap/DEPS b/chromium/third_party/blink/renderer/platform/heap/DEPS
index eda4c2ea500..5814f38e1e9 100644
--- a/chromium/third_party/blink/renderer/platform/heap/DEPS
+++ b/chromium/third_party/blink/renderer/platform/heap/DEPS
@@ -12,8 +12,9 @@ include_rules = [
"+base/strings/string_number_conversions.h",
"+base/synchronization/lock.h",
"+base/task_runner.h",
+ "+base/task/post_job.h",
"+base/template_util.h",
- "+testing/perf/perf_test.h",
+ "+testing/perf/perf_result_reporter.h",
"+third_party/blink/renderer/platform/bindings",
"+third_party/blink/renderer/platform/instrumentation/histogram.h",
diff --git a/chromium/third_party/blink/renderer/platform/heap/OWNERS b/chromium/third_party/blink/renderer/platform/heap/OWNERS
index bca3233e2e4..dafb539f11d 100644
--- a/chromium/third_party/blink/renderer/platform/heap/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/heap/OWNERS
@@ -2,6 +2,7 @@ bikineev@chromium.org
haraken@chromium.org
kouhei@chromium.org
mlippautz@chromium.org
+omerkatz@chromium.org
# TEAM: oilpan-reviews@chromium.org
# COMPONENT: Blink>MemoryAllocator>GarbageCollection
diff --git a/chromium/third_party/blink/renderer/platform/heap/asm/BUILD.gn b/chromium/third_party/blink/renderer/platform/heap/asm/BUILD.gn
index 8aa2cbe249d..fe44daf27a5 100644
--- a/chromium/third_party/blink/renderer/platform/heap/asm/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/heap/asm/BUILD.gn
@@ -8,9 +8,7 @@ if (current_cpu == "x86" || current_cpu == "x64") {
nasm_assemble("asm") {
assert(current_cpu == "x86" || current_cpu == "x64")
- sources = [
- "SaveRegisters_x86.asm",
- ]
+ sources = [ "SaveRegisters_x86.asm" ]
defines = []
if (is_mac) {
@@ -31,25 +29,15 @@ if (current_cpu == "x86" || current_cpu == "x64") {
} else { # current_cpu == "x86" || current_cpu == "x64"
source_set("asm") {
if (current_cpu == "arm") {
- sources = [
- "SaveRegisters_arm.S",
- ]
+ sources = [ "SaveRegisters_arm.S" ]
} else if (current_cpu == "arm64") {
- sources = [
- "SaveRegisters_arm64.S",
- ]
+ sources = [ "SaveRegisters_arm64.S" ]
} else if (current_cpu == "mipsel") {
- sources = [
- "SaveRegisters_mips.S",
- ]
+ sources = [ "SaveRegisters_mips.S" ]
} else if (current_cpu == "mips64el") {
- sources = [
- "SaveRegisters_mips64.S",
- ]
+ sources = [ "SaveRegisters_mips64.S" ]
} else if (current_cpu == "ppc64") {
- sources = [
- "SaveRegisters_ppc64.S",
- ]
+ sources = [ "SaveRegisters_ppc64.S" ]
}
if (current_cpu == "arm") {
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc.h b/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
index a1ba0e53a23..ccc1bfb0443 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -19,17 +19,18 @@ class MarkingVisitor;
class Visitor;
using Address = uint8_t*;
+using ConstAddress = const uint8_t*;
using FinalizationCallback = void (*)(void*);
-using VisitorCallback = void (*)(Visitor*, void*);
-using MarkingVisitorCallback = void (*)(MarkingVisitor*, void*);
+using VisitorCallback = void (*)(Visitor*, const void*);
+using MarkingVisitorCallback = void (*)(MarkingVisitor*, const void*);
using TraceCallback = VisitorCallback;
-using WeakCallback = void (*)(const WeakCallbackInfo&, void*);
+using WeakCallback = void (*)(const WeakCallbackInfo&, const void*);
using EphemeronCallback = VisitorCallback;
// Simple alias to avoid heap compaction type signatures turning into
// a sea of generic |void*|s.
-using MovableReference = void*;
+using MovableReference = const void*;
// Heap compaction supports registering callbacks that are to be invoked
// when an object is moved during compaction. This is to support internal
@@ -64,6 +65,11 @@ class PLATFORM_EXPORT BlinkGC final {
STATIC_ONLY(BlinkGC);
public:
+ // CollectionType represents generational collection. kMinor collects objects
+ // in the young generation (i.e. allocated since the previous collection
+ // cycle, since we use sticky bits), kMajor collects the entire heap.
+ enum class CollectionType { kMinor, kMajor };
+
// When garbage collecting we need to know whether or not there
// can be pointers to Blink GC managed objects on the stack for
// each thread. When threads reach a safe point they record
diff --git a/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler_test.cc b/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler_test.cc
index 23df65f74ed..97f4c8bf38d 100644
--- a/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler_test.cc
@@ -25,8 +25,6 @@ class ParallelTaskRunner : public base::TaskRunner {
return true;
}
- bool RunsTasksInCurrentSequence() const override { return false; }
-
void RunUntilIdle() {}
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/card_table_test.cc b/chromium/third_party/blink/renderer/platform/heap/card_table_test.cc
new file mode 100644
index 00000000000..a4620eadf0a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/card_table_test.cc
@@ -0,0 +1,181 @@
+// 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 <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/heap/heap_page.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+
+namespace blink {
+
+namespace {
+
+class BaseObject : public GarbageCollected<BaseObject> {
+ public:
+ size_t CardNumber() const;
+ void Trace(Visitor*) {}
+};
+
+} // namespace
+
+class CardTableTest : public TestSupportingGC {
+ public:
+ static constexpr size_t kCardSize = NormalPage::CardTable::kCardSize;
+
+ CardTableTest() { ClearOutOldGarbage(); }
+
+ static void CheckObjects(const std::vector<BaseObject*>& objects,
+ const NormalPage& page) {
+ page.IterateCardTable([&objects](HeapObjectHeader* header) {
+ const BaseObject* object =
+ reinterpret_cast<BaseObject*>(header->Payload());
+ auto it = std::find(objects.begin(), objects.end(), object);
+ EXPECT_NE(it, objects.end());
+ });
+ }
+
+ static void MarkCardForObject(BaseObject* object) {
+ NormalPage* page = static_cast<NormalPage*>(PageFromObject(object));
+ page->MarkCard(reinterpret_cast<Address>(object));
+ }
+
+ static bool IsCardMarked(const NormalPage& page, size_t card_number) {
+ return page.card_table_.IsMarked(card_number);
+ }
+
+ static size_t ObjectsInCard(const NormalPage& page, size_t card_number) {
+ const NormalPage::CardTable& cards = page.card_table_;
+
+ size_t objects = 0;
+ Address card_begin =
+ RoundToBlinkPageStart(page.GetAddress()) + (card_number * kCardSize);
+ const Address card_end = card_begin + kCardSize;
+ if (card_number == cards.begin().index) {
+ // First card is misaligned due to padding.
+ card_begin = page.Payload();
+ }
+
+ page.ArenaForNormalPage()->MakeConsistentForGC();
+
+ page.IterateOnCard(
+ [card_begin, card_end, &objects](HeapObjectHeader* header) {
+ const Address header_address = reinterpret_cast<Address>(header);
+ if (header_address < card_begin) {
+ const Address next_header_address = header_address + header->size();
+ EXPECT_GT(next_header_address, card_begin);
+ } else {
+ objects++;
+ EXPECT_LT(header_address, card_end);
+ }
+ },
+ card_number);
+
+ return objects;
+ }
+
+ static size_t MarkedObjects(const NormalPage& page) {
+ size_t objects = 0;
+ page.ArenaForNormalPage()->MakeConsistentForGC();
+ page.IterateCardTable([&objects](HeapObjectHeader*) { ++objects; });
+ return objects;
+ }
+
+ static void ClearCardTable(NormalPage& page) { page.card_table_.Clear(); }
+};
+
+namespace {
+
+size_t BaseObject::CardNumber() const {
+ return (reinterpret_cast<uintptr_t>(this) & kBlinkPageOffsetMask) /
+ CardTableTest::kCardSize;
+}
+
+template <size_t Size>
+class Object : public BaseObject {
+ private:
+ uint8_t array[Size];
+};
+
+} // namespace
+
+TEST_F(CardTableTest, Empty) {
+ BaseObject* obj = MakeGarbageCollected<BaseObject>();
+ EXPECT_EQ(0u, MarkedObjects(*static_cast<NormalPage*>(PageFromObject(obj))));
+}
+
+TEST_F(CardTableTest, SingleObjectOnFirstCard) {
+ BaseObject* obj = MakeGarbageCollected<BaseObject>();
+ MarkCardForObject(obj);
+
+ const NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj));
+ const size_t card_number = obj->CardNumber();
+ EXPECT_TRUE(IsCardMarked(page, card_number));
+
+ const size_t objects = ObjectsInCard(page, card_number);
+ EXPECT_EQ(1u, objects);
+}
+
+TEST_F(CardTableTest, SingleObjectOnSecondCard) {
+ MakeGarbageCollected<Object<kCardSize>>();
+ BaseObject* obj = MakeGarbageCollected<Object<kCardSize>>();
+ MarkCardForObject(obj);
+
+ const NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj));
+ const size_t card_number = obj->CardNumber();
+ EXPECT_TRUE(IsCardMarked(page, card_number));
+
+ const size_t objects = ObjectsInCard(page, card_number);
+ EXPECT_EQ(1u, objects);
+}
+
+TEST_F(CardTableTest, TwoObjectsOnSecondCard) {
+ static constexpr size_t kHalfCardSize = kCardSize / 2;
+ MakeGarbageCollected<Object<kHalfCardSize>>();
+ MakeGarbageCollected<Object<kHalfCardSize>>();
+ // The card on which 'obj' resides is guaranteed to have two objects, either
+ // the previously allocated one or the following one.
+ BaseObject* obj = MakeGarbageCollected<Object<kHalfCardSize>>();
+ MakeGarbageCollected<Object<kHalfCardSize>>();
+ MarkCardForObject(obj);
+
+ const NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj));
+ const size_t card_number = obj->CardNumber();
+ EXPECT_TRUE(IsCardMarked(page, card_number));
+
+ const size_t objects = ObjectsInCard(page, card_number);
+ EXPECT_EQ(2u, objects);
+}
+
+TEST_F(CardTableTest, Clear) {
+ MakeGarbageCollected<Object<kCardSize>>();
+ MakeGarbageCollected<Object<kCardSize / 2>>();
+ BaseObject* obj = MakeGarbageCollected<Object<kCardSize / 2>>();
+ MarkCardForObject(obj);
+
+ NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj));
+ ClearCardTable(page);
+
+ const size_t card_number = obj->CardNumber();
+ EXPECT_FALSE(IsCardMarked(page, card_number));
+}
+
+TEST_F(CardTableTest, MultipleObjects) {
+ std::vector<BaseObject*> objects;
+ BaseObject* obj = MakeGarbageCollected<Object<kCardSize>>();
+ BasePage* const first_page = PageFromObject(obj);
+ BasePage* new_page = first_page;
+
+ while (first_page == new_page) {
+ objects.push_back(obj);
+ MarkCardForObject(obj);
+
+ obj = MakeGarbageCollected<Object<kCardSize>>();
+ new_page = PageFromObject(obj);
+ }
+
+ CheckObjects(objects, *static_cast<NormalPage*>(first_page));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h
new file mode 100644
index 00000000000..8b91764b10d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h
@@ -0,0 +1,315 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
+
+#include "third_party/blink/renderer/platform/heap/heap_page.h"
+#include "third_party/blink/renderer/platform/heap/threading_traits.h"
+#include "third_party/blink/renderer/platform/heap/trace_traits.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+template <typename Table>
+class HeapHashTableBacking {
+ DISALLOW_NEW();
+ IS_GARBAGE_COLLECTED_TYPE();
+
+ public:
+ template <typename Backing>
+ static void* AllocateObject(size_t size);
+
+ static void Finalize(void* pointer);
+ void FinalizeGarbageCollectedObject() { Finalize(this); }
+};
+
+template <typename Table>
+struct ThreadingTrait<HeapHashTableBacking<Table>> {
+ STATIC_ONLY(ThreadingTrait);
+ using Key = typename Table::KeyType;
+ using Value = typename Table::ValueType;
+ static const ThreadAffinity kAffinity =
+ (ThreadingTrait<Key>::kAffinity == kMainThreadOnly) &&
+ (ThreadingTrait<Value>::kAffinity == kMainThreadOnly)
+ ? kMainThreadOnly
+ : kAnyThread;
+};
+
+// static
+template <typename Table>
+template <typename Backing>
+void* HeapHashTableBacking<Table>::AllocateObject(size_t size) {
+ ThreadState* state =
+ ThreadStateFor<ThreadingTrait<Backing>::kAffinity>::GetState();
+ DCHECK(state->IsAllocationAllowed());
+ const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(Backing);
+ return state->Heap().AllocateOnArenaIndex(
+ state, size, BlinkGC::kHashTableArenaIndex, GCInfoTrait<Backing>::Index(),
+ type_name);
+}
+
+template <typename Table>
+void HeapHashTableBacking<Table>::Finalize(void* pointer) {
+ using Value = typename Table::ValueType;
+ static_assert(
+ !std::is_trivially_destructible<Value>::value,
+ "Finalization of trivially destructible classes should not happen.");
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(pointer);
+ // Use the payload size as recorded by the heap to determine how many
+ // elements to finalize.
+ size_t length = header->PayloadSize() / sizeof(Value);
+ Value* table = reinterpret_cast<Value*>(pointer);
+ for (unsigned i = 0; i < length; ++i) {
+ if (!Table::IsEmptyOrDeletedBucket(table[i]))
+ table[i].~Value();
+ }
+}
+
+template <typename Table>
+struct MakeGarbageCollectedTrait<HeapHashTableBacking<Table>> {
+ static HeapHashTableBacking<Table>* Call(size_t num_elements) {
+ CHECK_GT(num_elements, 0u);
+ void* memory = HeapHashTableBacking<Table>::template AllocateObject<
+ HeapHashTableBacking<Table>>(num_elements *
+ sizeof(typename Table::ValueType));
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
+ // Placement new as regular operator new() is deleted.
+ HeapHashTableBacking<Table>* object =
+ ::new (memory) HeapHashTableBacking<Table>();
+ header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
+ return object;
+ }
+};
+
+template <typename Table>
+struct FinalizerTrait<HeapHashTableBacking<Table>> {
+ STATIC_ONLY(FinalizerTrait);
+ static const bool kNonTrivialFinalizer =
+ !std::is_trivially_destructible<typename Table::ValueType>::value;
+ static void Finalize(void* obj) {
+ internal::FinalizerTraitImpl<HeapHashTableBacking<Table>,
+ kNonTrivialFinalizer>::Finalize(obj);
+ }
+};
+
+// The trace trait for the heap hashtable backing is used when we find a
+// direct pointer to the backing from the conservative stack scanner. This
+// normally indicates that there is an ongoing iteration over the table, and so
+// we disable weak processing of table entries. When the backing is found
+// through the owning hash table we mark differently, in order to do weak
+// processing.
+template <typename Table>
+struct TraceTrait<HeapHashTableBacking<Table>> {
+ STATIC_ONLY(TraceTrait);
+ using Backing = HeapHashTableBacking<Table>;
+ using ValueType = typename Table::ValueTraits::TraitType;
+ using Traits = typename Table::ValueTraits;
+
+ public:
+ static TraceDescriptor GetTraceDescriptor(const void* self) {
+ return {self, Trace<WTF::kNoWeakHandling>};
+ }
+
+ static TraceDescriptor GetWeakTraceDescriptor(const void* self) {
+ return GetWeakTraceDescriptorImpl<ValueType>::GetWeakTraceDescriptor(self);
+ }
+
+ template <WTF::WeakHandlingFlag WeakHandling = WTF::kNoWeakHandling>
+ static void Trace(Visitor* visitor, const void* self) {
+ if (visitor->ConcurrentTracingBailOut({self, &Trace}))
+ return;
+
+ static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value ||
+ WTF::IsWeak<ValueType>::value,
+ "T should not be traced");
+ WTF::TraceInCollectionTrait<WeakHandling, Backing, void>::Trace(visitor,
+ self);
+ }
+
+ private:
+ template <typename ValueType>
+ struct GetWeakTraceDescriptorImpl {
+ static TraceDescriptor GetWeakTraceDescriptor(const void* backing) {
+ return {backing, nullptr};
+ }
+ };
+
+ template <typename K, typename V>
+ struct GetWeakTraceDescriptorImpl<WTF::KeyValuePair<K, V>> {
+ static TraceDescriptor GetWeakTraceDescriptor(const void* backing) {
+ return GetWeakTraceDescriptorKVPImpl<K, V>::GetWeakTraceDescriptor(
+ backing);
+ }
+
+ template <typename KeyType,
+ typename ValueType,
+ bool ephemeron_semantics = (WTF::IsWeak<KeyType>::value &&
+ !WTF::IsWeak<ValueType>::value &&
+ WTF::IsTraceable<ValueType>::value) ||
+ (WTF::IsWeak<ValueType>::value &&
+ !WTF::IsWeak<KeyType>::value &&
+ WTF::IsTraceable<KeyType>::value)>
+ struct GetWeakTraceDescriptorKVPImpl {
+ static TraceDescriptor GetWeakTraceDescriptor(const void* backing) {
+ return {backing, nullptr};
+ }
+ };
+
+ template <typename KeyType, typename ValueType>
+ struct GetWeakTraceDescriptorKVPImpl<KeyType, ValueType, true> {
+ static TraceDescriptor GetWeakTraceDescriptor(const void* backing) {
+ return {backing, Trace<WTF::kWeakHandling>};
+ }
+ };
+ };
+};
+
+} // namespace blink
+
+namespace WTF {
+
+// This trace method is for tracing a HashTableBacking either through regular
+// tracing (via the relevant TraceTraits) or when finding a HashTableBacking
+// through conservative stack scanning (which will treat all references in the
+// backing strongly).
+template <WTF::WeakHandlingFlag WeakHandling, typename Table>
+struct TraceHashTableBackingInCollectionTrait {
+ using Value = typename Table::ValueType;
+ using Traits = typename Table::ValueTraits;
+
+ static bool Trace(blink::Visitor* visitor, const void* self) {
+ static_assert(IsTraceableInCollectionTrait<Traits>::value ||
+ WTF::IsWeak<Value>::value,
+ "Table should not be traced");
+ const Value* array = reinterpret_cast<const Value*>(self);
+ blink::HeapObjectHeader* header =
+ blink::HeapObjectHeader::FromPayload(self);
+ // Use the payload size as recorded by the heap to determine how many
+ // elements to trace.
+ size_t length = header->PayloadSize() / sizeof(Value);
+ const bool is_concurrent = visitor->IsConcurrent();
+ for (size_t i = 0; i < length; ++i) {
+ // If tracing concurrently, use a concurrent-safe version of
+ // IsEmptyOrDeletedBucket (check performed on a local copy instead
+ // of directly on the bucket).
+ if (is_concurrent) {
+ if (!HashTableHelper<Value, typename Table::ExtractorType,
+ typename Table::KeyTraitsType>::
+ IsEmptyOrDeletedBucketSafe(array[i])) {
+ blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
+ visitor, &array[i]);
+ }
+ } else {
+ if (!HashTableHelper<Value, typename Table::ExtractorType,
+ typename Table::KeyTraitsType>::
+ IsEmptyOrDeletedBucket(array[i])) {
+ blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
+ visitor, &array[i]);
+ }
+ }
+ }
+ return false;
+ }
+};
+
+template <typename Table>
+struct TraceInCollectionTrait<kNoWeakHandling,
+ blink::HeapHashTableBacking<Table>,
+ void> {
+ static bool Trace(blink::Visitor* visitor, const void* self) {
+ return TraceHashTableBackingInCollectionTrait<kNoWeakHandling,
+ Table>::Trace(visitor, self);
+ }
+};
+
+template <typename Table>
+struct TraceInCollectionTrait<kWeakHandling,
+ blink::HeapHashTableBacking<Table>,
+ void> {
+ static bool Trace(blink::Visitor* visitor, const void* self) {
+ return TraceHashTableBackingInCollectionTrait<kWeakHandling, Table>::Trace(
+ visitor, self);
+ }
+};
+
+// Key value pairs, as used in HashMap. To disambiguate template choice we have
+// to have two versions, first the one with no special weak handling, then the
+// one with weak handling.
+template <typename Key, typename Value, typename Traits>
+struct TraceInCollectionTrait<kNoWeakHandling,
+ KeyValuePair<Key, Value>,
+ Traits> {
+ using EphemeronHelper =
+ blink::EphemeronKeyValuePair<Key,
+ Value,
+ typename Traits::KeyTraits,
+ typename Traits::ValueTraits>;
+
+ static bool Trace(blink::Visitor* visitor,
+ const KeyValuePair<Key, Value>& self) {
+ if (WTF::IsWeak<Key>::value != WTF::IsWeak<Value>::value) {
+ // Strongification of Weak/Strong and Strong/Weak.
+ EphemeronHelper helper(&self.key, &self.value);
+ visitor->VisitEphemeronKeyValuePair(
+ helper.key, helper.value,
+ blink::TraceCollectionIfEnabled<
+ kNoWeakHandling, typename EphemeronHelper::KeyType,
+ typename EphemeronHelper::KeyTraits>::Trace,
+ blink::TraceCollectionIfEnabled<
+ kNoWeakHandling, typename EphemeronHelper::ValueType,
+ typename EphemeronHelper::ValueTraits>::Trace);
+ } else {
+ // Strongification of Strong/Strong or Weak/Weak. Order does not matter
+ // here.
+ blink::TraceCollectionIfEnabled<
+ kNoWeakHandling, Key, typename Traits::KeyTraits>::Trace(visitor,
+ &self.key);
+ blink::TraceCollectionIfEnabled<
+ kNoWeakHandling, Value,
+ typename Traits::ValueTraits>::Trace(visitor, &self.value);
+ }
+ return false;
+ }
+};
+
+template <typename Key, typename Value, typename Traits>
+struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> {
+ using EphemeronHelper =
+ blink::EphemeronKeyValuePair<Key,
+ Value,
+ typename Traits::KeyTraits,
+ typename Traits::ValueTraits>;
+
+ static bool IsAlive(const KeyValuePair<Key, Value>& self) {
+ // Needed for Weak/Weak, Strong/Weak (reverse ephemeron), and Weak/Strong
+ // (ephemeron). Order of invocation does not matter as tracing weak key or
+ // value does not have any side effects.
+ return blink::TraceCollectionIfEnabled<
+ WeakHandlingTrait<Key>::value, Key,
+ typename Traits::KeyTraits>::IsAlive(self.key) &&
+ blink::TraceCollectionIfEnabled<
+ WeakHandlingTrait<Value>::value, Value,
+ typename Traits::ValueTraits>::IsAlive(self.value);
+ }
+
+ static bool Trace(blink::Visitor* visitor,
+ const KeyValuePair<Key, Value>& self) {
+ EphemeronHelper helper(&self.key, &self.value);
+ return visitor->VisitEphemeronKeyValuePair(
+ helper.key, helper.value,
+ blink::TraceCollectionIfEnabled<
+ WeakHandlingTrait<typename EphemeronHelper::KeyType>::value,
+ typename EphemeronHelper::KeyType,
+ typename EphemeronHelper::KeyTraits>::Trace,
+ blink::TraceCollectionIfEnabled<
+ WeakHandlingTrait<typename EphemeronHelper::ValueType>::value,
+ typename EphemeronHelper::ValueType,
+ typename EphemeronHelper::ValueTraits>::Trace);
+ }
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_linked_stack.h b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h
index b1ad5a367cd..c0b4e95350a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_linked_stack.h
+++ b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h
@@ -28,10 +28,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_LINKED_STACK_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_LINKED_STACK_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_LINKED_STACK_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_LINKED_STACK_H_
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -44,36 +45,40 @@ namespace blink {
// (now removed: https://codereview.chromium.org/2761853003/).
// See https://codereview.chromium.org/17314010 for the original use-case.
template <typename T>
-class HeapLinkedStack : public GarbageCollected<HeapLinkedStack<T>> {
+class HeapLinkedStack final : public GarbageCollected<HeapLinkedStack<T>> {
public:
- HeapLinkedStack() : size_(0) {}
+ static void CheckType() {
+ static_assert(internal::IsMember<T>,
+ "HeapLinkedStack supports only Member.");
+ }
- bool IsEmpty();
+ HeapLinkedStack() { CheckType(); }
- void Push(const T&);
- const T& Peek();
- void Pop();
+ inline size_t size() const;
+ inline bool IsEmpty() const;
- size_t size();
+ inline void Push(const T&);
+ inline const T& Peek() const;
+ inline void Pop();
- void Trace(blink::Visitor* visitor) {
- for (Node* current = head_; current; current = current->next_)
- visitor->Trace(current);
- }
+ void Trace(Visitor* visitor) { visitor->Trace(head_); }
private:
- class Node : public GarbageCollected<Node> {
+ class Node final : public GarbageCollected<Node> {
public:
- Node(const T&, Node* next);
+ Node(const T&, Node*);
- void Trace(blink::Visitor* visitor) { visitor->Trace(data_); }
+ void Trace(Visitor* visitor) {
+ visitor->Trace(data_);
+ visitor->Trace(next_);
+ }
T data_;
Member<Node> next_;
};
Member<Node> head_;
- size_t size_;
+ size_t size_ = 0;
};
template <typename T>
@@ -81,23 +86,23 @@ HeapLinkedStack<T>::Node::Node(const T& data, Node* next)
: data_(data), next_(next) {}
template <typename T>
-inline bool HeapLinkedStack<T>::IsEmpty() {
+bool HeapLinkedStack<T>::IsEmpty() const {
return !head_;
}
template <typename T>
-inline void HeapLinkedStack<T>::Push(const T& data) {
+void HeapLinkedStack<T>::Push(const T& data) {
head_ = MakeGarbageCollected<Node>(data, head_);
++size_;
}
template <typename T>
-inline const T& HeapLinkedStack<T>::Peek() {
+const T& HeapLinkedStack<T>::Peek() const {
return head_->data_;
}
template <typename T>
-inline void HeapLinkedStack<T>::Pop() {
+void HeapLinkedStack<T>::Pop() {
DCHECK(head_);
DCHECK(size_);
head_ = head_->next_;
@@ -105,10 +110,10 @@ inline void HeapLinkedStack<T>::Pop() {
}
template <typename T>
-inline size_t HeapLinkedStack<T>::size() {
+size_t HeapLinkedStack<T>::size() const {
return size_;
}
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_LINKED_STACK_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_LINKED_STACK_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack_test.cc b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack_test.cc
new file mode 100644
index 00000000000..27b3f0dbf06
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+
+namespace blink {
+
+namespace {
+class HeapLinkedStackTest : public TestSupportingGC {};
+} // namespace
+
+TEST_F(HeapLinkedStackTest, PushPop) {
+ using Stack = HeapLinkedStack<Member<IntegerObject>>;
+
+ ClearOutOldGarbage();
+ IntegerObject::destructor_calls = 0;
+
+ Stack* stack = MakeGarbageCollected<Stack>();
+
+ constexpr wtf_size_t kStackSize = 10;
+
+ for (wtf_size_t i = 0; i < kStackSize; i++)
+ stack->Push(MakeGarbageCollected<IntegerObject>(i));
+
+ ConservativelyCollectGarbage();
+ EXPECT_EQ(0, IntegerObject::destructor_calls);
+ EXPECT_EQ(kStackSize, stack->size());
+ while (!stack->IsEmpty()) {
+ EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->Peek()->Value()));
+ stack->Pop();
+ }
+
+ Persistent<Stack> holder = stack;
+
+ PreciselyCollectGarbage();
+ EXPECT_EQ(kStackSize, static_cast<size_t>(IntegerObject::destructor_calls));
+ EXPECT_EQ(0u, holder->size());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h
new file mode 100644
index 00000000000..eeba5dbc259
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h
@@ -0,0 +1,203 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_
+
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/heap/finalizer_traits.h"
+#include "third_party/blink/renderer/platform/heap/gc_info.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/heap/threading_traits.h"
+#include "third_party/blink/renderer/platform/heap/trace_traits.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+template <typename T, typename Traits = WTF::VectorTraits<T>>
+class HeapVectorBacking final {
+ DISALLOW_NEW();
+ IS_GARBAGE_COLLECTED_TYPE();
+
+ public:
+ template <typename Backing>
+ static void* AllocateObject(size_t size) {
+ ThreadState* state =
+ ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
+ DCHECK(state->IsAllocationAllowed());
+ const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(Backing);
+ return state->Heap().AllocateOnArenaIndex(
+ state, size, BlinkGC::kVectorArenaIndex, GCInfoTrait<Backing>::Index(),
+ type_name);
+ }
+
+ static void Finalize(void* pointer);
+ void FinalizeGarbageCollectedObject() { Finalize(this); }
+};
+
+template <typename T, typename Traits>
+void HeapVectorBacking<T, Traits>::Finalize(void* pointer) {
+ static_assert(Traits::kNeedsDestruction,
+ "Only vector buffers with items requiring destruction should "
+ "be finalized");
+ static_assert(
+ Traits::kCanClearUnusedSlotsWithMemset || std::is_polymorphic<T>::value,
+ "HeapVectorBacking doesn't support objects that cannot be cleared as "
+ "unused with memset or don't have a vtable");
+
+ static_assert(
+ !std::is_trivially_destructible<T>::value,
+ "Finalization of trivially destructible classes should not happen.");
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(pointer);
+ // Use the payload size as recorded by the heap to determine how many
+ // elements to finalize.
+ size_t length = header->PayloadSize() / sizeof(T);
+ char* payload = static_cast<char*>(pointer);
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ ANNOTATE_CHANGE_SIZE(payload, length * sizeof(T), 0, length * sizeof(T));
+#endif
+ // As commented above, HeapVectorBacking calls finalizers for unused slots
+ // (which are already zeroed out).
+ if (std::is_polymorphic<T>::value) {
+ for (unsigned i = 0; i < length; ++i) {
+ char* element = payload + i * sizeof(T);
+ if (blink::VTableInitialized(element))
+ reinterpret_cast<T*>(element)->~T();
+ }
+ } else {
+ T* buffer = reinterpret_cast<T*>(payload);
+ for (unsigned i = 0; i < length; ++i)
+ buffer[i].~T();
+ }
+}
+
+template <typename T>
+struct MakeGarbageCollectedTrait<HeapVectorBacking<T>> {
+ static HeapVectorBacking<T>* Call(size_t num_elements) {
+ CHECK_GT(num_elements, 0u);
+ void* memory =
+ HeapVectorBacking<T>::template AllocateObject<HeapVectorBacking<T>>(
+ num_elements * sizeof(T));
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
+ // Placement new as regular operator new() is deleted.
+ HeapVectorBacking<T>* object = ::new (memory) HeapVectorBacking<T>();
+ header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
+ return object;
+ }
+};
+
+template <typename T, typename Traits>
+struct FinalizerTrait<HeapVectorBacking<T, Traits>> {
+ STATIC_ONLY(FinalizerTrait);
+ static const bool kNonTrivialFinalizer = Traits::kNeedsDestruction;
+ static void Finalize(void* obj) {
+ internal::FinalizerTraitImpl<HeapVectorBacking<T, Traits>,
+ kNonTrivialFinalizer>::Finalize(obj);
+ }
+};
+
+template <typename T, typename Traits>
+struct ThreadingTrait<HeapVectorBacking<T, Traits>> {
+ STATIC_ONLY(ThreadingTrait);
+ static const ThreadAffinity kAffinity = ThreadingTrait<T>::Affinity;
+};
+
+template <typename T, typename Traits>
+struct TraceTrait<HeapVectorBacking<T, Traits>> {
+ STATIC_ONLY(TraceTrait);
+ using Backing = HeapVectorBacking<T, Traits>;
+
+ public:
+ static TraceDescriptor GetTraceDescriptor(const void* self) {
+ return {self, TraceTrait<Backing>::Trace};
+ }
+
+ static void Trace(Visitor* visitor, const void* self) {
+ if (visitor->ConcurrentTracingBailOut({self, &Trace}))
+ return;
+
+ static_assert(!WTF::IsWeak<T>::value,
+ "Weakness is not supported in HeapVector and HeapDeque");
+ if (WTF::IsTraceableInCollectionTrait<Traits>::value) {
+ WTF::TraceInCollectionTrait<WTF::kNoWeakHandling,
+ HeapVectorBacking<T, Traits>,
+ void>::Trace(visitor, self);
+ }
+ }
+};
+
+} // namespace blink
+
+namespace WTF {
+
+// This trace method is used only for on-stack HeapVectors found in
+// conservative scanning. On-heap HeapVectors are traced by Vector::trace.
+template <typename T, typename Traits>
+struct TraceInCollectionTrait<kNoWeakHandling,
+ blink::HeapVectorBacking<T, Traits>,
+ void> {
+ static bool Trace(blink::Visitor* visitor, const void* self) {
+ // HeapVectorBacking does not know the exact size of the vector
+ // and just knows the capacity of the vector. Due to the constraint,
+ // HeapVectorBacking can support only the following objects:
+ //
+ // - An object that has a vtable. In this case, HeapVectorBacking
+ // traces only slots that are not zeroed out. This is because if
+ // the object has a vtable, the zeroed slot means that it is
+ // an unused slot (Remember that the unused slots are guaranteed
+ // to be zeroed out by VectorUnusedSlotClearer).
+ //
+ // - An object that can be initialized with memset. In this case,
+ // HeapVectorBacking traces all slots including unused slots.
+ // This is fine because the fact that the object can be initialized
+ // with memset indicates that it is safe to treat the zerod slot
+ // as a valid object.
+ static_assert(!IsTraceableInCollectionTrait<Traits>::value ||
+ Traits::kCanClearUnusedSlotsWithMemset ||
+ std::is_polymorphic<T>::value,
+ "HeapVectorBacking doesn't support objects that cannot be "
+ "cleared as unused with memset.");
+
+ // This trace method is instantiated for vectors where
+ // IsTraceableInCollectionTrait<Traits>::value is false, but the trace
+ // method should not be called. Thus we cannot static-assert
+ // IsTraceableInCollectionTrait<Traits>::value but should runtime-assert it.
+ DCHECK(IsTraceableInCollectionTrait<Traits>::value);
+
+ const T* array = reinterpret_cast<const T*>(self);
+ blink::HeapObjectHeader* header =
+ blink::HeapObjectHeader::FromPayload(self);
+ // Use the payload size as recorded by the heap to determine how many
+ // elements to trace.
+ size_t length = header->PayloadSize() / sizeof(T);
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ // As commented above, HeapVectorBacking can trace unused slots
+ // (which are already zeroed out).
+ ANNOTATE_CHANGE_SIZE(array, length, 0, length);
+#endif
+ if (std::is_polymorphic<T>::value) {
+ const char* pointer = reinterpret_cast<const char*>(array);
+ for (unsigned i = 0; i < length; ++i) {
+ const char* element = pointer + i * sizeof(T);
+ if (blink::VTableInitialized(element)) {
+ blink::TraceIfNeeded<
+ T, IsTraceableInCollectionTrait<Traits>::value>::Trace(visitor,
+ array[i]);
+ }
+ }
+ } else {
+ for (size_t i = 0; i < length; ++i) {
+ blink::TraceIfNeeded<
+ T, IsTraceableInCollectionTrait<Traits>::value>::Trace(visitor,
+ array[i]);
+ }
+ }
+ return false;
+ }
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/concurrent_marking_test.cc b/chromium/third_party/blink/renderer/platform/heap/concurrent_marking_test.cc
index af57b2607c2..8f02fc2e91c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/concurrent_marking_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/concurrent_marking_test.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#if defined(THREAD_SANITIZER)
+
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -31,157 +33,294 @@ class CollectionWrapper : public GarbageCollected<CollectionWrapper<T>> {
};
// =============================================================================
-// Tests that expose data races when modifying collections ================
+// Tests that expose data races when modifying collections =====================
// =============================================================================
-TEST_F(ConcurrentMarkingTest, AddToHashMap) {
+template <typename C>
+void AddToCollection() {
+ constexpr int kIterations = 100;
IncrementalMarkingTestDriver driver(ThreadState::Current());
- using Map = HeapHashMap<Member<IntegerObject>, Member<IntegerObject>>;
- Persistent<CollectionWrapper<Map>> persistent =
- MakeGarbageCollected<CollectionWrapper<Map>>();
- Map* map = persistent->GetCollection();
+ Persistent<CollectionWrapper<C>> persistent =
+ MakeGarbageCollected<CollectionWrapper<C>>();
+ C* collection = persistent->GetCollection();
driver.Start();
- for (int i = 0; i < 100; ++i) {
+ for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep();
- for (int j = 0; j < 100; ++j) {
- int num = 100 * i + j;
- map->insert(MakeGarbageCollected<IntegerObject>(num),
- MakeGarbageCollected<IntegerObject>(num));
+ for (int j = 0; j < kIterations; ++j) {
+ int num = kIterations * i + j;
+ collection->insert(MakeGarbageCollected<IntegerObject>(num));
}
}
driver.FinishSteps();
driver.FinishGC();
}
-TEST_F(ConcurrentMarkingTest, RemoveFromHashMap) {
+template <typename C, typename GetLocation>
+void RemoveFromCollectionAtLocation(GetLocation location) {
+ constexpr int kIterations = 100;
IncrementalMarkingTestDriver driver(ThreadState::Current());
- using Map = HeapHashMap<Member<IntegerObject>, Member<IntegerObject>>;
- Persistent<CollectionWrapper<Map>> persistent =
- MakeGarbageCollected<CollectionWrapper<Map>>();
- Map* map = persistent->GetCollection();
- for (int i = 0; i < 10000; ++i) {
- map->insert(MakeGarbageCollected<IntegerObject>(i),
- MakeGarbageCollected<IntegerObject>(i));
+ Persistent<CollectionWrapper<C>> persistent =
+ MakeGarbageCollected<CollectionWrapper<C>>();
+ C* collection = persistent->GetCollection();
+ for (int i = 0; i < (kIterations * kIterations); ++i) {
+ collection->insert(MakeGarbageCollected<IntegerObject>(i));
}
driver.Start();
- for (int i = 0; i < 100; ++i) {
+ for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep();
- for (int j = 0; j < 100; ++j) {
- map->erase(map->begin());
+ for (int j = 0; j < kIterations; ++j) {
+ collection->erase(location(collection));
}
}
driver.FinishSteps();
driver.FinishGC();
}
-TEST_F(ConcurrentMarkingTest, SwapHashMaps) {
- IncrementalMarkingTestDriver driver(ThreadState::Current());
- using Map = HeapHashMap<Member<IntegerObject>, Member<IntegerObject>>;
- Persistent<CollectionWrapper<Map>> persistent =
- MakeGarbageCollected<CollectionWrapper<Map>>();
- Map* map = persistent->GetCollection();
- driver.Start();
- for (int i = 0; i < 100; ++i) {
- Map new_map;
- for (int j = 0; j < 10 * i; ++j) {
- new_map.insert(MakeGarbageCollected<IntegerObject>(j),
- MakeGarbageCollected<IntegerObject>(j));
- }
- driver.SingleConcurrentStep();
- map->swap(new_map);
- }
- driver.FinishSteps();
- driver.FinishGC();
+template <typename C>
+void RemoveFromBeginningOfCollection() {
+ RemoveFromCollectionAtLocation<C>(
+ [](C* collection) { return collection->begin(); });
}
-TEST_F(ConcurrentMarkingTest, AddToHashSet) {
- IncrementalMarkingTestDriver driver(ThreadState::Current());
- using Set = HeapHashSet<Member<IntegerObject>>;
- Persistent<CollectionWrapper<Set>> persistent =
- MakeGarbageCollected<CollectionWrapper<Set>>();
- Set* set = persistent->GetCollection();
- driver.Start();
- for (int i = 0; i < 100; ++i) {
- driver.SingleConcurrentStep();
- for (int j = 0; j < 100; ++j) {
- int num = 100 * i + j;
- set->insert(MakeGarbageCollected<IntegerObject>(num));
+template <typename C>
+void RemoveFromMiddleOfCollection() {
+ RemoveFromCollectionAtLocation<C>([](C* collection) {
+ auto iterator = collection->begin();
+ // Move iterator to middle of collection.
+ for (size_t i = 0; i < collection->size() / 2; ++i) {
+ ++iterator;
}
- }
- driver.FinishSteps();
- driver.FinishGC();
+ return iterator;
+ });
+}
+
+template <typename C>
+void RemoveFromEndOfCollection() {
+ RemoveFromCollectionAtLocation<C>([](C* collection) {
+ auto iterator = collection->end();
+ return --iterator;
+ });
}
-TEST_F(ConcurrentMarkingTest, RemoveFromHashSet) {
+template <typename C>
+void ClearCollection() {
+ constexpr int kIterations = 10;
IncrementalMarkingTestDriver driver(ThreadState::Current());
- using Set = HeapHashSet<Member<IntegerObject>>;
- Persistent<CollectionWrapper<Set>> persistent =
- MakeGarbageCollected<CollectionWrapper<Set>>();
- Set* set = persistent->GetCollection();
- for (int i = 0; i < 10000; ++i) {
- set->insert(MakeGarbageCollected<IntegerObject>(i));
- }
+ Persistent<CollectionWrapper<C>> persistent =
+ MakeGarbageCollected<CollectionWrapper<C>>();
+ C* collection = persistent->GetCollection();
driver.Start();
- for (int i = 0; i < 100; ++i) {
+ for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep();
- for (int j = 0; j < 100; ++j) {
- set->erase(set->begin());
+ for (int j = 0; j < kIterations; ++j) {
+ collection->insert(MakeGarbageCollected<IntegerObject>(i));
}
+ collection->clear();
}
driver.FinishSteps();
driver.FinishGC();
}
-TEST_F(ConcurrentMarkingTest, SwapHashSets) {
+template <typename C>
+void SwapCollections() {
+ constexpr int kIterations = 10;
IncrementalMarkingTestDriver driver(ThreadState::Current());
- using Set = HeapHashSet<Member<IntegerObject>>;
- Persistent<CollectionWrapper<Set>> persistent =
- MakeGarbageCollected<CollectionWrapper<Set>>();
- Set* set = persistent->GetCollection();
+ Persistent<CollectionWrapper<C>> persistent =
+ MakeGarbageCollected<CollectionWrapper<C>>();
+ C* collection = persistent->GetCollection();
driver.Start();
- for (int i = 0; i < 100; ++i) {
- Set new_set;
- for (int j = 0; j < 10 * i; ++j) {
- new_set.insert(MakeGarbageCollected<IntegerObject>(j));
+ for (int i = 0; i < (kIterations * kIterations); ++i) {
+ C* new_collection = MakeGarbageCollected<C>();
+ for (int j = 0; j < kIterations * i; ++j) {
+ new_collection->insert(MakeGarbageCollected<IntegerObject>(j));
}
driver.SingleConcurrentStep();
- set->swap(new_set);
+ collection->swap(*new_collection);
}
driver.FinishSteps();
driver.FinishGC();
}
-TEST_F(ConcurrentMarkingTest, AddToVector) {
- IncrementalMarkingTestDriver driver(ThreadState::Current());
- using V = HeapVector<Member<IntegerObject>>;
- Persistent<CollectionWrapper<V>> persistent =
- MakeGarbageCollected<CollectionWrapper<V>>();
- V* vector = persistent->GetCollection();
- driver.Start();
- for (int i = 0; i < 100; ++i) {
- driver.SingleConcurrentStep();
- for (int j = 0; j < 100; ++j) {
- int num = 100 * i + j;
- vector->push_back(MakeGarbageCollected<IntegerObject>(num));
- }
+// HeapHashMap
+
+template <typename T>
+class HeapHashMapAdapter : public HeapHashMap<T, T> {
+ public:
+ template <typename U>
+ ALWAYS_INLINE void insert(U* u) {
+ HeapHashMap<T, T>::insert(u, u);
}
- driver.FinishSteps();
- driver.FinishGC();
+};
+
+TEST_F(ConcurrentMarkingTest, AddToHashMap) {
+ AddToCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfHashMap) {
+ RemoveFromBeginningOfCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfHashMap) {
+ RemoveFromMiddleOfCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfHashMap) {
+ RemoveFromEndOfCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearHashMap) {
+ ClearCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapHashMap) {
+ SwapCollections<HeapHashMapAdapter<Member<IntegerObject>>>();
}
-TEST_F(ConcurrentMarkingTest, RemoveFromVector) {
+// HeapHashSet
+
+TEST_F(ConcurrentMarkingTest, AddToHashSet) {
+ AddToCollection<HeapHashSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfHashSet) {
+ RemoveFromBeginningOfCollection<HeapHashSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfHashSet) {
+ RemoveFromMiddleOfCollection<HeapHashSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfHashSet) {
+ RemoveFromEndOfCollection<HeapHashSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearHashSet) {
+ ClearCollection<HeapHashSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapHashSet) {
+ SwapCollections<HeapHashSet<Member<IntegerObject>>>();
+}
+
+// HeapLinkedHashSet
+template <typename T>
+class HeapLinkedHashSetAdapter : public HeapLinkedHashSet<T> {
+ public:
+ ALWAYS_INLINE void swap(HeapLinkedHashSetAdapter<T>& other) {
+ HeapLinkedHashSet<T>::Swap(other);
+ }
+};
+
+TEST_F(ConcurrentMarkingTest, AddToLinkedHashSet) {
+ AddToCollection<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfLinkedHashSet) {
+ RemoveFromBeginningOfCollection<
+ HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfLinkedHashSet) {
+ RemoveFromMiddleOfCollection<
+ HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfLinkedHashSet) {
+ RemoveFromEndOfCollection<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearLinkedHashSet) {
+ ClearCollection<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapLinkedHashSet) {
+ SwapCollections<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+
+// HeapNewLinkedHashSet
+template <typename T>
+class HeapNewLinkedHashSetAdapter : public HeapNewLinkedHashSet<T> {
+ public:
+ ALWAYS_INLINE void swap(HeapNewLinkedHashSetAdapter<T>& other) {
+ HeapNewLinkedHashSet<T>::Swap(other);
+ }
+};
+
+TEST_F(ConcurrentMarkingTest, AddToNewLinkedHashSet) {
+ AddToCollection<HeapNewLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfNewLinkedHashSet) {
+ RemoveFromBeginningOfCollection<
+ HeapNewLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfNewLinkedHashSet) {
+ RemoveFromMiddleOfCollection<
+ HeapNewLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfNewLinkedHashSet) {
+ RemoveFromEndOfCollection<
+ HeapNewLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearNewLinkedHashSet) {
+ ClearCollection<HeapNewLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapNewLinkedHashSet) {
+ SwapCollections<HeapNewLinkedHashSetAdapter<Member<IntegerObject>>>();
+}
+
+// HeapListHashSet
+
+template <typename T>
+class HeapListHashSetAdapter : public HeapListHashSet<T> {
+ public:
+ ALWAYS_INLINE void swap(HeapListHashSetAdapter<T>& other) {
+ HeapListHashSet<T>::Swap(other);
+ }
+};
+
+TEST_F(ConcurrentMarkingTest, AddToListHashSet) {
+ AddToCollection<HeapListHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfListHashSet) {
+ RemoveFromBeginningOfCollection<
+ HeapListHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfListHashSet) {
+ RemoveFromMiddleOfCollection<HeapListHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfListHashSet) {
+ RemoveFromEndOfCollection<HeapListHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearListHashSet) {
+ ClearCollection<HeapListHashSetAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapListHashSet) {
+ SwapCollections<HeapListHashSetAdapter<Member<IntegerObject>>>();
+}
+
+// HeapHashCountedSet
+
+TEST_F(ConcurrentMarkingTest, AddToHashCountedSet) {
+ AddToCollection<HeapHashCountedSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfHashCountedSet) {
+ RemoveFromBeginningOfCollection<HeapHashCountedSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfHashCountedSet) {
+ RemoveFromMiddleOfCollection<HeapHashCountedSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfHashCountedSet) {
+ RemoveFromEndOfCollection<HeapHashCountedSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearHashCountedSet) {
+ ClearCollection<HeapHashCountedSet<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapHashCountedSet) {
+ SwapCollections<HeapHashCountedSet<Member<IntegerObject>>>();
+}
+
+// HeapVector
+
+// Additional test for vectors and deques
+template <typename V>
+void PopFromCollection() {
+ constexpr int kIterations = 100;
IncrementalMarkingTestDriver driver(ThreadState::Current());
- using V = HeapVector<Member<IntegerObject>>;
Persistent<CollectionWrapper<V>> persistent =
MakeGarbageCollected<CollectionWrapper<V>>();
V* vector = persistent->GetCollection();
- for (int i = 0; i < 10000; ++i) {
- vector->push_back(MakeGarbageCollected<IntegerObject>(i));
+ for (int i = 0; i < (kIterations * kIterations); ++i) {
+ vector->insert(MakeGarbageCollected<IntegerObject>(i));
}
driver.Start();
- for (int i = 0; i < 100; ++i) {
+ for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep();
- for (int j = 0; j < 100; ++j) {
+ for (int j = 0; j < kIterations; ++j) {
vector->pop_back();
}
}
@@ -189,24 +328,160 @@ TEST_F(ConcurrentMarkingTest, RemoveFromVector) {
driver.FinishGC();
}
-TEST_F(ConcurrentMarkingTest, SwapVectors) {
- IncrementalMarkingTestDriver driver(ThreadState::Current());
- using V = HeapVector<Member<IntegerObject>>;
- Persistent<CollectionWrapper<V>> persistent =
- MakeGarbageCollected<CollectionWrapper<V>>();
- V* vector = persistent->GetCollection();
- driver.Start();
- for (int i = 0; i < 100; ++i) {
- V new_vector;
- for (int j = 0; j < 10 * i; ++j) {
- new_vector.push_back(MakeGarbageCollected<IntegerObject>(j));
- }
- driver.SingleConcurrentStep();
- vector->swap(new_vector);
+#define TEST_VECTOR_COLLECTION(name, type) \
+ TEST_F(ConcurrentMarkingTest, AddTo##name) { AddToCollection<type>(); } \
+ TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOf##name) { \
+ RemoveFromBeginningOfCollection<type>(); \
+ } \
+ TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOf##name) { \
+ RemoveFromMiddleOfCollection<type>(); \
+ } \
+ TEST_F(ConcurrentMarkingTest, RemoveFromEndOf##name) { \
+ RemoveFromEndOfCollection<type>(); \
+ } \
+ TEST_F(ConcurrentMarkingTest, Clear##name) { ClearCollection<type>(); } \
+ TEST_F(ConcurrentMarkingTest, Swap##name) { SwapCollections<type>(); } \
+ TEST_F(ConcurrentMarkingTest, PopFrom##name) { PopFromCollection<type>(); }
+
+template <typename T, wtf_size_t inlineCapacity = 0>
+class HeapVectorAdapter : public HeapVector<T, inlineCapacity> {
+ using Base = HeapVector<T, inlineCapacity>;
+
+ public:
+ template <typename U>
+ ALWAYS_INLINE void insert(U* u) {
+ Base::push_back(u);
}
- driver.FinishSteps();
- driver.FinishGC();
+};
+
+TEST_F(ConcurrentMarkingTest, AddToVector) {
+ AddToCollection<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfVector) {
+ RemoveFromBeginningOfCollection<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfVector) {
+ RemoveFromMiddleOfCollection<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfVector) {
+ RemoveFromEndOfCollection<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearVector) {
+ ClearCollection<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapVector) {
+ SwapCollections<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, PopFromVector) {
+ PopFromCollection<HeapVectorAdapter<Member<IntegerObject>>>();
+}
+
+// HeapVector with inlined buffer
+
+template <typename T>
+class HeapInlinedVectorAdapter : public HeapVectorAdapter<T, 100> {};
+
+TEST_F(ConcurrentMarkingTest, AddToInlinedVector) {
+ AddToCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfInlinedVector) {
+ RemoveFromBeginningOfCollection<
+ HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfInlinedVector) {
+ RemoveFromMiddleOfCollection<
+ HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfInlinedVector) {
+ RemoveFromEndOfCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearInlinedVector) {
+ ClearCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapInlinedVector) {
+ SwapCollections<HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, PopFromInlinedVector) {
+ PopFromCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>();
+}
+
+// HeapVector of std::pairs
+
+template <typename T>
+class HeapVectorOfPairsAdapter : public HeapVector<std::pair<T, T>> {
+ using Base = HeapVector<std::pair<T, T>>;
+
+ public:
+ template <typename U>
+ ALWAYS_INLINE void insert(U* u) {
+ Base::push_back(std::make_pair<T, T>(u, u));
+ }
+};
+
+TEST_F(ConcurrentMarkingTest, AddToVectorOfPairs) {
+ AddToCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfVectorOfPairs) {
+ RemoveFromBeginningOfCollection<
+ HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfVectorOfPairs) {
+ RemoveFromMiddleOfCollection<
+ HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfVectorOfPairs) {
+ RemoveFromEndOfCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearVectorOfPairs) {
+ ClearCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapVectorOfPairs) {
+ SwapCollections<HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, PopFromVectorOfPairs) {
+ PopFromCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
+}
+
+// HeapDeque
+
+template <typename T>
+class HeapDequeAdapter : public HeapDeque<T> {
+ public:
+ template <typename U>
+ ALWAYS_INLINE void insert(U* u) {
+ HeapDeque<T>::push_back(u);
+ }
+ ALWAYS_INLINE void erase(typename HeapDeque<T>::iterator) {
+ HeapDeque<T>::pop_back();
+ }
+ ALWAYS_INLINE void swap(HeapDequeAdapter<T>& other) {
+ HeapDeque<T>::Swap(other);
+ }
+};
+
+TEST_F(ConcurrentMarkingTest, AddToDeque) {
+ AddToCollection<HeapDequeAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfDeque) {
+ RemoveFromBeginningOfCollection<HeapDequeAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfDeque) {
+ RemoveFromMiddleOfCollection<HeapDequeAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, RemoveFromEndOfDeque) {
+ RemoveFromEndOfCollection<HeapDequeAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, ClearDeque) {
+ ClearCollection<HeapDequeAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, SwapDeque) {
+ SwapCollections<HeapDequeAdapter<Member<IntegerObject>>>();
+}
+TEST_F(ConcurrentMarkingTest, PopFromDeque) {
+ PopFromCollection<HeapDequeAdapter<Member<IntegerObject>>>();
}
} // namespace concurrent_marking_test
} // namespace blink
+
+#endif // defined(THREAD_SANITIZER)
diff --git a/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h b/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h
index 03ff1d959fb..232c3b95b68 100644
--- a/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h
@@ -91,10 +91,6 @@ struct FinalizerTrait {
};
class HeapAllocator;
-template <typename T, typename Traits>
-class HeapVectorBacking;
-template <typename Table>
-class HeapHashTableBacking;
template <typename T, typename U, typename V>
struct FinalizerTrait<LinkedHashSet<T, U, V, HeapAllocator>> {
@@ -139,27 +135,6 @@ struct FinalizerTrait<Deque<T, inlineCapacity, HeapAllocator>> {
}
};
-template <typename Table>
-struct FinalizerTrait<HeapHashTableBacking<Table>> {
- STATIC_ONLY(FinalizerTrait);
- static const bool kNonTrivialFinalizer =
- !std::is_trivially_destructible<typename Table::ValueType>::value;
- static void Finalize(void* obj) {
- internal::FinalizerTraitImpl<HeapHashTableBacking<Table>,
- kNonTrivialFinalizer>::Finalize(obj);
- }
-};
-
-template <typename T, typename Traits>
-struct FinalizerTrait<HeapVectorBacking<T, Traits>> {
- STATIC_ONLY(FinalizerTrait);
- static const bool kNonTrivialFinalizer = Traits::kNeedsDestruction;
- static void Finalize(void* obj) {
- internal::FinalizerTraitImpl<HeapVectorBacking<T, Traits>,
- kNonTrivialFinalizer>::Finalize(obj);
- }
-};
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FINALIZER_TRAITS_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h b/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
index d0f4d272e94..4f0495c4f3b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
+++ b/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
@@ -53,7 +53,7 @@ struct TraceDescriptor {
public:
// The adjusted base pointer of the object that should be traced.
- void* base_object_payload;
+ const void* base_object_payload;
// A callback for tracing the object.
TraceCallback callback;
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/gc_info.cc b/chromium/third_party/blink/renderer/platform/heap/gc_info.cc
index b6ea60e7f93..61b0f2e43b3 100644
--- a/chromium/third_party/blink/renderer/platform/heap/gc_info.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/gc_info.cc
@@ -43,43 +43,46 @@ constexpr size_t MaxTableSize() {
} // namespace
GCInfoTable* GCInfoTable::global_table_ = nullptr;
-constexpr uint32_t GCInfoTable::kMaxIndex;
+constexpr GCInfoIndex GCInfoTable::kMaxIndex;
+constexpr GCInfoIndex GCInfoTable::kMinIndex;
void GCInfoTable::CreateGlobalTable() {
DEFINE_STATIC_LOCAL(GCInfoTable, table, ());
global_table_ = &table;
}
-uint32_t GCInfoTable::EnsureGCInfoIndex(
+GCInfoIndex GCInfoTable::EnsureGCInfoIndex(
const GCInfo* gc_info,
- std::atomic<uint32_t>* gc_info_index_slot) {
+ std::atomic<GCInfoIndex>* gc_info_index_slot) {
DCHECK(gc_info);
DCHECK(gc_info_index_slot);
- // Ensuring a new index involves current index adjustment as well
- // as potentially resizing the table, both operations that require
- // a lock.
+ // Ensuring a new index involves current index adjustment as well as
+ // potentially resizing the table. For simplicity we use a lock.
MutexLocker locker(table_mutex_);
- // If more than one thread ends up allocating a slot for
- // the same GCInfo, have later threads reuse the slot
- // allocated by the first.
- uint32_t gc_info_index = gc_info_index_slot->load(std::memory_order_acquire);
+ // If more than one thread ends up allocating a slot for the same GCInfo, have
+ // later threads reuse the slot allocated by the first.
+ GCInfoIndex gc_info_index =
+ gc_info_index_slot->load(std::memory_order_relaxed);
if (gc_info_index)
return gc_info_index;
- gc_info_index = ++current_index_;
- CHECK(gc_info_index < GCInfoTable::kMaxIndex);
- if (current_index_ >= limit_)
+ if (current_index_ == limit_)
Resize();
+ gc_info_index = current_index_++;
+ CHECK_LT(gc_info_index, GCInfoTable::kMaxIndex);
+
table_[gc_info_index] = gc_info;
gc_info_index_slot->store(gc_info_index, std::memory_order_release);
return gc_info_index;
}
void GCInfoTable::Resize() {
- const size_t new_limit = (limit_) ? 2 * limit_ : ComputeInitialTableLimit();
+ const GCInfoIndex new_limit =
+ (limit_) ? 2 * limit_ : ComputeInitialTableLimit();
+ CHECK_GT(new_limit, limit_);
const size_t old_committed_size = limit_ * kEntrySize;
const size_t new_committed_size = new_limit * kEntrySize;
CHECK(table_);
@@ -107,11 +110,10 @@ void GCInfoTable::Resize() {
}
#endif // DCHECK_IS_ON()
- limit_ = static_cast<uint32_t>(new_limit);
+ limit_ = new_limit;
}
GCInfoTable::GCInfoTable() {
- CHECK(!table_);
table_ = reinterpret_cast<GCInfo const**>(base::AllocPages(
nullptr, MaxTableSize(), base::kPageAllocationGranularity,
base::PageInaccessible, base::PageTag::kBlinkGC));
@@ -119,16 +121,4 @@ GCInfoTable::GCInfoTable() {
Resize();
}
-#if DCHECK_IS_ON()
-void AssertObjectHasGCInfo(const void* payload, size_t gc_info_index) {
- HeapObjectHeader::CheckFromPayload(payload);
-#if !defined(COMPONENT_BUILD)
- // On component builds we cannot compare the gcInfos as they are statically
- // defined in each of the components and hence will not match.
- DCHECK_EQ(HeapObjectHeader::FromPayload(payload)->GcInfoIndex(),
- gc_info_index);
-#endif
-}
-#endif
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/gc_info.h b/chromium/third_party/blink/renderer/platform/heap/gc_info.h
index 36b53cc0c17..cf4d5a01c94 100644
--- a/chromium/third_party/blink/renderer/platform/heap/gc_info.h
+++ b/chromium/third_party/blink/renderer/platform/heap/gc_info.h
@@ -9,35 +9,26 @@
#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/platform/heap/finalizer_traits.h"
#include "third_party/blink/renderer/platform/heap/name_traits.h"
-#include "third_party/blink/renderer/platform/heap/visitor.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/hash_table.h"
-#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/list_hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/type_traits.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
+template <typename T>
+struct TraceTrait;
+
+using GCInfoIndex = uint32_t;
+
// GCInfo contains metadata for objects that are instantiated from classes that
// inherit from GarbageCollected.
-struct GCInfo {
+struct PLATFORM_EXPORT GCInfo final {
+ static inline const GCInfo& From(GCInfoIndex);
+
const TraceCallback trace;
const FinalizationCallback finalize;
const NameCallback name;
const bool has_v_table;
};
-#if DCHECK_IS_ON()
-PLATFORM_EXPORT void AssertObjectHasGCInfo(const void*, uint32_t gc_info_index);
-#endif
-
-class PLATFORM_EXPORT GCInfoTable {
+class PLATFORM_EXPORT GCInfoTable final {
public:
// At maximum |kMaxIndex - 1| indices are supported.
//
@@ -46,29 +37,36 @@ class PLATFORM_EXPORT GCInfoTable {
// of the Oilpan GC Clang plugin, there appear to be at most about 6,000
// types. Thus 14 bits should be more than twice as many bits as we will ever
// need.
- static constexpr uint32_t kMaxIndex = 1 << 14;
+ static constexpr GCInfoIndex kMaxIndex = 1 << 14;
+
+ // Minimum index returned. Values smaller |kMinIndex| may be used as
+ // sentinels.
+ static constexpr GCInfoIndex kMinIndex = 1;
// Sets up a singleton table that can be acquired using Get().
static void CreateGlobalTable();
- static GCInfoTable& Get() { return *global_table_; }
+ static GCInfoTable* GetMutable() { return global_table_; }
+ static const GCInfoTable& Get() { return *global_table_; }
- inline const GCInfo* GCInfoFromIndex(uint32_t index) {
- DCHECK_GE(index, 1u);
+ const GCInfo& GCInfoFromIndex(GCInfoIndex index) const {
+ DCHECK_GE(index, kMinIndex);
DCHECK_LT(index, kMaxIndex);
DCHECK(table_);
const GCInfo* info = table_[index];
DCHECK(info);
- return info;
+ return *info;
}
- uint32_t EnsureGCInfoIndex(const GCInfo*, std::atomic<std::uint32_t>*);
+ GCInfoIndex EnsureGCInfoIndex(const GCInfo*, std::atomic<GCInfoIndex>*);
- uint32_t GcInfoIndex() const { return current_index_; }
+ // Returns the number of recorded GCInfo objects, including |kMinIndex|.
+ GCInfoIndex NumberOfGCInfos() const { return current_index_; }
private:
FRIEND_TEST_ALL_PREFIXES(GCInfoTest, InitialEmpty);
FRIEND_TEST_ALL_PREFIXES(GCInfoTest, ResizeToMaxIndex);
+ FRIEND_TEST_ALL_PREFIXES(GCInfoDeathTest, MoreThanMaxIndexInfos);
// Singleton for each process. Retrieved through Get().
static GCInfoTable* global_table_;
@@ -83,20 +81,25 @@ class PLATFORM_EXPORT GCInfoTable {
// index into this table.
const GCInfo** table_ = nullptr;
- // GCInfo indices start from 1 for heap objects, with 0 being treated
- // specially as the index for freelist entries and large heap objects.
- uint32_t current_index_ = 0;
+ // Current index used when requiring a new GCInfo object.
+ GCInfoIndex current_index_ = kMinIndex;
// The limit (exclusive) of the currently allocated table.
- uint32_t limit_ = 0;
+ GCInfoIndex limit_ = 0;
Mutex table_mutex_;
};
+// static
+const GCInfo& GCInfo::From(GCInfoIndex index) {
+ return GCInfoTable::Get().GCInfoFromIndex(index);
+}
+
template <typename T>
struct GCInfoTrait {
STATIC_ONLY(GCInfoTrait);
- static uint32_t Index() {
+
+ static GCInfoIndex Index() {
static_assert(sizeof(T), "T must be fully defined");
static const GCInfo kGcInfo = {
TraceTrait<T>::Trace,
@@ -105,11 +108,13 @@ struct GCInfoTrait {
NameTrait<T>::GetName, std::is_polymorphic<T>::value};
// This is more complicated than using threadsafe initialization, but this
// is instantiated many times (once for every GC type).
- static std::atomic<std::uint32_t> gc_info_index{0};
- uint32_t index = gc_info_index.load(std::memory_order_acquire);
- if (!index)
- index = GCInfoTable::Get().EnsureGCInfoIndex(&kGcInfo, &gc_info_index);
- DCHECK_GE(index, 1u);
+ static std::atomic<GCInfoIndex> gc_info_index{0};
+ GCInfoIndex index = gc_info_index.load(std::memory_order_acquire);
+ if (!index) {
+ index = GCInfoTable::GetMutable()->EnsureGCInfoIndex(&kGcInfo,
+ &gc_info_index);
+ }
+ DCHECK_GE(index, GCInfoTable::kMinIndex);
DCHECK_LT(index, GCInfoTable::kMaxIndex);
return index;
}
@@ -118,49 +123,6 @@ struct GCInfoTrait {
template <typename U>
class GCInfoTrait<const U> : public GCInfoTrait<U> {};
-template <typename T, typename U, typename V, typename W, typename X>
-class HeapHashMap;
-template <typename T, typename U, typename V>
-class HeapHashSet;
-template <typename T, typename U, typename V>
-class HeapLinkedHashSet;
-template <typename T, wtf_size_t inlineCapacity, typename U>
-class HeapListHashSet;
-template <typename ValueArg, wtf_size_t inlineCapacity>
-class HeapListHashSetAllocator;
-template <typename T, wtf_size_t inlineCapacity>
-class HeapVector;
-template <typename T, wtf_size_t inlineCapacity>
-class HeapDeque;
-template <typename T, typename U, typename V>
-class HeapHashCountedSet;
-
-template <typename T, typename U, typename V, typename W, typename X>
-struct GCInfoTrait<HeapHashMap<T, U, V, W, X>>
- : public GCInfoTrait<HashMap<T, U, V, W, X, HeapAllocator>> {};
-template <typename T, typename U, typename V>
-struct GCInfoTrait<HeapHashSet<T, U, V>>
- : public GCInfoTrait<HashSet<T, U, V, HeapAllocator>> {};
-template <typename T, typename U, typename V>
-struct GCInfoTrait<HeapLinkedHashSet<T, U, V>>
- : public GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator>> {};
-template <typename T, wtf_size_t inlineCapacity, typename U>
-struct GCInfoTrait<HeapListHashSet<T, inlineCapacity, U>>
- : public GCInfoTrait<
- ListHashSet<T,
- inlineCapacity,
- U,
- HeapListHashSetAllocator<T, inlineCapacity>>> {};
-template <typename T, wtf_size_t inlineCapacity>
-struct GCInfoTrait<HeapVector<T, inlineCapacity>>
- : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> {};
-template <typename T, wtf_size_t inlineCapacity>
-struct GCInfoTrait<HeapDeque<T, inlineCapacity>>
- : public GCInfoTrait<Deque<T, inlineCapacity, HeapAllocator>> {};
-template <typename T, typename U, typename V>
-struct GCInfoTrait<HeapHashCountedSet<T, U, V>>
- : public GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator>> {};
-
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/platform/heap/gc_info_test.cc b/chromium/third_party/blink/renderer/platform/heap/gc_info_test.cc
index d6786ef34ab..0a4e667c914 100644
--- a/chromium/third_party/blink/renderer/platform/heap/gc_info_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/gc_info_test.cc
@@ -10,20 +10,36 @@ namespace blink {
TEST(GCInfoTest, InitialEmpty) {
GCInfoTable table;
- EXPECT_EQ(0u, table.GcInfoIndex());
+ EXPECT_EQ(GCInfoTable::kMinIndex, table.NumberOfGCInfos());
}
TEST(GCInfoTest, ResizeToMaxIndex) {
GCInfoTable table;
GCInfo info = {nullptr, nullptr, nullptr, false};
- std::atomic<std::uint32_t> slot{0};
- for (uint32_t i = 0; i < (GCInfoTable::kMaxIndex - 1); i++) {
+ std::atomic<GCInfoIndex> slot{0};
+ for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex;
+ i++) {
slot = 0;
- uint32_t index = table.EnsureGCInfoIndex(&info, &slot);
+ GCInfoIndex index = table.EnsureGCInfoIndex(&info, &slot);
EXPECT_EQ(index, slot);
EXPECT_LT(0u, slot);
- EXPECT_EQ(&info, table.GCInfoFromIndex(slot));
+ EXPECT_EQ(&info, &table.GCInfoFromIndex(index));
}
}
+TEST(GCInfoDeathTest, MoreThanMaxIndexInfos) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ GCInfoTable table;
+ GCInfo info = {nullptr, nullptr, nullptr, false};
+ std::atomic<GCInfoIndex> slot{0};
+ // Create GCInfoTable::kMaxIndex entries.
+ for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex;
+ i++) {
+ slot = 0;
+ table.EnsureGCInfoIndex(&info, &slot);
+ }
+ slot = 0;
+ EXPECT_DEATH(table.EnsureGCInfoIndex(&info, &slot), "");
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap.cc b/chromium/third_party/blink/renderer/platform/heap/heap.cc
index 6f4ce3f280d..b1c28d9798c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap.cc
@@ -102,8 +102,9 @@ ThreadHeap::ThreadHeap(ThreadState* thread_state)
main_thread_heap_ = this;
for (int arena_index = 0; arena_index < BlinkGC::kLargeObjectArenaIndex;
- arena_index++)
+ arena_index++) {
arenas_[arena_index] = new NormalPageArena(thread_state_, arena_index);
+ }
arenas_[BlinkGC::kLargeObjectArenaIndex] =
new LargeObjectArena(thread_state_, BlinkGC::kLargeObjectArenaIndex);
@@ -138,18 +139,47 @@ Address ThreadHeap::CheckAndMarkPointer(MarkingVisitor* visitor,
return nullptr;
}
-void ThreadHeap::SetupWorklists() {
+void ThreadHeap::VisitRememberedSets(MarkingVisitor* visitor) {
+ static_assert(BlinkGC::kLargeObjectArenaIndex + 1 == BlinkGC::kNumberOfArenas,
+ "LargeObject arena must be the last one.");
+ const auto visit_header = [visitor](HeapObjectHeader* header) {
+ // Process only old objects.
+ if (header->IsOld<HeapObjectHeader::AccessMode::kNonAtomic>()) {
+ // The design of young generation requires collections to be executed at
+ // the top level (with the guarantee that no objects are currently being
+ // in construction). This can be ensured by running young GCs from safe
+ // points or by reintroducing nested allocation scopes that avoid
+ // finalization.
+ DCHECK(header->IsMarked());
+ DCHECK(!MarkingVisitor::IsInConstruction(header));
+ const GCInfo& gc_info = GCInfo::From(header->GcInfoIndex());
+ gc_info.trace(visitor, header->Payload());
+ }
+ };
+ for (size_t i = 0; i < BlinkGC::kLargeObjectArenaIndex; ++i) {
+ static_cast<NormalPageArena*>(arenas_[i])
+ ->IterateAndClearCardTables(visit_header);
+ }
+ static_cast<LargeObjectArena*>(arenas_[BlinkGC::kLargeObjectArenaIndex])
+ ->IterateAndClearRememberedPages(visit_header);
+}
+
+void ThreadHeap::SetupWorklists(bool should_initialize_compaction_worklists) {
marking_worklist_.reset(new MarkingWorklist());
write_barrier_worklist_.reset(new WriteBarrierWorklist());
not_fully_constructed_worklist_.reset(new NotFullyConstructedWorklist());
previously_not_fully_constructed_worklist_.reset(
new NotFullyConstructedWorklist());
weak_callback_worklist_.reset(new WeakCallbackWorklist());
- movable_reference_worklist_.reset(new MovableReferenceWorklist());
weak_table_worklist_.reset(new WeakTableWorklist);
- backing_store_callback_worklist_.reset(new BackingStoreCallbackWorklist());
v8_references_worklist_.reset(new V8ReferencesWorklist());
+ not_safe_to_concurrently_trace_worklist_.reset(
+ new NotSafeToConcurrentlyTraceWorklist());
DCHECK(ephemeron_callbacks_.IsEmpty());
+ if (should_initialize_compaction_worklists) {
+ movable_reference_worklist_.reset(new MovableReferenceWorklist());
+ backing_store_callback_worklist_.reset(new BackingStoreCallbackWorklist());
+ }
}
void ThreadHeap::DestroyMarkingWorklists(BlinkGC::StackState stack_state) {
@@ -159,6 +189,7 @@ void ThreadHeap::DestroyMarkingWorklists(BlinkGC::StackState stack_state) {
weak_callback_worklist_.reset(nullptr);
weak_table_worklist_.reset();
v8_references_worklist_.reset();
+ not_safe_to_concurrently_trace_worklist_.reset();
ephemeron_callbacks_.clear();
// The fixed point iteration may have found not-fully-constructed objects.
@@ -201,8 +232,8 @@ HeapCompact* ThreadHeap::Compaction() {
return compaction_.get();
}
-bool ThreadHeap::ShouldRegisterMovingAddress(Address address) {
- return Compaction()->ShouldRegisterMovingAddress(address);
+bool ThreadHeap::ShouldRegisterMovingAddress() {
+ return Compaction()->ShouldRegisterMovingAddress();
}
void ThreadHeap::FlushNotFullyConstructedObjects() {
@@ -226,40 +257,8 @@ void ThreadHeap::MarkNotFullyConstructedObjects(MarkingVisitor* visitor) {
while (not_fully_constructed_worklist_->Pop(WorklistTaskId::MutatorThread,
&item)) {
BasePage* const page = PageFromObject(item);
- visitor->ConservativelyMarkAddress(page, reinterpret_cast<Address>(item));
- }
-}
-
-void ThreadHeap::InvokeEphemeronCallbacks(MarkingVisitor* visitor) {
- // Mark any strong pointers that have now become reachable in ephemeron maps.
- ThreadHeapStatsCollector::Scope stats_scope(
- stats_collector(),
- ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks);
-
- // We first reiterate over known callbacks from previous iterations.
- for (auto& tuple : ephemeron_callbacks_)
- tuple.value(visitor, tuple.key);
-
- DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
-
- // Then we iterate over the new callbacks found by the marking visitor.
- // Callbacks found by the concurrent marking will be flushed eventually
- // and then invoked by the mutator thread (in the atomic pause at latest).
- while (
- !weak_table_worklist_->IsLocalViewEmpty(WorklistTaskId::MutatorThread)) {
- // Read ephemeron callbacks from worklist to ephemeron_callbacks_ hashmap.
- WeakTableWorklist::View ephemerons_worklist(weak_table_worklist_.get(),
- WorklistTaskId::MutatorThread);
- WeakTableItem item;
- while (ephemerons_worklist.Pop(&item)) {
- auto result =
- ephemeron_callbacks_.insert(item.base_object_payload, item.callback);
- DCHECK(result.is_new_entry ||
- result.stored_value->value == item.callback);
- if (result.is_new_entry) {
- item.callback(visitor, item.base_object_payload);
- }
- }
+ visitor->ConservativelyMarkAddress(page,
+ reinterpret_cast<ConstAddress>(item));
}
}
@@ -288,6 +287,45 @@ bool DrainWorklistWithDeadline(base::TimeTicks deadline,
} // namespace
+bool ThreadHeap::InvokeEphemeronCallbacks(MarkingVisitor* visitor,
+ base::TimeTicks deadline) {
+ // Mark any strong pointers that have now become reachable in ephemeron maps.
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(),
+ ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks);
+
+ // We first reiterate over known callbacks from previous iterations.
+ constexpr size_t kDeadlineCheckInterval = 250;
+ size_t processed_callback_count = 0;
+ for (auto& tuple : ephemeron_callbacks_) {
+ tuple.value(visitor, tuple.key);
+ if (++processed_callback_count == kDeadlineCheckInterval) {
+ if (deadline <= base::TimeTicks::Now()) {
+ return false;
+ }
+ processed_callback_count = 0;
+ }
+ }
+
+ DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
+
+ // Then we iterate over the new callbacks found by the marking visitor.
+ // Callbacks found by the concurrent marking will be flushed eventually
+ // and then invoked by the mutator thread (in the atomic pause at latest).
+ return DrainWorklistWithDeadline(
+ deadline, weak_table_worklist_.get(),
+ [this, visitor](const WeakTableItem& item) {
+ auto result = ephemeron_callbacks_.insert(item.base_object_payload,
+ item.callback);
+ DCHECK(result.is_new_entry ||
+ result.stored_value->value == item.callback);
+ if (result.is_new_entry) {
+ item.callback(visitor, item.base_object_payload);
+ }
+ },
+ WorklistTaskId::MutatorThread);
+}
+
bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
base::TimeTicks deadline) {
DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
@@ -301,6 +339,39 @@ bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
ThreadHeapStatsCollector::Scope stats_scope(
stats_collector(), ThreadHeapStatsCollector::kMarkProcessWorklist);
+ // Start with mutator-thread-only worklists (not fully constructed).
+ // If time runs out, concurrent markers can take care of the rest.
+
+ // Convert |previously_not_fully_constructed_worklist_| to
+ // |marking_worklist_|. This merely re-adds items with the proper
+ // callbacks.
+ finished = DrainWorklistWithDeadline(
+ deadline, previously_not_fully_constructed_worklist_.get(),
+ [visitor](NotFullyConstructedItem& item) {
+ visitor->DynamicallyMarkAddress(
+ reinterpret_cast<ConstAddress>(item));
+ },
+ WorklistTaskId::MutatorThread);
+ if (!finished)
+ break;
+
+ {
+ ThreadHeapStatsCollector::EnabledScope bailout_scope(
+ stats_collector(), ThreadHeapStatsCollector::kMarkBailOutObjects);
+ finished = DrainWorklistWithDeadline(
+ deadline, not_safe_to_concurrently_trace_worklist_.get(),
+ [visitor](const MarkingItem& item) {
+ item.callback(visitor, item.base_object_payload);
+ },
+ WorklistTaskId::MutatorThread);
+ if (!finished)
+ break;
+ }
+
+ finished = FlushV8References(deadline);
+ if (!finished)
+ break;
+
finished = DrainWorklistWithDeadline(
deadline, marking_worklist_.get(),
[visitor](const MarkingItem& item) {
@@ -318,66 +389,61 @@ bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
deadline, write_barrier_worklist_.get(),
[visitor](HeapObjectHeader* header) {
DCHECK(!MarkingVisitor::IsInConstruction(header));
- GCInfoTable::Get()
- .GCInfoFromIndex(header->GcInfoIndex())
- ->trace(visitor, header->Payload());
+ GCInfo::From(header->GcInfoIndex())
+ .trace(visitor, header->Payload());
visitor->AccountMarkedBytes(header);
},
WorklistTaskId::MutatorThread);
if (!finished)
break;
-
- // Convert |previously_not_fully_constructed_worklist_| to
- // |marking_worklist_|. This merely re-adds items with the proper
- // callbacks.
- finished = DrainWorklistWithDeadline(
- deadline, previously_not_fully_constructed_worklist_.get(),
- [visitor](const NotFullyConstructedItem& item) {
- visitor->DynamicallyMarkAddress(reinterpret_cast<Address>(item));
- },
- WorklistTaskId::MutatorThread);
- if (!finished)
- break;
}
- InvokeEphemeronCallbacks(visitor);
+ finished = InvokeEphemeronCallbacks(visitor, deadline);
+ if (!finished)
+ break;
// Rerun loop if ephemeron processing queued more objects for tracing.
} while (!marking_worklist_->IsLocalViewEmpty(WorklistTaskId::MutatorThread));
- FlushV8References();
-
return finished;
}
+bool ThreadHeap::HasWorkForConcurrentMarking() const {
+ return !marking_worklist_->IsGlobalPoolEmpty() ||
+ !write_barrier_worklist_->IsGlobalPoolEmpty();
+}
+
bool ThreadHeap::AdvanceConcurrentMarking(ConcurrentMarkingVisitor* visitor,
base::TimeTicks deadline) {
- bool finished = false;
- // Iteratively mark all objects that are reachable from the objects
- // currently pushed onto the marking worklist.
- finished = DrainWorklistWithDeadline(
- deadline, marking_worklist_.get(),
- [visitor](const MarkingItem& item) {
- HeapObjectHeader* header =
- HeapObjectHeader::FromPayload(item.base_object_payload);
- DCHECK(!ConcurrentMarkingVisitor::IsInConstruction(header));
- item.callback(visitor, item.base_object_payload);
- visitor->AccountMarkedBytes(header);
- },
- visitor->task_id());
- if (!finished)
- return false;
-
- finished = DrainWorklistWithDeadline(
- deadline, write_barrier_worklist_.get(),
- [visitor](HeapObjectHeader* header) {
- DCHECK(!ConcurrentMarkingVisitor::IsInConstruction(header));
- GCInfoTable::Get()
- .GCInfoFromIndex(header->GcInfoIndex())
- ->trace(visitor, header->Payload());
- visitor->AccountMarkedBytes(header);
- },
- visitor->task_id());
+ bool finished;
+ do {
+ // Iteratively mark all objects that are reachable from the objects
+ // currently pushed onto the marking worklist.
+ finished = DrainWorklistWithDeadline(
+ deadline, marking_worklist_.get(),
+ [visitor](const MarkingItem& item) {
+ HeapObjectHeader* header =
+ HeapObjectHeader::FromPayload(item.base_object_payload);
+ DCHECK(!ConcurrentMarkingVisitor::IsInConstruction(header));
+ item.callback(visitor, item.base_object_payload);
+ visitor->AccountMarkedBytesSafe(header);
+ },
+ visitor->task_id());
+ if (!finished)
+ break;
+
+ finished = DrainWorklistWithDeadline(
+ deadline, write_barrier_worklist_.get(),
+ [visitor](HeapObjectHeader* header) {
+ DCHECK(!ConcurrentMarkingVisitor::IsInConstruction(header));
+ GCInfo::From(header->GcInfoIndex()).trace(visitor, header->Payload());
+ visitor->AccountMarkedBytesSafe(header);
+ },
+ visitor->task_id());
+ if (!finished)
+ break;
+ } while (HasWorkForConcurrentMarking());
+
return finished;
}
@@ -413,7 +479,7 @@ size_t ThreadHeap::ObjectPayloadSizeForTesting() {
size_t object_payload_size = 0;
thread_state_->SetGCPhase(ThreadState::GCPhase::kMarking);
thread_state_->Heap().MakeConsistentForGC();
- thread_state_->Heap().PrepareForSweep();
+ thread_state_->Heap().PrepareForSweep(BlinkGC::CollectionType::kMajor);
for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i)
object_payload_size += arenas_[i]->ObjectPayloadSizeForTesting();
MakeConsistentForMutator();
@@ -427,7 +493,7 @@ void ThreadHeap::ResetAllocationPointForTesting() {
arenas_[i]->ResetAllocationPoint();
}
-BasePage* ThreadHeap::LookupPageForAddress(Address address) {
+BasePage* ThreadHeap::LookupPageForAddress(ConstAddress address) {
if (PageMemoryRegion* region = region_tree_->Lookup(address)) {
return region->PageFromAddress(address);
}
@@ -436,14 +502,23 @@ BasePage* ThreadHeap::LookupPageForAddress(Address address) {
void ThreadHeap::MakeConsistentForGC() {
DCHECK(thread_state_->InAtomicMarkingPause());
- for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i)
- arenas_[i]->MakeConsistentForGC();
+ for (BaseArena* arena : arenas_) {
+ arena->MakeConsistentForGC();
+ }
}
void ThreadHeap::MakeConsistentForMutator() {
DCHECK(thread_state_->InAtomicMarkingPause());
- for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i)
- arenas_[i]->MakeConsistentForMutator();
+ for (BaseArena* arena : arenas_) {
+ arena->MakeConsistentForMutator();
+ }
+}
+
+void ThreadHeap::Unmark() {
+ DCHECK(thread_state_->InAtomicMarkingPause());
+ for (BaseArena* arena : arenas_) {
+ arena->Unmark();
+ }
}
void ThreadHeap::Compact() {
@@ -468,11 +543,11 @@ void ThreadHeap::Compact() {
Compaction()->Finish();
}
-void ThreadHeap::PrepareForSweep() {
+void ThreadHeap::PrepareForSweep(BlinkGC::CollectionType collection_type) {
DCHECK(thread_state_->InAtomicMarkingPause());
DCHECK(thread_state_->CheckThread());
for (int i = 0; i < BlinkGC::kNumberOfArenas; i++)
- arenas_[i]->PrepareForSweep();
+ arenas_[i]->PrepareForSweep(collection_type);
}
void ThreadHeap::RemoveAllPages() {
@@ -519,45 +594,53 @@ void ThreadHeap::CollectStatistics(ThreadState::Statistics* stats) {
#undef SNAPSHOT_ARENA
}
-bool ThreadHeap::AdvanceSweep(SweepingType sweeping_type,
- base::TimeTicks deadline) {
+bool ThreadHeap::AdvanceLazySweep(base::TimeTicks deadline) {
static constexpr base::TimeDelta slack = base::TimeDelta::FromSecondsD(0.001);
- auto sweeping_function = sweeping_type == SweepingType::kMutator
- ? &BaseArena::LazySweepWithDeadline
- : &BaseArena::ConcurrentSweepWithDeadline;
for (size_t i = 0; i < BlinkGC::kNumberOfArenas; i++) {
// lazySweepWithDeadline() won't check the deadline until it sweeps
// 10 pages. So we give a small slack for safety.
const base::TimeDelta remaining_budget =
deadline - slack - base::TimeTicks::Now();
if (remaining_budget <= base::TimeDelta() ||
- !(arenas_[i]->*sweeping_function)(deadline)) {
+ !arenas_[i]->LazySweepWithDeadline(deadline)) {
return false;
}
}
return true;
}
+bool ThreadHeap::AdvanceConcurrentSweep(base::JobDelegate* job) {
+ for (size_t i = 0; i < BlinkGC::kNumberOfArenas; i++) {
+ while (!arenas_[i]->ConcurrentSweepOnePage()) {
+ if (job->ShouldYield())
+ return false;
+ }
+ }
+ return true;
+}
+
// TODO(omerkatz): Temporary solution until concurrent marking is ready. see
// https://crrev.com/c/1730054 for details. Eventually this will be removed.
-void ThreadHeap::FlushV8References() {
+bool ThreadHeap::FlushV8References(base::TimeTicks deadline) {
if (!thread_state_->IsUnifiedGCMarkingInProgress())
- return;
+ return true;
DCHECK(base::FeatureList::IsEnabled(
blink::features::kBlinkHeapConcurrentMarking) ||
v8_references_worklist_->IsGlobalEmpty());
- V8ReferencesWorklist::View v8_references(v8_references_worklist_.get(),
- WorklistTaskId::MutatorThread);
- V8Reference reference;
v8::EmbedderHeapTracer* controller =
reinterpret_cast<v8::EmbedderHeapTracer*>(
thread_state_->unified_heap_controller());
- while (v8_references.Pop(&reference)) {
- controller->RegisterEmbedderReference(
- reference->template Cast<v8::Data>().Get());
- }
+ return DrainWorklistWithDeadline(
+ deadline, v8_references_worklist_.get(),
+ [controller](const V8Reference& reference) {
+ if (!reference->Get().IsEmpty()) {
+ controller->RegisterEmbedderReference(
+ reference->template Cast<v8::Data>().Get());
+ }
+ },
+ WorklistTaskId::MutatorThread);
}
ThreadHeap* ThreadHeap::main_thread_heap_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap.h b/chromium/third_party/blink/renderer/platform/heap/heap.h
index 5fa69d97c07..953dd7839f0 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap.h
@@ -68,17 +68,17 @@ class ProcessHeapReporter;
class RegionTree;
using MarkingItem = TraceDescriptor;
-using NotFullyConstructedItem = void*;
+using NotFullyConstructedItem = const void*;
using WeakTableItem = MarkingItem;
struct BackingStoreCallbackItem {
- void* backing;
+ const void* backing;
MovingObjectCallback callback;
};
struct CustomCallbackItem {
WeakCallback callback;
- void* parameter;
+ const void* parameter;
};
using V8Reference = const TraceWrapperV8Reference<v8::Value>*;
@@ -86,19 +86,21 @@ using V8Reference = const TraceWrapperV8Reference<v8::Value>*;
// Segment size of 512 entries necessary to avoid throughput regressions. Since
// the work list is currently a temporary object this is not a problem.
using MarkingWorklist = Worklist<MarkingItem, 512 /* local entries */>;
-using WriteBarrierWorklist = Worklist<HeapObjectHeader*, 256>;
+using WriteBarrierWorklist = Worklist<HeapObjectHeader*, 64>;
using NotFullyConstructedWorklist =
Worklist<NotFullyConstructedItem, 16 /* local entries */>;
using WeakCallbackWorklist =
- Worklist<CustomCallbackItem, 256 /* local entries */>;
+ Worklist<CustomCallbackItem, 64 /* local entries */>;
// Using large local segments here (sized 512 entries) to avoid throughput
// regressions.
using MovableReferenceWorklist =
- Worklist<MovableReference*, 512 /* local entries */>;
+ Worklist<const MovableReference*, 256 /* local entries */>;
using WeakTableWorklist = Worklist<WeakTableItem, 16 /* local entries */>;
using BackingStoreCallbackWorklist =
Worklist<BackingStoreCallbackItem, 16 /* local entries */>;
using V8ReferencesWorklist = Worklist<V8Reference, 16 /* local entries */>;
+using NotSafeToConcurrentlyTraceWorklist =
+ Worklist<MarkingItem, 64 /* local entries */>;
class PLATFORM_EXPORT HeapAllocHooks {
STATIC_ONLY(HeapAllocHooks);
@@ -260,6 +262,10 @@ class PLATFORM_EXPORT ThreadHeap {
return v8_references_worklist_.get();
}
+ NotSafeToConcurrentlyTraceWorklist* GetNotSafeToConcurrentlyTraceWorklist()
+ const {
+ return not_safe_to_concurrently_trace_worklist_.get();
+ }
// Register an ephemeron table for fixed-point iteration.
void RegisterWeakTable(void* container_object,
EphemeronCallback);
@@ -268,7 +274,7 @@ class PLATFORM_EXPORT ThreadHeap {
// Checks whether we need to register |addr| as a backing store or a slot
// containing reference to it.
- bool ShouldRegisterMovingAddress(Address addr);
+ bool ShouldRegisterMovingAddress();
RegionTree* GetRegionTree() { return region_tree_.get(); }
@@ -302,6 +308,8 @@ class PLATFORM_EXPORT ThreadHeap {
bool AdvanceMarking(MarkingVisitor*, base::TimeTicks deadline);
void VerifyMarking();
+ // Returns true if concurrent markers will have work to steal
+ bool HasWorkForConcurrentMarking() const;
// Returns true if marker is done
bool AdvanceConcurrentMarking(ConcurrentMarkingVisitor*, base::TimeTicks);
@@ -309,6 +317,9 @@ class PLATFORM_EXPORT ThreadHeap {
// thread heaps. If so marks the object pointed to as live.
Address CheckAndMarkPointer(MarkingVisitor*, Address);
+ // Visits remembered sets.
+ void VisitRememberedSets(MarkingVisitor*);
+
size_t ObjectPayloadSizeForTesting();
void ResetAllocationPointForTesting();
@@ -317,7 +328,7 @@ class PLATFORM_EXPORT ThreadHeap {
// This look-up uses the region search tree and a negative contains cache to
// provide an efficient mapping from arbitrary addresses to the containing
// heap-page if one exists.
- BasePage* LookupPageForAddress(Address);
+ BasePage* LookupPageForAddress(ConstAddress);
HeapCompact* Compaction();
@@ -341,12 +352,16 @@ class PLATFORM_EXPORT ThreadHeap {
// the executions of mutators.
void MakeConsistentForMutator();
+ // Unmarks all objects in the entire heap. This is supposed to be called in
+ // the beginning of major GC.
+ void Unmark();
+
void Compact();
- enum class SweepingType : uint8_t { kMutator, kConcurrent };
- bool AdvanceSweep(SweepingType sweeping_type, base::TimeTicks deadline);
+ bool AdvanceLazySweep(base::TimeTicks deadline);
+ bool AdvanceConcurrentSweep(base::JobDelegate*);
- void PrepareForSweep();
+ void PrepareForSweep(BlinkGC::CollectionType);
void RemoveAllPages();
void InvokeFinalizersOnSweptPages();
void CompleteSweep();
@@ -374,16 +389,24 @@ class PLATFORM_EXPORT ThreadHeap {
PageBloomFilter* page_bloom_filter() { return page_bloom_filter_.get(); }
+ bool IsInLastAllocatedRegion(Address address) const;
+ void SetLastAllocatedRegion(Address start, size_t length);
+
private:
+ struct LastAllocatedRegion {
+ Address start = nullptr;
+ size_t length = 0;
+ };
+
static int ArenaIndexForObjectSize(size_t);
- void SetupWorklists();
+ void SetupWorklists(bool);
void DestroyMarkingWorklists(BlinkGC::StackState);
void DestroyCompactionWorklists();
- void InvokeEphemeronCallbacks(MarkingVisitor*);
+ bool InvokeEphemeronCallbacks(MarkingVisitor*, base::TimeTicks);
- void FlushV8References();
+ bool FlushV8References(base::TimeTicks);
ThreadState* thread_state_;
std::unique_ptr<ThreadHeapStatsCollector> heap_stats_collector_;
@@ -436,12 +459,17 @@ class PLATFORM_EXPORT ThreadHeap {
// to V8.
std::unique_ptr<V8ReferencesWorklist> v8_references_worklist_;
+ std::unique_ptr<NotSafeToConcurrentlyTraceWorklist>
+ not_safe_to_concurrently_trace_worklist_;
+
// No duplicates allowed for ephemeron callbacks. Hence, we use a hashmap
// with the key being the HashTable.
- WTF::HashMap<void*, EphemeronCallback> ephemeron_callbacks_;
+ WTF::HashMap<const void*, EphemeronCallback> ephemeron_callbacks_;
std::unique_ptr<HeapCompact> compaction_;
+ LastAllocatedRegion last_allocated_region_;
+
BaseArena* arenas_[BlinkGC::kNumberOfArenas];
static ThreadHeap* main_thread_heap_;
@@ -457,31 +485,22 @@ template <typename T>
class GarbageCollected {
IS_GARBAGE_COLLECTED_TYPE();
- // For now direct allocation of arrays on the heap is not allowed.
- void* operator new[](size_t size);
-
-#if defined(OS_WIN) && defined(COMPILER_MSVC)
- // Due to some quirkiness in the MSVC compiler we have to provide
- // the delete[] operator in the GarbageCollected subclasses as it
- // is called when a class is exported in a DLL.
- protected:
- void operator delete[](void* p) { NOTREACHED(); }
-#else
- void operator delete[](void* p);
-#endif
-
public:
using ParentMostGarbageCollectedType = T;
- void* operator new(size_t size) = delete; // Must use MakeGarbageCollected.
+ // Must use MakeGarbageCollected.
+ void* operator new(size_t) = delete;
+ void* operator new[](size_t) = delete;
+ // The garbage collector is taking care of reclaiming the object. Also,
+ // virtual destructor requires an unambiguous, accessible 'operator delete'.
+ void operator delete(void*) { NOTREACHED(); }
+ void operator delete[](void*) = delete;
template <typename Derived>
static void* AllocateObject(size_t size) {
return ThreadHeap::Allocate<GCInfoFoldedType<Derived>>(size);
}
- void operator delete(void* p) { NOTREACHED(); }
-
protected:
// This trait in theory can be moved to gc_info.h, but that would cause
// significant memory bloat caused by huge number of ThreadHeap::Allocate<>
@@ -513,61 +532,75 @@ class GarbageCollected {
DISALLOW_COPY_AND_ASSIGN(GarbageCollected);
};
-// Default MakeGarbageCollected: Constructs an instance of T, which is a garbage
-// collected type.
-template <typename T, typename... Args>
-T* MakeGarbageCollected(Args&&... args) {
- static_assert(WTF::IsGarbageCollectedType<T>::value,
- "T needs to be a garbage collected object");
- static_assert(std::is_trivially_destructible<T>::value ||
- std::has_virtual_destructor<T>::value ||
- std::is_final<T>::value ||
- internal::IsGarbageCollectedContainer<T>::value ||
- internal::HasFinalizeGarbageCollectedObject<T>::value,
- "Finalized GarbageCollected class should either have a virtual "
- "destructor or be marked as final");
- static_assert(!IsGarbageCollectedMixin<T>::value ||
- sizeof(T) <= kLargeObjectSizeThreshold,
- "GarbageCollectedMixin may not be a large object");
- void* memory = T::template AllocateObject<T>(sizeof(T));
- HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
- // Placement new as regular operator new() is deleted.
- T* object = ::new (memory) T(std::forward<Args>(args)...);
- header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
- return object;
-}
-
// Used for passing custom sizes to MakeGarbageCollected.
struct AdditionalBytes {
explicit AdditionalBytes(size_t bytes) : value(bytes) {}
const size_t value;
};
+template <typename T>
+struct MakeGarbageCollectedTrait {
+ template <typename... Args>
+ static T* Call(Args&&... args) {
+ static_assert(WTF::IsGarbageCollectedType<T>::value,
+ "T needs to be a garbage collected object");
+ static_assert(
+ std::is_trivially_destructible<T>::value ||
+ std::has_virtual_destructor<T>::value || std::is_final<T>::value ||
+ internal::IsGarbageCollectedContainer<T>::value ||
+ internal::HasFinalizeGarbageCollectedObject<T>::value,
+ "Finalized GarbageCollected class should either have a virtual "
+ "destructor or be marked as final");
+ static_assert(!IsGarbageCollectedMixin<T>::value ||
+ sizeof(T) <= kLargeObjectSizeThreshold,
+ "GarbageCollectedMixin may not be a large object");
+ void* memory = T::template AllocateObject<T>(sizeof(T));
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
+ // Placement new as regular operator new() is deleted.
+ T* object = ::new (memory) T(std::forward<Args>(args)...);
+ header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
+ return object;
+ }
+
+ template <typename... Args>
+ static T* Call(AdditionalBytes additional_bytes, Args&&... args) {
+ static_assert(WTF::IsGarbageCollectedType<T>::value,
+ "T needs to be a garbage collected object");
+ static_assert(
+ std::is_trivially_destructible<T>::value ||
+ std::has_virtual_destructor<T>::value || std::is_final<T>::value ||
+ internal::IsGarbageCollectedContainer<T>::value ||
+ internal::HasFinalizeGarbageCollectedObject<T>::value,
+ "Finalized GarbageCollected class should either have a virtual "
+ "destructor or be marked as final.");
+ const size_t size = sizeof(T) + additional_bytes.value;
+ if (IsGarbageCollectedMixin<T>::value) {
+ // Ban large mixin so we can use PageFromObject() on them.
+ CHECK_GE(kLargeObjectSizeThreshold, size)
+ << "GarbageCollectedMixin may not be a large object";
+ }
+ void* memory = T::template AllocateObject<T>(size);
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
+ // Placement new as regular operator new() is deleted.
+ T* object = ::new (memory) T(std::forward<Args>(args)...);
+ header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
+ return object;
+ }
+};
+
+// Default MakeGarbageCollected: Constructs an instance of T, which is a garbage
+// collected type.
+template <typename T, typename... Args>
+T* MakeGarbageCollected(Args&&... args) {
+ return MakeGarbageCollectedTrait<T>::Call(std::forward<Args>(args)...);
+}
+
// Constructs an instance of T, which is a garbage collected type. This special
// version takes size which enables constructing inline objects.
template <typename T, typename... Args>
T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) {
- static_assert(WTF::IsGarbageCollectedType<T>::value,
- "T needs to be a garbage collected object");
- static_assert(std::is_trivially_destructible<T>::value ||
- std::has_virtual_destructor<T>::value ||
- std::is_final<T>::value ||
- internal::IsGarbageCollectedContainer<T>::value ||
- internal::HasFinalizeGarbageCollectedObject<T>::value,
- "Finalized GarbageCollected class should either have a virtual "
- "destructor or be marked as final.");
- const size_t size = sizeof(T) + additional_bytes.value;
- if (IsGarbageCollectedMixin<T>::value) {
- // Ban large mixin so we can use PageFromObject() on them.
- CHECK_GE(kLargeObjectSizeThreshold, size)
- << "GarbageCollectedMixin may not be a large object";
- }
- void* memory = T::template AllocateObject<T>(size);
- HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
- // Placement new as regular operator new() is deleted.
- T* object = ::new (memory) T(std::forward<Args>(args)...);
- header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
- return object;
+ return MakeGarbageCollectedTrait<T>::Call(additional_bytes,
+ std::forward<Args>(args)...);
}
// Assigning class types to their arenas.
@@ -620,9 +653,21 @@ Address ThreadHeap::Allocate(size_t size) {
GCInfoTrait<T>::Index(), type_name);
}
+inline bool ThreadHeap::IsInLastAllocatedRegion(Address address) const {
+ return last_allocated_region_.start <= address &&
+ address <
+ (last_allocated_region_.start + last_allocated_region_.length);
+}
+
+inline void ThreadHeap::SetLastAllocatedRegion(Address start, size_t length) {
+ last_allocated_region_.start = start;
+ last_allocated_region_.length = length;
+}
+
template <typename T>
-void Visitor::HandleWeakCell(const WeakCallbackInfo&, void* object) {
- WeakMember<T>* weak_member = reinterpret_cast<WeakMember<T>*>(object);
+void Visitor::HandleWeakCell(const WeakCallbackInfo&, const void* object) {
+ WeakMember<T>* weak_member =
+ reinterpret_cast<WeakMember<T>*>(const_cast<void*>(object));
if (weak_member->Get()) {
if (weak_member->IsHashTableDeletedValue()) {
// This can happen when weak fields are deleted while incremental marking
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
index d41fe4e422c..867165c8079 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -8,6 +8,8 @@
#include <type_traits>
#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_buildflags.h"
#include "third_party/blink/renderer/platform/heap/marking_visitor.h"
@@ -45,26 +47,6 @@ template <typename T>
struct IsAllowedInContainer<T, typename T::IsDisallowedInContainerMarker>
: std::false_type {};
-template <typename T, typename Traits = WTF::VectorTraits<T>>
-class HeapVectorBacking {
- DISALLOW_NEW();
- IS_GARBAGE_COLLECTED_TYPE();
-
- public:
- static void Finalize(void* pointer);
- void FinalizeGarbageCollectedObject() { Finalize(this); }
-};
-
-template <typename Table>
-class HeapHashTableBacking {
- DISALLOW_NEW();
- IS_GARBAGE_COLLECTED_TYPE();
-
- public:
- static void Finalize(void* pointer);
- void FinalizeGarbageCollectedObject() { Finalize(this); }
-};
-
// This is a static-only class used as a trait on collections to make them heap
// allocated. However see also HeapListHashSetAllocator.
class PLATFORM_EXPORT HeapAllocator {
@@ -88,16 +70,8 @@ class PLATFORM_EXPORT HeapAllocator {
}
template <typename T>
static T* AllocateVectorBacking(size_t size) {
- ThreadState* state =
- ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
- DCHECK(state->IsAllocationAllowed());
- uint32_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
- const char* type_name =
- WTF_HEAP_PROFILER_TYPE_NAME(HeapHashTableBacking<HeapVectorBacking<T>>);
return reinterpret_cast<T*>(
- MarkAsConstructed(state->Heap().AllocateOnArenaIndex(
- state, ThreadHeap::AllocationSizeFromSize(size),
- BlinkGC::kVectorArenaIndex, gc_info_index, type_name)));
+ MakeGarbageCollected<HeapVectorBacking<T>>(size / sizeof(T)));
}
static void FreeVectorBacking(void*);
static bool ExpandVectorBacking(void*, size_t);
@@ -107,16 +81,9 @@ class PLATFORM_EXPORT HeapAllocator {
template <typename T, typename HashTable>
static T* AllocateHashTableBacking(size_t size) {
- uint32_t gc_info_index =
- GCInfoTrait<HeapHashTableBacking<HashTable>>::Index();
- ThreadState* state =
- ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
- const char* type_name =
- WTF_HEAP_PROFILER_TYPE_NAME(HeapHashTableBacking<HashTable>);
return reinterpret_cast<T*>(
- MarkAsConstructed(state->Heap().AllocateOnArenaIndex(
- state, size, BlinkGC::kHashTableArenaIndex, gc_info_index,
- type_name)));
+ MakeGarbageCollected<HeapHashTableBacking<HashTable>>(
+ size / sizeof(typename HashTable::ValueType)));
}
template <typename T, typename HashTable>
static T* AllocateZeroedHashTableBacking(size_t size) {
@@ -125,19 +92,27 @@ class PLATFORM_EXPORT HeapAllocator {
static void FreeHashTableBacking(void* address);
static bool ExpandHashTableBacking(void*, size_t);
- static void TraceMarkedBackingStore(void* address) {
- MarkingVisitor::TraceMarkedBackingStore(address);
+ static void TraceBackingStoreIfMarked(const void* address) {
+ // Trace backing store elements only if backing store was marked. The
+ // sweeper may be active on the backing store which requires atomic mark bit
+ // access. A precise filter is performed in
+ // MarkingVisitor::TraceMarkedBackingStore.
+ if (HeapObjectHeader::FromPayload(address)
+ ->IsMarked<HeapObjectHeader::AccessMode::kAtomic>()) {
+ MarkingVisitor::TraceMarkedBackingStore(address);
+ }
}
- static void BackingWriteBarrier(void* address) {
- MarkingVisitor::WriteBarrier(address);
+ template <typename T>
+ static void BackingWriteBarrier(T** slot) {
+ MarkingVisitor::WriteBarrier(slot);
}
- template <typename HashTable>
- static void BackingWriteBarrierForHashTable(void* address) {
- if (MarkingVisitor::WriteBarrier(address)) {
+ template <typename HashTable, typename T>
+ static void BackingWriteBarrierForHashTable(T** slot) {
+ if (MarkingVisitor::WriteBarrier(slot)) {
AddMovingCallback<HashTable>(
- static_cast<typename HashTable::ValueType*>(address));
+ static_cast<typename HashTable::ValueType*>(*slot));
}
}
@@ -167,13 +142,18 @@ class PLATFORM_EXPORT HeapAllocator {
return ThreadState::Current()->SweepForbidden();
}
+ static bool IsIncrementalMarking() {
+ return ThreadState::IsAnyIncrementalMarking() &&
+ ThreadState::Current()->IsIncrementalMarking();
+ }
+
template <typename T>
static bool IsHeapObjectAlive(T* object) {
return ThreadHeap::IsHeapObjectAlive(object);
}
template <typename T, typename Traits>
- static void Trace(blink::Visitor* visitor, T& t) {
+ static void Trace(Visitor* visitor, const T& t) {
TraceCollectionIfEnabled<WTF::WeakHandlingTrait<T>::value, T,
Traits>::Trace(visitor, &t);
}
@@ -195,84 +175,106 @@ class PLATFORM_EXPORT HeapAllocator {
template <typename T, typename Traits>
static void NotifyNewObject(T* object) {
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ ThreadState* const thread_state = ThreadState::Current();
+ if (!thread_state->IsIncrementalMarking()) {
+ MarkingVisitor::GenerationalBarrier(reinterpret_cast<Address>(object),
+ thread_state);
+ return;
+ }
+#else
if (!ThreadState::IsAnyIncrementalMarking())
return;
// The object may have been in-place constructed as part of a large object.
// It is not safe to retrieve the page from the object here.
ThreadState* const thread_state = ThreadState::Current();
- if (thread_state->IsIncrementalMarking()) {
- // Eagerly trace the object ensuring that the object and all its children
- // are discovered by the marker.
- ThreadState::NoAllocationScope no_allocation_scope(thread_state);
- DCHECK(thread_state->CurrentVisitor());
- // No weak handling for write barriers. Modifying weakly reachable objects
- // strongifies them for the current cycle.
- DCHECK(!Traits::kCanHaveDeletedValue || !Traits::IsDeletedValue(*object));
- TraceCollectionIfEnabled<WTF::kNoWeakHandling, T, Traits>::Trace(
- thread_state->CurrentVisitor(), object);
+ if (!thread_state->IsIncrementalMarking()) {
+ return;
}
+#endif // BLINK_HEAP_YOUNG_GENERATION
+ // Eagerly trace the object ensuring that the object and all its children
+ // are discovered by the marker.
+ ThreadState::NoAllocationScope no_allocation_scope(thread_state);
+ DCHECK(thread_state->CurrentVisitor());
+ // No weak handling for write barriers. Modifying weakly reachable objects
+ // strongifies them for the current cycle.
+ DCHECK(!Traits::kCanHaveDeletedValue || !Traits::IsDeletedValue(*object));
+ TraceCollectionIfEnabled<WTF::kNoWeakHandling, T, Traits>::Trace(
+ thread_state->CurrentVisitor(), object);
}
template <typename T, typename Traits>
static void NotifyNewObjects(T* array, size_t len) {
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ ThreadState* const thread_state = ThreadState::Current();
+ if (!thread_state->IsIncrementalMarking()) {
+ MarkingVisitor::GenerationalBarrier(reinterpret_cast<Address>(array),
+ thread_state);
+ return;
+ }
+#else
if (!ThreadState::IsAnyIncrementalMarking())
return;
// The object may have been in-place constructed as part of a large object.
// It is not safe to retrieve the page from the object here.
ThreadState* const thread_state = ThreadState::Current();
- if (thread_state->IsIncrementalMarking()) {
- // See |NotifyNewObject| for details.
- ThreadState::NoAllocationScope no_allocation_scope(thread_state);
- DCHECK(thread_state->CurrentVisitor());
- // No weak handling for write barriers. Modifying weakly reachable objects
- // strongifies them for the current cycle.
- while (len-- > 0) {
- DCHECK(!Traits::kCanHaveDeletedValue ||
- !Traits::IsDeletedValue(*array));
- TraceCollectionIfEnabled<WTF::kNoWeakHandling, T, Traits>::Trace(
- thread_state->CurrentVisitor(), array);
- array++;
- }
+ if (!thread_state->IsIncrementalMarking()) {
+ return;
+ }
+#endif // BLINK_HEAP_YOUNG_GENERATION
+ // See |NotifyNewObject| for details.
+ ThreadState::NoAllocationScope no_allocation_scope(thread_state);
+ DCHECK(thread_state->CurrentVisitor());
+ // No weak handling for write barriers. Modifying weakly reachable objects
+ // strongifies them for the current cycle.
+ while (len-- > 0) {
+ DCHECK(!Traits::kCanHaveDeletedValue || !Traits::IsDeletedValue(*array));
+ TraceCollectionIfEnabled<WTF::kNoWeakHandling, T, Traits>::Trace(
+ thread_state->CurrentVisitor(), array);
+ array++;
}
}
template <typename T>
static void TraceVectorBacking(Visitor* visitor,
- T* backing,
- T** backing_slot) {
+ const T* backing,
+ const T* const* backing_slot) {
visitor->TraceBackingStoreStrongly(
- reinterpret_cast<HeapVectorBacking<T>*>(backing),
- reinterpret_cast<HeapVectorBacking<T>**>(backing_slot));
+ reinterpret_cast<const HeapVectorBacking<T>*>(backing),
+ reinterpret_cast<const HeapVectorBacking<T>* const*>(backing_slot));
}
template <typename T, typename HashTable>
static void TraceHashTableBackingStrongly(Visitor* visitor,
- T* backing,
- T** backing_slot) {
+ const T* backing,
+ const T* const* backing_slot) {
visitor->TraceBackingStoreStrongly(
- reinterpret_cast<HeapHashTableBacking<HashTable>*>(backing),
- reinterpret_cast<HeapHashTableBacking<HashTable>**>(backing_slot));
+ reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing),
+ reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>(
+ backing_slot));
}
template <typename T, typename HashTable>
static void TraceHashTableBackingWeakly(Visitor* visitor,
- T* backing,
- T** backing_slot,
+ const T* backing,
+ const T* const* backing_slot,
WeakCallback callback,
- void* parameter) {
+ const void* parameter) {
visitor->TraceBackingStoreWeakly<HashTable>(
- reinterpret_cast<HeapHashTableBacking<HashTable>*>(backing),
- reinterpret_cast<HeapHashTableBacking<HashTable>**>(backing_slot),
+ reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing),
+ reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>(
+ backing_slot),
callback, parameter);
}
template <typename T, typename HashTable>
static void TraceHashTableBackingOnly(Visitor* visitor,
- T* backing,
- T** backing_slot) {
+ const T* backing,
+ const T* const* backing_slot) {
visitor->TraceBackingStoreOnly(
- reinterpret_cast<HeapHashTableBacking<HashTable>*>(backing),
- reinterpret_cast<HeapHashTableBacking<HashTable>**>(backing_slot));
+ reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing),
+ reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>(
+ backing_slot));
}
private:
@@ -318,7 +320,8 @@ class PLATFORM_EXPORT HeapAllocator {
};
template <typename VisitorDispatcher, typename Value>
-static void TraceListHashSetValue(VisitorDispatcher visitor, Value& value) {
+static void TraceListHashSetValue(VisitorDispatcher visitor,
+ const Value& value) {
// We use the default hash traits for the value in the node, because
// ListHashSet does not let you specify any specific ones.
// We don't allow ListHashSet of WeakMember, so we set that one false
@@ -376,64 +379,22 @@ class HeapListHashSetAllocator : public HeapAllocator {
}
template <typename VisitorDispatcher>
- static void TraceValue(VisitorDispatcher visitor, Node* node) {
+ static void TraceValue(VisitorDispatcher visitor, const Node* node) {
TraceListHashSetValue(visitor, node->value_);
}
};
-template <typename T, typename Traits>
-void HeapVectorBacking<T, Traits>::Finalize(void* pointer) {
- static_assert(Traits::kNeedsDestruction,
- "Only vector buffers with items requiring destruction should "
- "be finalized");
- // See the comment in HeapVectorBacking::trace.
- static_assert(
- Traits::kCanClearUnusedSlotsWithMemset || std::is_polymorphic<T>::value,
- "HeapVectorBacking doesn't support objects that cannot be cleared as "
- "unused with memset or don't have a vtable");
-
- static_assert(
- !std::is_trivially_destructible<T>::value,
- "Finalization of trivially destructible classes should not happen.");
- HeapObjectHeader* header = HeapObjectHeader::FromPayload(pointer);
- // Use the payload size as recorded by the heap to determine how many
- // elements to finalize.
- size_t length = header->PayloadSize() / sizeof(T);
- char* payload = static_cast<char*>(pointer);
-#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
- ANNOTATE_CHANGE_SIZE(payload, length * sizeof(T), 0, length * sizeof(T));
-#endif
- // As commented above, HeapVectorBacking calls finalizers for unused slots
- // (which are already zeroed out).
- if (std::is_polymorphic<T>::value) {
- for (unsigned i = 0; i < length; ++i) {
- char* element = payload + i * sizeof(T);
- if (blink::VTableInitialized(element))
- reinterpret_cast<T*>(element)->~T();
- }
- } else {
- T* buffer = reinterpret_cast<T*>(payload);
- for (unsigned i = 0; i < length; ++i)
- buffer[i].~T();
- }
-}
+namespace internal {
-template <typename Table>
-void HeapHashTableBacking<Table>::Finalize(void* pointer) {
- using Value = typename Table::ValueType;
- static_assert(
- !std::is_trivially_destructible<Value>::value,
- "Finalization of trivially destructible classes should not happen.");
- HeapObjectHeader* header = HeapObjectHeader::FromPayload(pointer);
- // Use the payload size as recorded by the heap to determine how many
- // elements to finalize.
- size_t length = header->PayloadSize() / sizeof(Value);
- Value* table = reinterpret_cast<Value*>(pointer);
- for (unsigned i = 0; i < length; ++i) {
- if (!Table::IsEmptyOrDeletedBucket(table[i]))
- table[i].~Value();
- }
-}
+template <typename T>
+constexpr bool IsMember = WTF::IsSubclassOfTemplate<T, Member>::value;
+
+template <typename T>
+constexpr bool IsMemberOrWeakMemberType =
+ WTF::IsSubclassOfTemplate<T, Member>::value ||
+ WTF::IsSubclassOfTemplate<T, WeakMember>::value;
+
+} // namespace internal
template <typename KeyArg,
typename MappedArg,
@@ -475,6 +436,10 @@ class HeapHashMap : public HashMap<KeyArg,
HeapHashMap() { CheckType(); }
};
+template <typename T, typename U, typename V, typename W, typename X>
+struct GCInfoTrait<HeapHashMap<T, U, V, W, X>>
+ : public GCInfoTrait<HashMap<T, U, V, W, X, HeapAllocator>> {};
+
template <typename ValueArg,
typename HashArg = typename DefaultHash<ValueArg>::Hash,
typename TraitsArg = HashTraits<ValueArg>>
@@ -484,6 +449,8 @@ class HeapHashSet
DISALLOW_NEW();
static void CheckType() {
+ static_assert(internal::IsMemberOrWeakMemberType<ValueArg>,
+ "HeapHashSet supports only Member and WeakMember.");
static_assert(std::is_trivially_destructible<HeapHashSet>::value,
"HeapHashSet must be trivially destructible.");
static_assert(
@@ -504,6 +471,10 @@ class HeapHashSet
HeapHashSet() { CheckType(); }
};
+template <typename T, typename U, typename V>
+struct GCInfoTrait<HeapHashSet<T, U, V>>
+ : public GCInfoTrait<HashSet<T, U, V, HeapAllocator>> {};
+
template <typename ValueArg,
typename HashArg = typename DefaultHash<ValueArg>::Hash,
typename TraitsArg = HashTraits<ValueArg>>
@@ -516,6 +487,8 @@ class HeapLinkedHashSet
DISALLOW_IN_CONTAINER();
static void CheckType() {
+ static_assert(internal::IsMemberOrWeakMemberType<ValueArg>,
+ "HeapLinkedHashSet supports only Member and WeakMember.");
static_assert(
IsAllowedInContainer<ValueArg>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
@@ -534,6 +507,45 @@ class HeapLinkedHashSet
HeapLinkedHashSet() { CheckType(); }
};
+template <typename T, typename U, typename V>
+struct GCInfoTrait<HeapLinkedHashSet<T, U, V>>
+ : public GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator>> {};
+
+// This class is still experimental. Do not use this class.
+template <typename ValueArg>
+class HeapNewLinkedHashSet : public NewLinkedHashSet<ValueArg, HeapAllocator> {
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
+ DISALLOW_NEW();
+
+ static void CheckType() {
+ // TODO(keinakashima): support WeakMember<T>
+ static_assert(internal::IsMember<ValueArg>,
+ "HeapNewLinkedHashSet supports only Member.");
+ // If not trivially destructible, we have to add a destructor which will
+ // hinder performance.
+ static_assert(std::is_trivially_destructible<HeapNewLinkedHashSet>::value,
+ "HeapNewLinkedHashSet must be trivially destructible.");
+ static_assert(
+ IsAllowedInContainer<ValueArg>::value,
+ "Not allowed to directly nest type. Use Member<> indirection instead.");
+ static_assert(WTF::IsTraceable<ValueArg>::value,
+ "For sets without traceable elements, use NewLinkedHashSet<> "
+ "instead of HeapNewLinkedHashSet<>.");
+ }
+
+ public:
+ template <typename>
+ static void* AllocateObject(size_t size) {
+ return ThreadHeap::Allocate<HeapNewLinkedHashSet<ValueArg>>(size);
+ }
+
+ HeapNewLinkedHashSet() { CheckType(); }
+};
+
+template <typename T>
+struct GCInfoTrait<HeapNewLinkedHashSet<T>>
+ : public GCInfoTrait<NewLinkedHashSet<T, HeapAllocator>> {};
+
template <typename ValueArg,
wtf_size_t inlineCapacity =
0, // The inlineCapacity is just a dummy to
@@ -548,6 +560,8 @@ class HeapListHashSet
DISALLOW_NEW();
static void CheckType() {
+ static_assert(internal::IsMemberOrWeakMemberType<ValueArg>,
+ "HeapListHashSet supports only Member and WeakMember.");
static_assert(std::is_trivially_destructible<HeapListHashSet>::value,
"HeapListHashSet must be trivially destructible.");
static_assert(
@@ -568,6 +582,14 @@ class HeapListHashSet
HeapListHashSet() { CheckType(); }
};
+template <typename T, wtf_size_t inlineCapacity, typename U>
+struct GCInfoTrait<HeapListHashSet<T, inlineCapacity, U>>
+ : public GCInfoTrait<
+ ListHashSet<T,
+ inlineCapacity,
+ U,
+ HeapListHashSetAllocator<T, inlineCapacity>>> {};
+
template <typename Value,
typename HashFunctions = typename DefaultHash<Value>::Hash,
typename Traits = HashTraits<Value>>
@@ -577,6 +599,8 @@ class HeapHashCountedSet
DISALLOW_NEW();
static void CheckType() {
+ static_assert(internal::IsMemberOrWeakMemberType<Value>,
+ "HeapHashCountedSet supports only Member and WeakMember.");
static_assert(std::is_trivially_destructible<HeapHashCountedSet>::value,
"HeapHashCountedSet must be trivially destructible.");
static_assert(
@@ -597,6 +621,10 @@ class HeapHashCountedSet
HeapHashCountedSet() { CheckType(); }
};
+template <typename T, typename U, typename V>
+struct GCInfoTrait<HeapHashCountedSet<T, U, V>>
+ : public GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator>> {};
+
template <typename T, wtf_size_t inlineCapacity = 0>
class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
@@ -612,6 +640,8 @@ class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
static_assert(WTF::IsTraceable<T>::value,
"For vectors without traceable elements, use Vector<> "
"instead of HeapVector<>.");
+ static_assert(!WTF::IsWeak<T>::value,
+ "Weak types are not allowed in HeapVector.");
}
public:
@@ -649,15 +679,19 @@ class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
}
};
-template <typename T, wtf_size_t inlineCapacity = 0>
-class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
+template <typename T, wtf_size_t inlineCapacity>
+struct GCInfoTrait<HeapVector<T, inlineCapacity>>
+ : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> {};
+
+template <typename T>
+class HeapDeque : public Deque<T, 0, HeapAllocator> {
IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
- static_assert(
- std::is_trivially_destructible<HeapDeque>::value || inlineCapacity,
- "HeapDeque must be trivially destructible.");
+ static_assert(internal::IsMember<T>, "HeapDeque supports only Member.");
+ static_assert(std::is_trivially_destructible<HeapDeque>::value,
+ "HeapDeque must be trivially destructible.");
static_assert(
IsAllowedInContainer<T>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
@@ -669,37 +703,33 @@ class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
public:
template <typename>
static void* AllocateObject(size_t size) {
- // On-heap HeapDeques generally should not have inline capacity, but it is
- // hard to avoid when using a type alias. Hence we only disallow the
- // VectorTraits<T>::kNeedsDestruction case for now.
- static_assert(inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
- "on-heap HeapDeque<> should not have an inline capacity");
- return ThreadHeap::Allocate<HeapDeque<T, inlineCapacity>>(size);
+ return ThreadHeap::Allocate<HeapDeque<T>>(size);
}
HeapDeque() { CheckType(); }
- explicit HeapDeque(wtf_size_t size)
- : Deque<T, inlineCapacity, HeapAllocator>(size) {
+ explicit HeapDeque(wtf_size_t size) : Deque<T, 0, HeapAllocator>(size) {
CheckType();
}
HeapDeque(wtf_size_t size, const T& val)
- : Deque<T, inlineCapacity, HeapAllocator>(size, val) {
+ : Deque<T, 0, HeapAllocator>(size, val) {
CheckType();
}
HeapDeque& operator=(const HeapDeque& other) {
HeapDeque<T> copy(other);
- Deque<T, inlineCapacity, HeapAllocator>::Swap(copy);
+ Deque<T, 0, HeapAllocator>::Swap(copy);
return *this;
}
- template <wtf_size_t otherCapacity>
- HeapDeque(const HeapDeque<T, otherCapacity>& other)
- : Deque<T, inlineCapacity, HeapAllocator>(other) {}
+ HeapDeque(const HeapDeque<T>& other) : Deque<T, 0, HeapAllocator>(other) {}
};
+template <typename T>
+struct GCInfoTrait<HeapDeque<T>>
+ : public GCInfoTrait<Deque<T, 0, HeapAllocator>> {};
+
} // namespace blink
namespace WTF {
@@ -745,8 +775,8 @@ struct VectorTraits<blink::HeapVector<T, 0>>
};
template <typename T>
-struct VectorTraits<blink::HeapDeque<T, 0>>
- : VectorTraitsBase<blink::HeapDeque<T, 0>> {
+struct VectorTraits<blink::HeapDeque<T>>
+ : VectorTraitsBase<blink::HeapDeque<T>> {
STATIC_ONLY(VectorTraits);
static const bool kNeedsDestruction = false;
static const bool kCanInitializeWithMemset = true;
@@ -766,18 +796,6 @@ struct VectorTraits<blink::HeapVector<T, inlineCapacity>>
static const bool kCanMoveWithMemcpy = VectorTraits<T>::kCanMoveWithMemcpy;
};
-template <typename T, wtf_size_t inlineCapacity>
-struct VectorTraits<blink::HeapDeque<T, inlineCapacity>>
- : VectorTraitsBase<blink::HeapDeque<T, inlineCapacity>> {
- STATIC_ONLY(VectorTraits);
- static const bool kNeedsDestruction = VectorTraits<T>::kNeedsDestruction;
- static const bool kCanInitializeWithMemset =
- VectorTraits<T>::kCanInitializeWithMemset;
- static const bool kCanClearUnusedSlotsWithMemset =
- VectorTraits<T>::kCanClearUnusedSlotsWithMemset;
- static const bool kCanMoveWithMemcpy = VectorTraits<T>::kCanMoveWithMemcpy;
-};
-
template <typename T>
struct HashTraits<blink::Member<T>> : SimpleClassHashTraits<blink::Member<T>> {
STATIC_ONLY(HashTraits);
@@ -808,9 +826,6 @@ struct HashTraits<blink::Member<T>> : SimpleClassHashTraits<blink::Member<T>> {
static void ConstructDeletedValue(blink::Member<T>& slot, bool) {
slot = WTF::kHashTableDeletedValue;
}
- static bool IsDeletedValue(const blink::Member<T>& value) {
- return value.IsHashTableDeletedValue();
- }
};
template <typename T>
@@ -841,6 +856,10 @@ struct HashTraits<blink::WeakMember<T>>
}
static PeekOutType Peek(const blink::WeakMember<T>& value) { return value; }
+
+ static void ConstructDeletedValue(blink::WeakMember<T>& slot, bool) {
+ slot = WTF::kHashTableDeletedValue;
+ }
};
template <typename T>
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
index 1d9a577d2e3..24194d0db0b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -38,7 +38,7 @@ class HeapCompact::MovableObjectFixups final {
void AddCompactingPage(BasePage* page);
// Adds a slot for compaction. Filters slots in dead objects.
- void AddOrFilter(MovableReference* slot);
+ void AddOrFilter(const MovableReference*);
// Relocates a backing store |from| -> |to|.
void Relocate(Address from, Address to);
@@ -89,7 +89,7 @@ class HeapCompact::MovableObjectFixups final {
#if DCHECK_IS_ON()
// The following two collections are used to allow refer back from a slot to
// an already moved object.
- HashSet<void*> moved_objects_;
+ HashSet<const void*> moved_objects_;
HashMap<MovableReference*, MovableReference> interior_slot_to_object_;
#endif // DCHECK_IS_ON()
};
@@ -99,8 +99,9 @@ void HeapCompact::MovableObjectFixups::AddCompactingPage(BasePage* page) {
relocatable_pages_.insert(page);
}
-void HeapCompact::MovableObjectFixups::AddOrFilter(MovableReference* slot) {
- MovableReference value = *slot;
+void HeapCompact::MovableObjectFixups::AddOrFilter(
+ const MovableReference* const_slot) {
+ const void* value = *const_slot;
CHECK(value);
// All slots and values are part of Oilpan's heap.
@@ -111,13 +112,13 @@ void HeapCompact::MovableObjectFixups::AddOrFilter(MovableReference* slot) {
// Slots handling.
BasePage* const slot_page =
- heap_->LookupPageForAddress(reinterpret_cast<Address>(slot));
+ heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(const_slot));
CHECK(slot_page);
HeapObjectHeader* const header =
slot_page->IsLargeObjectPage()
? static_cast<LargeObjectPage*>(slot_page)->ObjectHeader()
: static_cast<NormalPage*>(slot_page)->FindHeaderFromAddress(
- reinterpret_cast<Address>(slot));
+ reinterpret_cast<ConstAddress>(const_slot));
CHECK(header);
// Filter the slot since the object that contains the slot is dead.
if (!header->IsMarked())
@@ -125,7 +126,7 @@ void HeapCompact::MovableObjectFixups::AddOrFilter(MovableReference* slot) {
// Value handling.
BasePage* const value_page =
- heap_->LookupPageForAddress(reinterpret_cast<Address>(value));
+ heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(value));
CHECK(value_page);
// The following cases are not compacted and do not require recording:
@@ -142,7 +143,7 @@ void HeapCompact::MovableObjectFixups::AddOrFilter(MovableReference* slot) {
// dynamic header lookup is required.
HeapObjectHeader* const value_header =
static_cast<NormalPage*>(value_page)
- ->FindHeaderFromAddress(reinterpret_cast<Address>(value));
+ ->FindHeaderFromAddress(reinterpret_cast<ConstAddress>(value));
CHECK(value_header);
CHECK(value_header->IsMarked());
@@ -151,11 +152,12 @@ void HeapCompact::MovableObjectFixups::AddOrFilter(MovableReference* slot) {
// times.
auto fixup_it = fixups_.find(value);
if (UNLIKELY(fixup_it != fixups_.end())) {
- CHECK_EQ(slot, fixup_it->value);
+ CHECK_EQ(const_slot, fixup_it->value);
return;
}
// Add regular fixup.
+ MovableReference* slot = const_cast<MovableReference*>(const_slot);
fixups_.insert(value, slot);
// Check whether the slot itself resides on a page that is compacted.
@@ -301,7 +303,7 @@ void HeapCompact::MovableObjectFixups::VerifyUpdatedSlot(
if (!*slot)
return;
BasePage* slot_page =
- heap_->LookupPageForAddress(reinterpret_cast<Address>(*slot));
+ heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(*slot));
// ref_page is null if *slot is pointing to an off-heap region. This may
// happy if *slot is pointing to an inline buffer of HeapVector with
// inline capacity.
@@ -373,9 +375,7 @@ void HeapCompact::Initialize(ThreadState* state) {
force_for_next_gc_ = false;
}
-bool HeapCompact::ShouldRegisterMovingAddress(Address address) {
- CHECK(heap_->LookupPageForAddress(reinterpret_cast<Address>(address)));
-
+bool HeapCompact::ShouldRegisterMovingAddress() {
return do_compact_;
}
@@ -442,8 +442,9 @@ void HeapCompact::FilterNonLiveSlots() {
last_fixup_count_for_testing_ = 0;
MovableReferenceWorklist::View traced_slots(
heap_->GetMovableReferenceWorklist(), WorklistTaskId::MutatorThread);
- MovableReference* slot;
+ const MovableReference* slot;
while (traced_slots.Pop(&slot)) {
+ CHECK(heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(slot)));
if (*slot) {
Fixups().AddOrFilter(slot);
last_fixup_count_for_testing_++;
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact.h b/chromium/third_party/blink/renderer/platform/heap/heap_compact.h
index be7b142e17b..93624129098 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact.h
@@ -64,7 +64,7 @@ class PLATFORM_EXPORT HeapCompact final {
}
// See |Heap::ShouldRegisterMovingAddress()| documentation.
- bool ShouldRegisterMovingAddress(Address address);
+ bool ShouldRegisterMovingAddress();
// Slots that are not contained within live objects are filtered. This can
// happen when the write barrier for in-payload objects triggers but the outer
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc
index e2eef4b7e05..f87e00b143f 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc
@@ -224,26 +224,6 @@ TEST_F(HeapCompactTest, CompactDeques) {
EXPECT_EQ(static_cast<int>(7 - i), deque->at(i)->Value());
}
-TEST_F(HeapCompactTest, CompactDequeVectors) {
- Persistent<HeapDeque<IntVector>> deque =
- MakeGarbageCollected<HeapDeque<IntVector>>();
- for (int i = 0; i < 8; ++i) {
- IntWrapper* value = IntWrapper::Create(i, VectorsAreCompacted);
- IntVector vector = IntVector(8, value);
- deque->push_front(vector);
- }
- EXPECT_EQ(8u, deque->size());
-
- for (wtf_size_t i = 0; i < deque->size(); ++i)
- EXPECT_EQ(static_cast<int>(7 - i), deque->at(i).at(i)->Value());
-
- PerformHeapCompaction();
- EXPECT_TRUE(IntWrapper::did_verify_at_least_once);
-
- for (wtf_size_t i = 0; i < deque->size(); ++i)
- EXPECT_EQ(static_cast<int>(7 - i), deque->at(i).at(i)->Value());
-}
-
TEST_F(HeapCompactTest, CompactLinkedHashSet) {
using OrderedHashSet = HeapLinkedHashSet<Member<IntWrapper>>;
Persistent<OrderedHashSet> set = MakeGarbageCollected<OrderedHashSet>();
@@ -357,6 +337,135 @@ TEST_F(HeapCompactTest, CompactLinkedHashSetNested) {
}
}
+TEST_F(HeapCompactTest, CompactNewLinkedHashSet) {
+ using OrderedHashSet = HeapNewLinkedHashSet<Member<IntWrapper>>;
+ Persistent<OrderedHashSet> set = MakeGarbageCollected<OrderedHashSet>();
+ for (int i = 0; i < 13; ++i) {
+ IntWrapper* value = IntWrapper::Create(i, HashTablesAreCompacted);
+ set->insert(value);
+ }
+ EXPECT_EQ(13u, set->size());
+
+ int expected = 0;
+ for (IntWrapper* v : *set) {
+ EXPECT_EQ(expected, v->Value());
+ expected++;
+ }
+
+ for (int i = 1; i < 13; i += 2) {
+ auto it = set->begin();
+ for (int j = 0; j < (i + 1) / 2; ++j) {
+ ++it;
+ }
+ set->erase(it);
+ }
+ EXPECT_EQ(7u, set->size());
+
+ expected = 0;
+ for (IntWrapper* v : *set) {
+ EXPECT_EQ(expected, v->Value());
+ expected += 2;
+ }
+
+ PerformHeapCompaction();
+ EXPECT_TRUE(IntWrapper::did_verify_at_least_once);
+
+ expected = 0;
+ for (IntWrapper* v : *set) {
+ EXPECT_EQ(expected, v->Value());
+ expected += 2;
+ }
+ EXPECT_EQ(7u, set->size());
+}
+
+TEST_F(HeapCompactTest, CompactNewLinkedHashSetVector) {
+ using OrderedHashSet = HeapNewLinkedHashSet<Member<IntVector>>;
+ Persistent<OrderedHashSet> set = MakeGarbageCollected<OrderedHashSet>();
+ for (int i = 0; i < 13; ++i) {
+ IntWrapper* value = IntWrapper::Create(i);
+ IntVector* vector = MakeGarbageCollected<IntVector>(19, value);
+ set->insert(vector);
+ }
+ EXPECT_EQ(13u, set->size());
+
+ int expected = 0;
+ for (IntVector* v : *set) {
+ EXPECT_EQ(expected, (*v)[0]->Value());
+ expected++;
+ }
+
+ PerformHeapCompaction();
+ EXPECT_TRUE(IntWrapper::did_verify_at_least_once);
+
+ expected = 0;
+ for (IntVector* v : *set) {
+ EXPECT_EQ(expected, (*v)[0]->Value());
+ expected++;
+ }
+}
+
+TEST_F(HeapCompactTest, CompactNewLinkedHashSetMap) {
+ using Inner = HeapHashSet<Member<IntWrapper>>;
+ using OrderedHashSet = HeapNewLinkedHashSet<Member<Inner>>;
+
+ Persistent<OrderedHashSet> set = MakeGarbageCollected<OrderedHashSet>();
+ for (int i = 0; i < 13; ++i) {
+ IntWrapper* value = IntWrapper::Create(i);
+ Inner* inner = MakeGarbageCollected<Inner>();
+ inner->insert(value);
+ set->insert(inner);
+ }
+ EXPECT_EQ(13u, set->size());
+
+ int expected = 0;
+ for (const Inner* v : *set) {
+ EXPECT_EQ(1u, v->size());
+ EXPECT_EQ(expected, (*v->begin())->Value());
+ expected++;
+ }
+
+ PerformHeapCompaction();
+ EXPECT_TRUE(IntWrapper::did_verify_at_least_once);
+
+ expected = 0;
+ for (const Inner* v : *set) {
+ EXPECT_EQ(1u, v->size());
+ EXPECT_EQ(expected, (*v->begin())->Value());
+ expected++;
+ }
+}
+
+TEST_F(HeapCompactTest, CompactNewLinkedHashSetNested) {
+ using Inner = HeapNewLinkedHashSet<Member<IntWrapper>>;
+ using OrderedHashSet = HeapNewLinkedHashSet<Member<Inner>>;
+
+ Persistent<OrderedHashSet> set = MakeGarbageCollected<OrderedHashSet>();
+ for (int i = 0; i < 13; ++i) {
+ IntWrapper* value = IntWrapper::Create(i);
+ Inner* inner = MakeGarbageCollected<Inner>();
+ inner->insert(value);
+ set->insert(inner);
+ }
+ EXPECT_EQ(13u, set->size());
+
+ int expected = 0;
+ for (const Inner* v : *set) {
+ EXPECT_EQ(1u, v->size());
+ EXPECT_EQ(expected, (*v->begin())->Value());
+ expected++;
+ }
+
+ PerformHeapCompaction();
+ EXPECT_TRUE(IntWrapper::did_verify_at_least_once);
+
+ expected = 0;
+ for (const Inner* v : *set) {
+ EXPECT_EQ(1u, v->size());
+ EXPECT_EQ(expected, (*v->begin())->Value());
+ expected++;
+ }
+}
+
TEST_F(HeapCompactTest, CompactInlinedBackingStore) {
// Regression test: https://crbug.com/875044
//
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_page.cc b/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
index 953d4214834..ae8472c80d1 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -89,21 +89,19 @@ namespace blink {
void HeapObjectHeader::Finalize(Address object, size_t object_size) {
HeapAllocHooks::FreeHookIfEnabled(object);
- const GCInfo* gc_info = GCInfoTable::Get().GCInfoFromIndex(GcInfoIndex());
- if (gc_info->finalize)
- gc_info->finalize(object);
+ const GCInfo& gc_info = GCInfo::From(GcInfoIndex());
+ if (gc_info.finalize)
+ gc_info.finalize(object);
ASAN_RETIRE_CONTAINER_ANNOTATION(object, object_size);
}
bool HeapObjectHeader::HasNonTrivialFinalizer() const {
- const GCInfo* gc_info = GCInfoTable::Get().GCInfoFromIndex(GcInfoIndex());
- return gc_info->finalize;
+ return GCInfo::From(GcInfoIndex()).finalize;
}
const char* HeapObjectHeader::Name() const {
- const GCInfo* gc_info = GCInfoTable::Get().GCInfoFromIndex(GcInfoIndex());
- return gc_info->name(Payload()).value;
+ return GCInfo::From(GcInfoIndex()).name(Payload()).value;
}
BaseArena::BaseArena(ThreadState* state, int index)
@@ -132,7 +130,7 @@ void BaseArena::CollectStatistics(std::string name,
ResetAllocationPoint();
if (!NameClient::HideInternalName()) {
- size_t num_types = GCInfoTable::Get().GcInfoIndex() + 1;
+ const size_t num_types = GCInfoTable::Get().NumberOfGCInfos();
arena_stats.object_stats.num_types = num_types;
arena_stats.object_stats.type_name.resize(num_types);
arena_stats.object_stats.type_count.resize(num_types);
@@ -156,7 +154,7 @@ void NormalPageArena::CollectFreeListStatistics(
}
#if DCHECK_IS_ON()
-BasePage* BaseArena::FindPageFromAddress(Address address) {
+BasePage* BaseArena::FindPageFromAddress(ConstAddress address) const {
for (BasePage* page : swept_pages_) {
if (page->Contains(address))
return page;
@@ -215,6 +213,15 @@ void BaseArena::MakeConsistentForMutator() {
VerifyObjectStartBitmap();
}
+void BaseArena::Unmark() {
+ DCHECK(GetThreadState()->InAtomicMarkingPause());
+ DCHECK(SweepingAndFinalizationCompleted());
+
+ for (BasePage* page : swept_pages_) {
+ page->Unmark();
+ }
+}
+
size_t BaseArena::ObjectPayloadSizeForTesting() {
#if DCHECK_IS_ON()
DCHECK(IsConsistentForGC());
@@ -228,7 +235,7 @@ size_t BaseArena::ObjectPayloadSizeForTesting() {
return object_payload_size;
}
-void BaseArena::PrepareForSweep() {
+void BaseArena::PrepareForSweep(BlinkGC::CollectionType collection_type) {
DCHECK(GetThreadState()->InAtomicMarkingPause());
DCHECK(SweepingAndFinalizationCompleted());
@@ -237,10 +244,23 @@ void BaseArena::PrepareForSweep() {
// Verification depends on the allocation point being cleared.
VerifyObjectStartBitmap();
+ if (collection_type == BlinkGC::CollectionType::kMinor) {
+ auto** first_young =
+ std::partition(swept_pages_.begin(), swept_pages_.end(),
+ [](BasePage* page) { return !page->IsYoung(); });
+ for (auto** it = first_young; it != swept_pages_.end(); ++it) {
+ BasePage* page = *it;
+ page->MarkAsUnswept();
+ page->SetAsYoung(false);
+ unswept_pages_.Push(page);
+ }
+ swept_pages_.erase(first_young, swept_pages_.end());
+ return;
+ }
+
for (BasePage* page : swept_pages_) {
page->MarkAsUnswept();
}
-
// Move all pages to a list of unswept pages.
unswept_pages_.MoveFrom(std::move(swept_pages_));
DCHECK(swept_pages_.IsEmpty());
@@ -268,7 +288,7 @@ Address BaseArena::LazySweep(size_t allocation_size, size_t gc_info_index) {
if (GetThreadState()->SweepForbidden())
return nullptr;
- ThreadHeapStatsCollector::Scope stats_scope(
+ ThreadHeapStatsCollector::EnabledScope stats_scope(
GetThreadState()->Heap().stats_collector(),
ThreadHeapStatsCollector::kLazySweepOnAllocation);
ThreadState::SweepForbiddenScope sweep_forbidden(GetThreadState());
@@ -311,11 +331,9 @@ bool BaseArena::LazySweepWithDeadline(base::TimeTicks deadline) {
DCHECK(ScriptForbiddenScope::IsScriptForbidden());
size_t page_count = 1;
- // TODO(bikineev): We should probably process pages in the reverse order. This
- // will leave more work for concurrent sweeper and reduce memory footprint
- // faster.
- while (BasePage* page = unswept_pages_.PopLocked()) {
- SweepUnsweptPage(page);
+ // First, process empty pages to faster reduce memory footprint.
+ while (BasePage* page = swept_unfinalized_empty_pages_.PopLocked()) {
+ page->FinalizeSweep(SweepResult::kPageEmpty);
if (page_count % kDeadlineCheckInterval == 0) {
if (deadline <= base::TimeTicks::Now()) {
// Deadline has come.
@@ -324,6 +342,7 @@ bool BaseArena::LazySweepWithDeadline(base::TimeTicks deadline) {
}
page_count++;
}
+ // Second, execute finalizers to leave more work for concurrent sweeper.
while (BasePage* page = swept_unfinalized_pages_.PopLocked()) {
swept_pages_.PushLocked(page);
page->FinalizeSweep(SweepResult::kPageNotEmpty);
@@ -335,8 +354,9 @@ bool BaseArena::LazySweepWithDeadline(base::TimeTicks deadline) {
}
page_count++;
}
- while (BasePage* page = swept_unfinalized_empty_pages_.PopLocked()) {
- page->FinalizeSweep(SweepResult::kPageEmpty);
+ // Help concurrent sweeper.
+ while (BasePage* page = unswept_pages_.PopLocked()) {
+ SweepUnsweptPage(page);
if (page_count % kDeadlineCheckInterval == 0) {
if (deadline <= base::TimeTicks::Now()) {
// Deadline has come.
@@ -362,18 +382,12 @@ void BaseArena::InvokeFinalizersOnSweptPages() {
}
}
-bool BaseArena::ConcurrentSweepWithDeadline(base::TimeTicks deadline) {
- static constexpr size_t kDeadlineCheckInterval = 10;
- size_t page_count = 1;
- while (BasePage* page = unswept_pages_.PopLocked()) {
- SweepUnsweptPageOnConcurrentThread(page);
- if (page_count % kDeadlineCheckInterval == 0 &&
- deadline <= base::TimeTicks::Now()) {
- return SweepingCompleted();
- }
- ++page_count;
- }
- return true;
+bool BaseArena::ConcurrentSweepOnePage() {
+ BasePage* page = unswept_pages_.PopLocked();
+ if (!page)
+ return true;
+ SweepUnsweptPageOnConcurrentThread(page);
+ return false;
}
void BaseArena::CompleteSweep() {
@@ -384,14 +398,14 @@ void BaseArena::CompleteSweep() {
// Some phases, e.g. verification, require iterability of a page.
MakeIterable();
- // First, sweep and finalize pages.
+ // First, finalize pages that have been processed by concurrent sweepers.
+ InvokeFinalizersOnSweptPages();
+
+ // Then, sweep and finalize pages.
while (BasePage* page = unswept_pages_.PopLocked()) {
SweepUnsweptPage(page);
}
- // Then, finalize pages that have been processed by concurrent sweepers.
- InvokeFinalizersOnSweptPages();
-
// Verify object start bitmap after all freelists have been merged.
VerifyObjectStartBitmap();
}
@@ -410,9 +424,17 @@ NormalPageArena::NormalPageArena(ThreadState* state, int index)
: BaseArena(state, index),
current_allocation_point_(nullptr),
remaining_allocation_size_(0),
- last_remaining_allocation_size_(0),
- promptly_freed_size_(0) {
- ClearFreeLists();
+ promptly_freed_size_(0) {}
+
+void NormalPageArena::AddToFreeList(Address address, size_t size) {
+#if DCHECK_IS_ON()
+ DCHECK(FindPageFromAddress(address));
+ DCHECK(FindPageFromAddress(address + size - 1));
+#endif
+ free_list_.Add(address, size);
+ static_cast<NormalPage*>(PageFromObject(address))
+ ->object_start_bit_map()
+ ->SetBit(address);
}
void NormalPageArena::MakeConsistentForGC() {
@@ -621,7 +643,7 @@ bool NormalPageArena::IsConsistentForGC() {
return true;
}
-bool NormalPageArena::PagesToBeSweptContains(Address address) {
+bool NormalPageArena::PagesToBeSweptContains(ConstAddress address) const {
for (BasePage* page : unswept_pages_) {
if (page->Contains(address))
return true;
@@ -716,7 +738,7 @@ void NormalPageArena::PromptlyFreeObject(HeapObjectHeader* header) {
if (IsObjectAllocatedAtAllocationPoint(header)) {
current_allocation_point_ -= size;
DCHECK_EQ(address, current_allocation_point_);
- SetRemainingAllocationSize(remaining_allocation_size_ + size);
+ remaining_allocation_size_ += size;
SET_MEMORY_INACCESSIBLE(address, size);
// Memory that is part of the allocation point is not allowed to be part
// of the object start bit map.
@@ -763,7 +785,7 @@ bool NormalPageArena::ExpandObject(HeapObjectHeader* header, size_t new_size) {
expand_size <= remaining_allocation_size_) {
current_allocation_point_ += expand_size;
DCHECK_GE(remaining_allocation_size_, expand_size);
- SetRemainingAllocationSize(remaining_allocation_size_ - expand_size);
+ remaining_allocation_size_ -= expand_size;
// Unpoison the memory used for the object (payload).
SET_MEMORY_ACCESSIBLE(header->PayloadEnd(), expand_size);
header->SetSize(allocation_size);
@@ -782,7 +804,7 @@ bool NormalPageArena::ShrinkObject(HeapObjectHeader* header, size_t new_size) {
size_t shrink_size = header->size() - allocation_size;
if (IsObjectAllocatedAtAllocationPoint(header)) {
current_allocation_point_ -= shrink_size;
- SetRemainingAllocationSize(remaining_allocation_size_ + shrink_size);
+ remaining_allocation_size_ += shrink_size;
SET_MEMORY_INACCESSIBLE(current_allocation_point_, shrink_size);
header->SetSize(allocation_size);
return true;
@@ -790,9 +812,9 @@ bool NormalPageArena::ShrinkObject(HeapObjectHeader* header, size_t new_size) {
DCHECK_GE(shrink_size, sizeof(HeapObjectHeader));
DCHECK_GT(header->GcInfoIndex(), 0u);
Address shrink_address = header->PayloadEnd() - shrink_size;
- HeapObjectHeader* freed_header =
- new (NotNull, shrink_address) HeapObjectHeader(
- shrink_size, header->GcInfoIndex(), HeapObjectHeader::kNormalPage);
+ HeapObjectHeader* freed_header = new (NotNull, shrink_address)
+ HeapObjectHeader(shrink_size, header->GcInfoIndex());
+ // Since only size has been changed, we don't need to update object starts.
PromptlyFreeObjectInFreeList(freed_header, shrink_size);
#if DCHECK_IS_ON()
DCHECK_EQ(PageFromObject(reinterpret_cast<Address>(header)),
@@ -843,24 +865,6 @@ Address NormalPageArena::LazySweepPages(size_t allocation_size,
return result;
}
-void NormalPageArena::SetRemainingAllocationSize(
- size_t new_remaining_allocation_size) {
- remaining_allocation_size_ = new_remaining_allocation_size;
-
- // Sync recorded allocated-object size using the recorded checkpoint in
- // |remaining_allocation_size_|:
- // - If checkpoint is larger, the allocated size has increased.
- // - The allocated size has decreased, otherwise.
- if (last_remaining_allocation_size_ > remaining_allocation_size_) {
- GetThreadState()->Heap().stats_collector()->IncreaseAllocatedObjectSize(
- last_remaining_allocation_size_ - remaining_allocation_size_);
- } else if (last_remaining_allocation_size_ != remaining_allocation_size_) {
- GetThreadState()->Heap().stats_collector()->DecreaseAllocatedObjectSize(
- remaining_allocation_size_ - last_remaining_allocation_size_);
- }
- last_remaining_allocation_size_ = remaining_allocation_size_;
-}
-
void NormalPageArena::SetAllocationPoint(Address point, size_t size) {
#if DCHECK_IS_ON()
if (point) {
@@ -878,7 +882,11 @@ void NormalPageArena::SetAllocationPoint(Address point, size_t size) {
}
// Set up a new linear allocation area.
current_allocation_point_ = point;
- last_remaining_allocation_size_ = remaining_allocation_size_ = size;
+ remaining_allocation_size_ = size;
+ // Update last allocated region in ThreadHeap. This must also be done if the
+ // allocation point is set to 0 (before doing GC), so that the last allocated
+ // region is automatically reset after GC.
+ GetThreadState()->Heap().SetLastAllocatedRegion(point, size);
if (point) {
// Only, update allocated size and object start bitmap if the area is
// actually set up with a non-null address.
@@ -889,6 +897,8 @@ void NormalPageArena::SetAllocationPoint(Address point, size_t size) {
// clearing the allocation point.
NormalPage* page = reinterpret_cast<NormalPage*>(PageFromObject(point));
page->object_start_bit_map()->ClearBit(point);
+ // Mark page as containing young objects.
+ page->SetAsYoung(true);
}
}
@@ -985,8 +995,8 @@ Address LargeObjectArena::DoAllocateLargeObjectPage(size_t allocation_size,
DCHECK_GT(gc_info_index, 0u);
LargeObjectPage* large_object = new (large_object_address)
LargeObjectPage(page_memory, this, allocation_size);
- HeapObjectHeader* header = new (NotNull, header_address) HeapObjectHeader(
- kLargeObjectSizeInHeader, gc_info_index, HeapObjectHeader::kLargePage);
+ HeapObjectHeader* header = new (NotNull, header_address)
+ HeapObjectHeader(kLargeObjectSizeInHeader, gc_info_index);
Address result = header_address + sizeof(*header);
DCHECK(!(reinterpret_cast<uintptr_t>(result) & kAllocationMask));
@@ -997,6 +1007,10 @@ Address LargeObjectArena::DoAllocateLargeObjectPage(size_t allocation_size,
swept_pages_.PushLocked(large_object);
+ // Update last allocated region in ThreadHeap.
+ GetThreadState()->Heap().SetLastAllocatedRegion(large_object->Payload(),
+ large_object->PayloadSize());
+
// Add all segments of kBlinkPageSize to the bloom filter so that the large
// object can be kept by derived pointers on stack. An alternative might be to
// prohibit derived pointers to large objects, but that is dangerous since the
@@ -1009,6 +1023,8 @@ Address LargeObjectArena::DoAllocateLargeObjectPage(size_t allocation_size,
large_object->size());
GetThreadState()->Heap().stats_collector()->IncreaseAllocatedObjectSize(
large_object->PayloadSize());
+ // Add page to the list of young pages.
+ large_object->SetAsYoung(true);
return result;
}
@@ -1053,7 +1069,9 @@ Address LargeObjectArena::LazySweepPages(size_t allocation_size,
return result;
}
-FreeList::FreeList() : biggest_free_list_index_(0) {}
+FreeList::FreeList() : biggest_free_list_index_(0) {
+ Clear();
+}
void FreeList::Add(Address address, size_t size) {
DCHECK_LT(size, BlinkPagePayloadSize());
@@ -1062,15 +1080,15 @@ void FreeList::Add(Address address, size_t size) {
DCHECK(!((reinterpret_cast<uintptr_t>(address) + sizeof(HeapObjectHeader)) &
kAllocationMask));
DCHECK(!(size & kAllocationMask));
+ DCHECK(!PageFromObject(address)->IsLargeObjectPage());
ASAN_UNPOISON_MEMORY_REGION(address, size);
FreeListEntry* entry;
if (size < sizeof(*entry)) {
// Create a dummy header with only a size and freelist bit set.
DCHECK_GE(size, sizeof(HeapObjectHeader));
// Free list encode the size to mark the lost memory as freelist memory.
- new (NotNull, address) HeapObjectHeader(size, kGcInfoIndexForFreeListHeader,
- HeapObjectHeader::kNormalPage);
-
+ new (NotNull, address)
+ HeapObjectHeader(size, kGcInfoIndexForFreeListHeader);
ASAN_POISON_MEMORY_REGION(address, size);
// This memory gets lost. Sweeping can reclaim it.
return;
@@ -1381,11 +1399,18 @@ void NormalPage::ToBeFinalizedObject::Finalize() {
}
void NormalPage::FinalizeSweep(SweepResult action) {
+ // Call finalizers.
for (ToBeFinalizedObject& object : to_be_finalized_objects_) {
object.Finalize();
}
to_be_finalized_objects_.clear();
-
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ // Copy object start bit map.
+ DCHECK(cached_object_start_bit_map_);
+ object_start_bit_map_ = *cached_object_start_bit_map_;
+ cached_object_start_bit_map_.reset();
+#endif
+ // Merge freelists or unmap the page.
if (action == SweepResult::kPageNotEmpty) {
MergeFreeLists();
MarkAsSwept();
@@ -1407,6 +1432,11 @@ void NormalPage::AddToFreeList(Address start,
unfinalized_freelist_.push_back(std::move(entry));
} else {
cached_freelist_.Add(start, size);
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ cached_object_start_bit_map_->SetBit(start);
+#else
+ object_start_bit_map_.SetBit(start);
+#endif
#if !DCHECK_IS_ON() && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
if (Arena()->GetThreadState()->IsMemoryReducingGC()) {
DiscardPages(start + sizeof(FreeListEntry), start + size);
@@ -1433,7 +1463,14 @@ void NormalPage::MergeFreeLists() {
}
bool NormalPage::Sweep(FinalizeType finalize_type) {
+ ObjectStartBitmap* bitmap;
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ cached_object_start_bit_map_ = std::make_unique<ObjectStartBitmap>(Payload());
+ bitmap = cached_object_start_bit_map_.get();
+#else
object_start_bit_map()->Clear();
+ bitmap = object_start_bit_map();
+#endif
cached_freelist_.Clear();
unfinalized_freelist_.clear();
Address start_of_gap = Payload();
@@ -1478,8 +1515,10 @@ bool NormalPage::Sweep(FinalizeType finalize_type) {
found_finalizer);
found_finalizer = false;
}
- object_start_bit_map()->SetBit(header_address);
+ bitmap->SetBit(header_address);
+#if !BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
header->Unmark<HeapObjectHeader::AccessMode::kAtomic>();
+#endif
header_address += size;
start_of_gap = header_address;
}
@@ -1543,7 +1582,9 @@ void NormalPage::SweepAndCompact(CompactionContext& context) {
header_address += size;
continue;
}
+#if !BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
header->Unmark();
+#endif
// Allocate and copy over the live object.
Address compact_frontier = current_page->Payload() + allocation_point;
if (compact_frontier + size > current_page->PayloadEnd()) {
@@ -1570,8 +1611,9 @@ void NormalPage::SweepAndCompact(CompactionContext& context) {
// store object, let go of the container annotations.
// Do that by unpoisoning the payload entirely.
ASAN_UNPOISON_MEMORY_REGION(header, sizeof(HeapObjectHeader));
- if (is_vector_arena)
+ if (is_vector_arena) {
ASAN_UNPOISON_MEMORY_REGION(payload, payload_size);
+ }
#endif
// Use a non-overlapping copy, if possible.
if (current_page == this)
@@ -1635,6 +1677,30 @@ void NormalPage::MakeConsistentForMutator() {
VerifyObjectStartBitmapIsConsistentWithPayload();
}
+// This is assumed to be called from the atomic pause, so no concurrency should
+// be involved here.
+void NormalPage::Unmark() {
+ const Address current_allocation_point =
+ ArenaForNormalPage()->CurrentAllocationPoint();
+ const size_t allocation_area_size =
+ ArenaForNormalPage()->RemainingAllocationSize();
+ for (Address header_address = Payload(); header_address < PayloadEnd();) {
+ // Since unmarking can happen inside IncrementalMarkingStart, the current
+ // allocation point can be set and we need to skip over it.
+ if (header_address == current_allocation_point && allocation_area_size) {
+ header_address += allocation_area_size;
+ continue;
+ }
+ HeapObjectHeader* header =
+ reinterpret_cast<HeapObjectHeader*>(header_address);
+ if (header->IsMarked()) {
+ header->Unmark();
+ }
+ header_address += header->size();
+ }
+ ClearCardTable();
+}
+
#if defined(ADDRESS_SANITIZER)
void NormalPage::PoisonUnmarkedObjects() {
for (Address header_address = Payload(); header_address < PayloadEnd();) {
@@ -1647,8 +1713,9 @@ void NormalPage::PoisonUnmarkedObjects() {
header_address += header->size();
continue;
}
- if (!header->IsMarked())
+ if (!header->IsMarked()) {
ASAN_POISON_MEMORY_REGION(header->Payload(), header->PayloadSize());
+ }
header_address += header->size();
}
}
@@ -1693,7 +1760,7 @@ void LargeObjectPage::VerifyMarking() {
}
Address ObjectStartBitmap::FindHeader(
- Address address_maybe_pointing_to_the_middle_of_object) {
+ ConstAddress address_maybe_pointing_to_the_middle_of_object) const {
size_t object_offset =
address_maybe_pointing_to_the_middle_of_object - offset_;
size_t object_start_number = object_offset / kAllocationGranularity;
@@ -1716,7 +1783,7 @@ Address ObjectStartBitmap::FindHeader(
}
HeapObjectHeader* NormalPage::ConservativelyFindHeaderFromAddress(
- Address address) {
+ ConstAddress address) const {
if (!ContainedInObjectPayload(address))
return nullptr;
if (ArenaForNormalPage()->IsInCurrentAllocationPointRegion(address))
@@ -1759,7 +1826,7 @@ void NormalPage::CollectStatistics(
}
#if DCHECK_IS_ON()
-bool NormalPage::Contains(Address addr) {
+bool NormalPage::Contains(ConstAddress addr) const {
Address blink_page_start = RoundToBlinkPageStart(GetAddress());
// Page is at aligned address plus guard page size.
DCHECK_EQ(blink_page_start, GetAddress() - kBlinkGuardPageSize);
@@ -1791,15 +1858,22 @@ bool LargeObjectPage::Sweep(FinalizeType) {
if (!ObjectHeader()->IsMarked()) {
return true;
}
+#if !BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
ObjectHeader()->Unmark();
+#endif
return false;
}
-void LargeObjectPage::MakeConsistentForMutator() {
+void LargeObjectPage::Unmark() {
HeapObjectHeader* header = ObjectHeader();
if (header->IsMarked()) {
header->Unmark();
}
+ SetRemembered(false);
+}
+
+void LargeObjectPage::MakeConsistentForMutator() {
+ Unmark();
}
void LargeObjectPage::FinalizeSweep(SweepResult action) {
@@ -1814,8 +1888,9 @@ void LargeObjectPage::FinalizeSweep(SweepResult action) {
#if defined(ADDRESS_SANITIZER)
void LargeObjectPage::PoisonUnmarkedObjects() {
HeapObjectHeader* header = ObjectHeader();
- if (!header->IsMarked())
+ if (!header->IsMarked()) {
ASAN_POISON_MEMORY_REGION(header->Payload(), header->PayloadSize());
+ }
}
#endif
@@ -1840,7 +1915,7 @@ void LargeObjectPage::CollectStatistics(
}
#if DCHECK_IS_ON()
-bool LargeObjectPage::Contains(Address object) {
+bool LargeObjectPage::Contains(ConstAddress object) const {
return RoundToBlinkPageStart(GetAddress()) <= object &&
object < RoundToBlinkPageEnd(GetAddress() + size());
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_page.h b/chromium/third_party/blink/renderer/platform/heap/heap_page.h
index 4a937e53c1d..f9f0076112c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_page.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_page.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_PAGE_H_
#include <stdint.h>
+#include <array>
#include <atomic>
#include "base/bits.h"
@@ -39,8 +40,10 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
#include "third_party/blink/renderer/platform/heap/gc_info.h"
+#include "third_party/blink/renderer/platform/heap/heap_buildflags.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/heap/thread_state_statistics.h"
+#include "third_party/blink/renderer/platform/heap/unsanitized_atomic.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -179,28 +182,6 @@ static_assert(
namespace internal {
-// This is needed due to asan complaining deep from std::atomic<>::load/store
-// stacktraces.
-class AsanUnpoisonScope {
- public:
- AsanUnpoisonScope(const void* addr, size_t size)
- : addr_(addr), size_(size), was_poisoned_(false) {
- if (!ASAN_REGION_IS_POISONED(const_cast<void*>(addr_), size_))
- return;
- ASAN_UNPOISON_MEMORY_REGION(addr_, size_);
- was_poisoned_ = true;
- }
- ~AsanUnpoisonScope() {
- if (was_poisoned_)
- ASAN_POISON_MEMORY_REGION(addr_, size_);
- }
-
- private:
- const void* addr_;
- size_t size_;
- bool was_poisoned_;
-};
-
NO_SANITIZE_ADDRESS constexpr uint16_t EncodeSize(size_t size) {
// Essentially, gets optimized to >> 1.
return static_cast<uint16_t>((size << kHeaderSizeShift) /
@@ -219,7 +200,6 @@ class PLATFORM_EXPORT HeapObjectHeader {
DISALLOW_NEW();
public:
- enum HeaderLocation : uint8_t { kNormalPage, kLargePage };
enum class AccessMode : uint8_t { kNonAtomic, kAtomic };
static HeapObjectHeader* FromPayload(const void*);
@@ -230,7 +210,7 @@ class PLATFORM_EXPORT HeapObjectHeader {
static void CheckFromPayload(const void*);
// If |gc_info_index| is 0, this header is interpreted as a free list header.
- HeapObjectHeader(size_t, size_t, HeaderLocation);
+ HeapObjectHeader(size_t, size_t);
template <AccessMode mode = AccessMode::kNonAtomic>
NO_SANITIZE_ADDRESS bool IsFree() const {
@@ -239,7 +219,8 @@ class PLATFORM_EXPORT HeapObjectHeader {
template <AccessMode mode = AccessMode::kNonAtomic>
NO_SANITIZE_ADDRESS uint32_t GcInfoIndex() const {
- const uint16_t encoded = LoadEncoded<mode, EncodedHalf::kHigh>();
+ const uint16_t encoded =
+ LoadEncoded<mode, EncodedHalf::kHigh, std::memory_order_acquire>();
return (encoded & kHeaderGCInfoIndexMask) >> kHeaderGCInfoIndexShift;
}
@@ -247,18 +228,20 @@ class PLATFORM_EXPORT HeapObjectHeader {
size_t size() const;
void SetSize(size_t size);
+ template <AccessMode = AccessMode::kNonAtomic>
bool IsLargeObject() const;
template <AccessMode = AccessMode::kNonAtomic>
bool IsMarked() const;
template <AccessMode = AccessMode::kNonAtomic>
- void Mark();
- template <AccessMode = AccessMode::kNonAtomic>
void Unmark();
template <AccessMode = AccessMode::kNonAtomic>
bool TryMark();
template <AccessMode = AccessMode::kNonAtomic>
+ bool IsOld() const;
+
+ template <AccessMode = AccessMode::kNonAtomic>
bool IsInConstruction() const;
template <AccessMode = AccessMode::kNonAtomic>
void MarkFullyConstructed();
@@ -281,9 +264,13 @@ class PLATFORM_EXPORT HeapObjectHeader {
private:
enum class EncodedHalf : uint8_t { kLow, kHigh };
- template <AccessMode, EncodedHalf>
+ template <AccessMode,
+ EncodedHalf part,
+ std::memory_order = std::memory_order_seq_cst>
uint16_t LoadEncoded() const;
- template <AccessMode mode, EncodedHalf>
+ template <AccessMode mode,
+ EncodedHalf part,
+ std::memory_order = std::memory_order_seq_cst>
void StoreEncoded(uint16_t bits, uint16_t mask);
#if defined(ARCH_CPU_64_BITS)
@@ -297,11 +284,7 @@ class FreeListEntry final : public HeapObjectHeader {
public:
NO_SANITIZE_ADDRESS
explicit FreeListEntry(size_t size)
- : HeapObjectHeader(size,
- kGcInfoIndexForFreeListHeader,
- HeapObjectHeader::kNormalPage),
- next_(nullptr) {
- }
+ : HeapObjectHeader(size, kGcInfoIndexForFreeListHeader), next_(nullptr) {}
Address GetAddress() { return reinterpret_cast<Address>(this); }
@@ -386,7 +369,7 @@ class FreeList {
};
// Blink heap pages are set up with a guard page before and after the payload.
-inline size_t BlinkPagePayloadSize() {
+constexpr size_t BlinkPagePayloadSize() {
return kBlinkPageSize - 2 * kBlinkGuardPageSize;
}
@@ -410,8 +393,8 @@ inline Address BlinkPageAddress(Address address) {
kBlinkPageBaseMask);
}
-inline bool VTableInitialized(void* object_pointer) {
- return !!(*reinterpret_cast<Address*>(object_pointer));
+inline bool VTableInitialized(const void* object_pointer) {
+ return !!(*reinterpret_cast<const ConstAddress*>(object_pointer));
}
#if DCHECK_IS_ON()
@@ -465,6 +448,7 @@ class BasePage {
// Does not create free list entries for empty pages.
virtual bool Sweep(FinalizeType) = 0;
virtual void MakeConsistentForMutator() = 0;
+ virtual void Unmark() = 0;
// Calls finalizers after sweeping is done.
virtual void FinalizeSweep(SweepResult) = 0;
@@ -477,11 +461,13 @@ class BasePage {
ThreadState::Statistics::ArenaStatistics* arena_stats) = 0;
#if DCHECK_IS_ON()
- virtual bool Contains(Address) = 0;
+ virtual bool Contains(ConstAddress) const = 0;
#endif
- virtual size_t size() = 0;
+ virtual size_t size() const = 0;
- Address GetAddress() { return reinterpret_cast<Address>(this); }
+ Address GetAddress() const {
+ return reinterpret_cast<Address>(const_cast<BasePage*>(this));
+ }
PageMemory* Storage() const { return storage_; }
BaseArena* Arena() const { return arena_; }
ThreadState* thread_state() const { return thread_state_; }
@@ -505,6 +491,11 @@ class BasePage {
return page_type_ == PageType::kLargeObjectPage;
}
+ // Young pages are pages that contain at least a single young object.
+ bool IsYoung() const { return is_young_; }
+
+ void SetAsYoung(bool young) { is_young_ = young; }
+
virtual void VerifyMarking() = 0;
private:
@@ -515,6 +506,7 @@ class BasePage {
// Track the sweeping state of a page. Set to false at the start of a sweep,
// true upon completion of sweeping that page.
bool swept_ = true;
+ bool is_young_ = false;
PageType page_type_;
@@ -544,8 +536,11 @@ class PageStack : Vector<BasePage*> {
}
using Base::begin;
- using Base::clear;
using Base::end;
+
+ using Base::clear;
+ using Base::erase;
+
using Base::IsEmpty;
using Base::size;
};
@@ -581,7 +576,7 @@ class PageStackThreadSafe : public PageStack {
// - kBlinkPageSize
// - kAllocationGranularity
class PLATFORM_EXPORT ObjectStartBitmap {
- DISALLOW_NEW();
+ USING_FAST_MALLOC(ObjectStartBitmap);
public:
// Granularity of addresses added to the bitmap.
@@ -597,7 +592,8 @@ class PLATFORM_EXPORT ObjectStartBitmap {
// Finds an object header based on a
// address_maybe_pointing_to_the_middle_of_object. Will search for an object
// start in decreasing address order.
- Address FindHeader(Address address_maybe_pointing_to_the_middle_of_object);
+ Address FindHeader(
+ ConstAddress address_maybe_pointing_to_the_middle_of_object) const;
inline void SetBit(Address);
inline void ClearBit(Address);
@@ -625,7 +621,7 @@ class PLATFORM_EXPORT ObjectStartBitmap {
inline void ObjectStartIndexAndBit(Address, size_t*, size_t*) const;
- const Address offset_;
+ Address offset_;
// The bitmap contains a bit for every kGranularity aligned address on a
// a NormalPage, i.e., for a page of size kBlinkPageSize.
uint8_t object_start_bit_map_[kReservedForBitmap];
@@ -636,12 +632,12 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
NormalPage(PageMemory*, BaseArena*);
~NormalPage() override;
- Address Payload() { return GetAddress() + PageHeaderSize(); }
- size_t PayloadSize() {
+ Address Payload() const { return GetAddress() + PageHeaderSize(); }
+ static constexpr size_t PayloadSize() {
return (BlinkPagePayloadSize() - PageHeaderSize()) & ~kAllocationMask;
}
- Address PayloadEnd() { return Payload() + PayloadSize(); }
- bool ContainedInObjectPayload(Address address) {
+ Address PayloadEnd() const { return Payload() + PayloadSize(); }
+ bool ContainedInObjectPayload(ConstAddress address) const {
return Payload() <= address && address < PayloadEnd();
}
@@ -649,6 +645,7 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
void RemoveFromHeap() override;
bool Sweep(FinalizeType) override;
void MakeConsistentForMutator() override;
+ void Unmark() override;
void FinalizeSweep(SweepResult) override;
#if defined(ADDRESS_SANITIZER)
void PoisonUnmarkedObjects() override;
@@ -661,17 +658,17 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
// Returns true for the whole |kBlinkPageSize| page that the page is on, even
// for the header, and the unmapped guard page at the start. That ensures the
// result can be used to populate the negative page cache.
- bool Contains(Address) override;
+ bool Contains(ConstAddress) const override;
#endif
- size_t size() override { return kBlinkPageSize; }
- static size_t PageHeaderSize() {
+ size_t size() const override { return kBlinkPageSize; }
+ static constexpr size_t PageHeaderSize() {
// Compute the amount of padding we have to add to a header to make the size
// of the header plus the padding a multiple of 8 bytes.
- size_t padding_size =
+ constexpr size_t kPaddingSize =
(sizeof(NormalPage) + kAllocationGranularity -
(sizeof(HeapObjectHeader) % kAllocationGranularity)) %
kAllocationGranularity;
- return sizeof(NormalPage) + padding_size;
+ return sizeof(NormalPage) + kPaddingSize;
}
inline NormalPageArena* ArenaForNormalPage() const;
@@ -698,6 +695,9 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
// Object start bitmap of this page.
ObjectStartBitmap* object_start_bit_map() { return &object_start_bit_map_; }
+ const ObjectStartBitmap* object_start_bit_map() const {
+ return &object_start_bit_map_;
+ }
// Verifies that the object start bitmap only contains a bit iff the object
// is also reachable through iteration on the page.
@@ -706,18 +706,87 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
// Uses the object_start_bit_map_ to find an object for a given address. The
// returned header is either nullptr, indicating that no object could be
// found, or it is pointing to valid object or free list entry.
- HeapObjectHeader* ConservativelyFindHeaderFromAddress(Address);
+ HeapObjectHeader* ConservativelyFindHeaderFromAddress(ConstAddress) const;
// Uses the object_start_bit_map_ to find an object for a given address. It is
// assumed that the address points into a valid heap object. Use the
// conservative version if that assumption does not hold.
template <
HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic>
- HeapObjectHeader* FindHeaderFromAddress(Address);
+ HeapObjectHeader* FindHeaderFromAddress(ConstAddress) const;
void VerifyMarking() override;
+ // Marks a card corresponding to address.
+ void MarkCard(Address address);
+
+ // Iterates over all objects in marked cards.
+ template <typename Function>
+ void IterateCardTable(Function function) const;
+
+ // Clears all bits in the card table.
+ void ClearCardTable() { card_table_.Clear(); }
+
private:
+ // Data structure that divides a page in a number of cards each of 512 bytes
+ // size. Marked cards are stored in bytes, not bits, to make write barrier
+ // faster and reduce chances of false sharing. This gives only ~0.1% of memory
+ // overhead. Also, since there are guard pages before and after a Blink page,
+ // some of card bits are wasted and unneeded.
+ class CardTable final {
+ public:
+ struct value_type {
+ uint8_t bit;
+ size_t index;
+ };
+
+ struct iterator {
+ iterator& operator++() {
+ ++index;
+ return *this;
+ }
+ value_type operator*() const { return {table->table_[index], index}; }
+ bool operator!=(iterator other) const {
+ return table != other.table || index != other.index;
+ }
+
+ size_t index = 0;
+ const CardTable* table = nullptr;
+ };
+
+ using const_iterator = iterator;
+
+ static constexpr size_t kBitsPerCard = 9;
+ static constexpr size_t kCardSize = 1 << kBitsPerCard;
+
+ const_iterator begin() const { return {FirstPayloadCard(), this}; }
+ const_iterator end() const { return {LastPayloadCard(), this}; }
+
+ void Mark(size_t card) {
+ DCHECK_LE(FirstPayloadCard(), card);
+ DCHECK_GT(LastPayloadCard(), card);
+ table_[card] = 1;
+ }
+
+ bool IsMarked(size_t card) const {
+ DCHECK_LE(FirstPayloadCard(), card);
+ DCHECK_GT(LastPayloadCard(), card);
+ return table_[card];
+ }
+
+ void Clear() { std::fill(table_.begin(), table_.end(), 0); }
+
+ private:
+ static constexpr size_t FirstPayloadCard() {
+ return (kBlinkGuardPageSize + NormalPage::PageHeaderSize()) / kCardSize;
+ }
+ static constexpr size_t LastPayloadCard() {
+ return (kBlinkGuardPageSize + BlinkPagePayloadSize()) / kCardSize;
+ }
+
+ std::array<uint8_t, kBlinkPageSize / kCardSize> table_{};
+ };
+
struct ToBeFinalizedObject {
HeapObjectHeader* header;
void Finalize();
@@ -727,16 +796,25 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
size_t size;
};
+ template <typename Function>
+ void IterateOnCard(Function function, size_t card_number) const;
+
void MergeFreeLists();
void AddToFreeList(Address start,
size_t size,
FinalizeType finalize_type,
bool found_finalizer);
+ CardTable card_table_;
ObjectStartBitmap object_start_bit_map_;
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ std::unique_ptr<ObjectStartBitmap> cached_object_start_bit_map_;
+#endif
Vector<ToBeFinalizedObject> to_be_finalized_objects_;
FreeList cached_freelist_;
Vector<FutureFreelistEntry> unfinalized_freelist_;
+
+ friend class CardTableTest;
};
// Large allocations are allocated as separate objects and linked in a list.
@@ -771,7 +849,7 @@ class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
// ObjectSize(): PayloadSize() + sizeof(HeapObjectHeader)
// size(): ObjectSize() + PageHeaderSize()
- HeapObjectHeader* ObjectHeader() {
+ HeapObjectHeader* ObjectHeader() const {
Address header_address = GetAddress() + PageHeaderSize();
return reinterpret_cast<HeapObjectHeader*>(header_address);
}
@@ -781,18 +859,18 @@ class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
size_t ObjectSize() const { return object_size_; }
// Returns the size of the page including the header.
- size_t size() override { return PageHeaderSize() + object_size_; }
+ size_t size() const override { return PageHeaderSize() + object_size_; }
// Returns the payload start of the underlying object.
- Address Payload() { return ObjectHeader()->Payload(); }
+ Address Payload() const { return ObjectHeader()->Payload(); }
// Returns the payload size of the underlying object.
- size_t PayloadSize() { return object_size_ - sizeof(HeapObjectHeader); }
+ size_t PayloadSize() const { return object_size_ - sizeof(HeapObjectHeader); }
// Points to the payload end of the underlying object.
- Address PayloadEnd() { return Payload() + PayloadSize(); }
+ Address PayloadEnd() const { return Payload() + PayloadSize(); }
- bool ContainedInObjectPayload(Address address) {
+ bool ContainedInObjectPayload(ConstAddress address) const {
return Payload() <= address && address < PayloadEnd();
}
@@ -800,6 +878,7 @@ class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
void RemoveFromHeap() override;
bool Sweep(FinalizeType) override;
void MakeConsistentForMutator() override;
+ void Unmark() override;
void FinalizeSweep(SweepResult) override;
void CollectStatistics(
@@ -815,7 +894,7 @@ class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
// Returns true for any address that is on one of the pages that this large
// object uses. That ensures that we can use a negative result to populate the
// negative page cache.
- bool Contains(Address) override;
+ bool Contains(ConstAddress) const override;
#endif
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
@@ -823,12 +902,19 @@ class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
bool IsVectorBackingPage() const { return is_vector_backing_page_; }
#endif
+ // Remembers the page as containing inter-generational pointers.
+ void SetRemembered(bool remembered) {
+ is_remembered_ = remembered;
+ }
+ bool IsRemembered() const { return is_remembered_; }
+
private:
// The size of the underlying object including HeapObjectHeader.
size_t object_size_;
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
bool is_vector_backing_page_;
#endif
+ bool is_remembered_ = false;
};
// Each thread has a number of thread arenas (e.g., Generic arenas, typed arenas
@@ -852,17 +938,18 @@ class PLATFORM_EXPORT BaseArena {
ThreadState::Statistics::FreeListStatistics*) {}
#if DCHECK_IS_ON()
- BasePage* FindPageFromAddress(Address);
+ BasePage* FindPageFromAddress(ConstAddress) const;
#endif
virtual void ClearFreeLists() {}
virtual void MakeIterable() {}
virtual void MakeConsistentForGC();
void MakeConsistentForMutator();
+ void Unmark();
#if DCHECK_IS_ON()
virtual bool IsConsistentForGC() = 0;
#endif
size_t ObjectPayloadSizeForTesting();
- void PrepareForSweep();
+ void PrepareForSweep(BlinkGC::CollectionType);
#if defined(ADDRESS_SANITIZER)
void PoisonUnmarkedObjects();
#endif
@@ -872,7 +959,8 @@ class PLATFORM_EXPORT BaseArena {
// Returns true if we have swept all pages within the deadline. Returns false
// otherwise.
bool LazySweepWithDeadline(base::TimeTicks deadline);
- bool ConcurrentSweepWithDeadline(base::TimeTicks deadline);
+ // Returns true if the arena has been fully swept.
+ bool ConcurrentSweepOnePage();
void CompleteSweep();
void InvokeFinalizersOnSweptPages();
@@ -919,15 +1007,7 @@ class PLATFORM_EXPORT BaseArena {
class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
public:
NormalPageArena(ThreadState*, int index);
- void AddToFreeList(Address address, size_t size) {
-#if DCHECK_IS_ON()
- DCHECK(FindPageFromAddress(address));
- // TODO(palmer): Do we need to handle about integer overflow here (and in
- // similar expressions elsewhere)?
- DCHECK(FindPageFromAddress(address + size - 1));
-#endif
- free_list_.Add(address, size);
- }
+ void AddToFreeList(Address address, size_t size);
void AddToFreeList(FreeList* other) { free_list_.MoveFrom(other); }
void ClearFreeLists() override;
void CollectFreeListStatistics(
@@ -936,7 +1016,7 @@ class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
#if DCHECK_IS_ON()
bool IsConsistentForGC() override;
- bool PagesToBeSweptContains(Address);
+ bool PagesToBeSweptContains(ConstAddress) const;
#endif
Address AllocateObject(size_t allocation_size, size_t gc_info_index);
@@ -964,7 +1044,7 @@ class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
Address CurrentAllocationPoint() const { return current_allocation_point_; }
- bool IsInCurrentAllocationPointRegion(Address address) const {
+ bool IsInCurrentAllocationPointRegion(ConstAddress address) const {
return HasCurrentAllocationArea() &&
(CurrentAllocationPoint() <= address) &&
(address < (CurrentAllocationPoint() + RemainingAllocationSize()));
@@ -974,6 +1054,9 @@ class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
void MakeConsistentForGC() override;
+ template <typename Function>
+ void IterateAndClearCardTables(Function function);
+
private:
void AllocatePage();
@@ -992,14 +1075,9 @@ class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
}
void SetAllocationPoint(Address, size_t);
- // Only use when adjusting the area from allocation and free and not when
- // returning it to free list.
- void SetRemainingAllocationSize(size_t);
-
FreeList free_list_;
Address current_allocation_point_;
size_t remaining_allocation_size_;
- size_t last_remaining_allocation_size_;
// The size of promptly freed objects in the heap. This counter is set to
// zero before sweeping when clearing the free list and after coalescing.
@@ -1017,6 +1095,9 @@ class LargeObjectArena final : public BaseArena {
bool IsConsistentForGC() override { return true; }
#endif
+ template <typename Function>
+ void IterateAndClearRememberedPages(Function function);
+
private:
Address DoAllocateLargeObjectPage(size_t, size_t gc_info_index);
Address LazySweepPages(size_t, size_t gc_info_index) override;
@@ -1053,7 +1134,7 @@ inline HeapObjectHeader* HeapObjectHeader::FromInnerAddress(
return page->IsLargeObjectPage()
? static_cast<LargeObjectPage*>(page)->ObjectHeader()
: static_cast<NormalPage*>(page)->FindHeaderFromAddress<mode>(
- reinterpret_cast<Address>(const_cast<void*>(address)));
+ reinterpret_cast<ConstAddress>(address));
}
inline void HeapObjectHeader::CheckFromPayload(const void* payload) {
@@ -1062,19 +1143,10 @@ inline void HeapObjectHeader::CheckFromPayload(const void* payload) {
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const {
- uint16_t encoded_low_value;
- if (mode == AccessMode::kNonAtomic) {
- encoded_low_value = encoded_low_;
- } else {
- // mode == AccessMode::kAtomic
- // Relaxed load as size is immutable after construction while either
- // marking or sweeping is running
- internal::AsanUnpoisonScope unpoison_scope(
- static_cast<const void*>(&encoded_low_), sizeof(encoded_low_));
- encoded_low_value =
- reinterpret_cast<const std::atomic<uint16_t>&>(encoded_low_)
- .load(std::memory_order_relaxed);
- }
+ // Size is immutable after construction while either marking or sweeping
+ // is running so relaxed load (if mode == kAtomic) is enough.
+ uint16_t encoded_low_value =
+ LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>();
const size_t result = internal::DecodeSize(encoded_low_value);
// Large objects should not refer to header->size() but use
// LargeObjectPage::PayloadSize().
@@ -1090,21 +1162,24 @@ NO_SANITIZE_ADDRESS inline void HeapObjectHeader::SetSize(size_t size) {
(encoded_low_ & ~kHeaderSizeMask));
}
+template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsLargeObject() const {
- return internal::DecodeSize(encoded_low_) == kLargeObjectSizeInHeader;
+ uint16_t encoded_low_value =
+ LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>();
+ return internal::DecodeSize(encoded_low_value) == kLargeObjectSizeInHeader;
}
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsInConstruction() const {
- return (LoadEncoded<mode, EncodedHalf::kHigh>() &
+ return (LoadEncoded<mode, EncodedHalf::kHigh, std::memory_order_acquire>() &
kHeaderIsInConstructionMask) == 0;
}
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline void HeapObjectHeader::MarkFullyConstructed() {
DCHECK(IsInConstruction());
- StoreEncoded<mode, EncodedHalf::kHigh>(kHeaderIsInConstructionMask,
- kHeaderIsInConstructionMask);
+ StoreEncoded<mode, EncodedHalf::kHigh, std::memory_order_release>(
+ kHeaderIsInConstructionMask, kHeaderIsInConstructionMask);
}
inline Address HeapObjectHeader::Payload() const {
@@ -1130,20 +1205,22 @@ NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::PayloadSize() const {
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsMarked() const {
- const uint16_t encoded = LoadEncoded<mode, EncodedHalf::kLow>();
+ const uint16_t encoded =
+ LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>();
return encoded & kHeaderMarkBitMask;
}
template <HeapObjectHeader::AccessMode mode>
-NO_SANITIZE_ADDRESS inline void HeapObjectHeader::Mark() {
- DCHECK(!IsMarked<mode>());
- StoreEncoded<mode, EncodedHalf::kLow>(kHeaderMarkBitMask, kHeaderMarkBitMask);
+NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsOld() const {
+ // Oilpan uses the sticky-mark-bits technique to encode old objects.
+ return IsMarked<mode>();
}
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline void HeapObjectHeader::Unmark() {
DCHECK(IsMarked<mode>());
- StoreEncoded<mode, EncodedHalf::kLow>(0u, kHeaderMarkBitMask);
+ StoreEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>(
+ 0u, kHeaderMarkBitMask);
}
// The function relies on size bits being unmodified when the function is
@@ -1156,16 +1233,12 @@ NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::TryMark() {
encoded_low_ |= kHeaderMarkBitMask;
return true;
}
- internal::AsanUnpoisonScope unpoison_scope(
- static_cast<const void*>(&encoded_low_), sizeof(encoded_low_));
- auto* atomic_encoded =
- reinterpret_cast<std::atomic<uint16_t>*>(&encoded_low_);
+ auto* atomic_encoded = internal::AsUnsanitizedAtomic(&encoded_low_);
uint16_t old_value = atomic_encoded->load(std::memory_order_relaxed);
if (old_value & kHeaderMarkBitMask)
return false;
const uint16_t new_value = old_value | kHeaderMarkBitMask;
return atomic_encoded->compare_exchange_strong(old_value, new_value,
- std::memory_order_acq_rel,
std::memory_order_relaxed);
}
@@ -1176,8 +1249,12 @@ inline Address NormalPageArena::AllocateObject(size_t allocation_size,
current_allocation_point_ += allocation_size;
remaining_allocation_size_ -= allocation_size;
DCHECK_GT(gc_info_index, 0u);
- new (NotNull, header_address) HeapObjectHeader(
- allocation_size, gc_info_index, HeapObjectHeader::kNormalPage);
+ new (NotNull, header_address)
+ HeapObjectHeader(allocation_size, gc_info_index);
+ DCHECK(!PageFromObject(header_address)->IsLargeObjectPage());
+ static_cast<NormalPage*>(PageFromObject(header_address))
+ ->object_start_bit_map()
+ ->SetBit(header_address);
Address result = header_address + sizeof(HeapObjectHeader);
DCHECK(!(reinterpret_cast<uintptr_t>(result) & kAllocationMask));
@@ -1194,6 +1271,29 @@ inline NormalPageArena* NormalPage::ArenaForNormalPage() const {
return static_cast<NormalPageArena*>(Arena());
}
+// Iterates over all card tables and clears them.
+template <typename Function>
+inline void NormalPageArena::IterateAndClearCardTables(Function function) {
+ for (BasePage* page : swept_pages_) {
+ auto* normal_page = static_cast<NormalPage*>(page);
+ normal_page->IterateCardTable(function);
+ normal_page->ClearCardTable();
+ }
+}
+
+// Iterates over all pages that may contain inter-generational pointers.
+template <typename Function>
+inline void LargeObjectArena::IterateAndClearRememberedPages(
+ Function function) {
+ for (BasePage* page : swept_pages_) {
+ auto* large_page = static_cast<LargeObjectPage*>(page);
+ if (large_page->IsRemembered()) {
+ function(large_page->ObjectHeader());
+ large_page->SetRemembered(false);
+ }
+ }
+}
+
inline void ObjectStartBitmap::SetBit(Address header_address) {
size_t cell_index, object_bit;
ObjectStartIndexAndBit(header_address, &cell_index, &object_bit);
@@ -1248,8 +1348,7 @@ inline void ObjectStartBitmap::Iterate(Callback callback) const {
NO_SANITIZE_ADDRESS inline HeapObjectHeader::HeapObjectHeader(
size_t size,
- size_t gc_info_index,
- HeaderLocation header_location) {
+ size_t gc_info_index) {
// sizeof(HeapObjectHeader) must be equal to or smaller than
// |kAllocationGranularity|, because |HeapObjectHeader| is used as a header
// for a freed entry. Given that the smallest entry size is
@@ -1264,52 +1363,44 @@ NO_SANITIZE_ADDRESS inline HeapObjectHeader::HeapObjectHeader(
encoded_high_ =
static_cast<uint16_t>(gc_info_index << kHeaderGCInfoIndexShift);
encoded_low_ = internal::EncodeSize(size);
- if (header_location == kNormalPage) {
- DCHECK(!PageFromObject(this)->IsLargeObjectPage());
- static_cast<NormalPage*>(PageFromObject(this))
- ->object_start_bit_map()
- ->SetBit(reinterpret_cast<Address>(this));
- } else {
- DCHECK(PageFromObject(this)->IsLargeObjectPage());
- }
DCHECK(IsInConstruction());
}
-template <HeapObjectHeader::AccessMode mode, HeapObjectHeader::EncodedHalf part>
+template <HeapObjectHeader::AccessMode mode,
+ HeapObjectHeader::EncodedHalf part,
+ std::memory_order memory_order>
NO_SANITIZE_ADDRESS inline uint16_t HeapObjectHeader::LoadEncoded() const {
const uint16_t& half =
- (part == EncodedHalf::kLow ? encoded_low_ : encoded_high_);
- internal::AsanUnpoisonScope unpoison_scope(static_cast<const void*>(&half),
- sizeof(half));
+ part == EncodedHalf::kLow ? encoded_low_ : encoded_high_;
if (mode == AccessMode::kNonAtomic)
return half;
- return reinterpret_cast<const std::atomic<uint16_t>&>(half).load(
- std::memory_order_acquire);
+ return internal::AsUnsanitizedAtomic(&half)->load(memory_order);
}
// Sets bits selected by the mask to the given value. Please note that atomicity
// of the whole operation is not guaranteed.
-template <HeapObjectHeader::AccessMode mode, HeapObjectHeader::EncodedHalf part>
+template <HeapObjectHeader::AccessMode mode,
+ HeapObjectHeader::EncodedHalf part,
+ std::memory_order memory_order>
NO_SANITIZE_ADDRESS inline void HeapObjectHeader::StoreEncoded(uint16_t bits,
uint16_t mask) {
DCHECK_EQ(static_cast<uint16_t>(0u), bits & ~mask);
- uint16_t* half = (part == EncodedHalf::kLow ? &encoded_low_ : &encoded_high_);
- internal::AsanUnpoisonScope unpoison_scope(static_cast<void*>(half),
- sizeof(&half));
+ uint16_t& half = part == EncodedHalf::kLow ? encoded_low_ : encoded_high_;
if (mode == AccessMode::kNonAtomic) {
- *half = (*half & ~mask) | bits;
+ half = (half & ~mask) | bits;
return;
}
// We don't perform CAS loop here assuming that the data is constant and no
// one except for us can change this half concurrently.
- auto* atomic_encoded = reinterpret_cast<std::atomic<uint16_t>*>(half);
+ auto* atomic_encoded = internal::AsUnsanitizedAtomic(&half);
uint16_t value = atomic_encoded->load(std::memory_order_relaxed);
value = (value & ~mask) | bits;
- atomic_encoded->store(value, std::memory_order_release);
+ atomic_encoded->store(value, memory_order);
}
template <HeapObjectHeader::AccessMode mode>
-HeapObjectHeader* NormalPage::FindHeaderFromAddress(Address address) {
+HeapObjectHeader* NormalPage::FindHeaderFromAddress(
+ ConstAddress address) const {
DCHECK(ContainedInObjectPayload(address));
DCHECK(!ArenaForNormalPage()->IsInCurrentAllocationPointRegion(address));
HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(
@@ -1319,6 +1410,54 @@ HeapObjectHeader* NormalPage::FindHeaderFromAddress(Address address) {
return header;
}
+template <typename Function>
+void NormalPage::IterateCardTable(Function function) const {
+ // TODO(bikineev): Consider introducing a "dirty" per-page bit to avoid
+ // the loop (this may in turn pessimize barrier implementation).
+ for (auto card : card_table_) {
+ if (UNLIKELY(card.bit)) {
+ IterateOnCard(std::move(function), card.index);
+ }
+ }
+}
+
+// Iterates over all objects in the specified marked card. Please note that
+// since objects are not aligned by the card boundary, it starts from the
+// object which may reside on a previous card.
+template <typename Function>
+void NormalPage::IterateOnCard(Function function, size_t card_number) const {
+#if DCHECK_IS_ON()
+ DCHECK(card_table_.IsMarked(card_number));
+ DCHECK(ArenaForNormalPage()->IsConsistentForGC());
+#endif
+
+ const Address card_begin = RoundToBlinkPageStart(GetAddress()) +
+ (card_number << CardTable::kBitsPerCard);
+ const Address card_end = card_begin + CardTable::kCardSize;
+ // Generational barrier marks cards corresponding to slots (not source
+ // objects), therefore the potential source object may reside on a
+ // previous card.
+ HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(
+ card_number == card_table_.begin().index
+ ? Payload()
+ : object_start_bit_map_.FindHeader(card_begin));
+ for (; header < reinterpret_cast<HeapObjectHeader*>(card_end);
+ reinterpret_cast<Address&>(header) += header->size()) {
+ if (!header->IsFree()) {
+ function(header);
+ }
+ }
+}
+
+inline void NormalPage::MarkCard(Address address) {
+#if DCHECK_IS_ON()
+ DCHECK(Contains(address));
+#endif
+ const size_t byte = reinterpret_cast<size_t>(address) & kBlinkPageOffsetMask;
+ const size_t card = byte / CardTable::kCardSize;
+ card_table_.Mark(card);
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_PAGE_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
index 6b8dc5c4cfd..41b2a28062d 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
@@ -14,11 +14,13 @@ namespace blink {
void ThreadHeapStatsCollector::IncreaseCompactionFreedSize(size_t bytes) {
DCHECK(is_started_);
current_.compaction_freed_bytes += bytes;
+ current_.compaction_recorded_events = true;
}
void ThreadHeapStatsCollector::IncreaseCompactionFreedPages(size_t pages) {
DCHECK(is_started_);
current_.compaction_freed_pages += pages;
+ current_.compaction_recorded_events = true;
}
void ThreadHeapStatsCollector::IncreaseAllocatedObjectSize(size_t bytes) {
@@ -100,11 +102,14 @@ void ThreadHeapStatsCollector::IncreaseCollectedWrapperCount(size_t count) {
collected_wrapper_count_ += count;
}
-void ThreadHeapStatsCollector::NotifyMarkingStarted(BlinkGC::GCReason reason) {
+void ThreadHeapStatsCollector::NotifyMarkingStarted(
+ BlinkGC::CollectionType collection_type,
+ BlinkGC::GCReason reason) {
DCHECK(!is_started_);
DCHECK(current_.marking_time().is_zero());
is_started_ = true;
current_.reason = reason;
+ current_.collection_type = collection_type;
}
void ThreadHeapStatsCollector::NotifyMarkingCompleted(size_t marked_bytes) {
@@ -170,6 +175,10 @@ base::TimeDelta ThreadHeapStatsCollector::estimated_marking_time() const {
return base::TimeDelta::FromSecondsD(estimated_marking_time_in_seconds());
}
+base::TimeDelta ThreadHeapStatsCollector::Event::roots_marking_time() const {
+ return scope_data[kVisitRoots];
+}
+
base::TimeDelta ThreadHeapStatsCollector::Event::incremental_marking_time()
const {
return scope_data[kIncrementalMarkingStartMarking] +
@@ -195,8 +204,8 @@ base::TimeDelta ThreadHeapStatsCollector::Event::foreground_marking_time()
base::TimeDelta ThreadHeapStatsCollector::Event::background_marking_time()
const {
- return base::TimeDelta::FromMicroseconds(
- base::subtle::NoBarrier_Load(&concurrent_scope_data[kConcurrentMark]));
+ return base::TimeDelta::FromMicroseconds(base::subtle::NoBarrier_Load(
+ &concurrent_scope_data[kConcurrentMarkingStep]));
}
base::TimeDelta ThreadHeapStatsCollector::Event::marking_time() const {
@@ -229,7 +238,7 @@ base::TimeDelta ThreadHeapStatsCollector::Event::foreground_sweeping_time()
base::TimeDelta ThreadHeapStatsCollector::Event::background_sweeping_time()
const {
return base::TimeDelta::FromMicroseconds(
- concurrent_scope_data[kConcurrentSweep]);
+ concurrent_scope_data[kConcurrentSweepingStep]);
}
base::TimeDelta ThreadHeapStatsCollector::Event::sweeping_time() const {
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h
index e5e7207f379..c7fa3f9b571 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -54,6 +54,7 @@ class PLATFORM_EXPORT ThreadHeapStatsObserver {
V(InvokePreFinalizers) \
V(LazySweepInIdle) \
V(LazySweepOnAllocation) \
+ V(MarkBailOutObjects) \
V(MarkInvokeEphemeronCallbacks) \
V(MarkProcessWorklist) \
V(MarkNotFullyConstructedObjects) \
@@ -63,17 +64,20 @@ class PLATFORM_EXPORT ThreadHeapStatsObserver {
V(VisitDOMWrappers) \
V(VisitPersistentRoots) \
V(VisitPersistents) \
- V(VisitStackRoots)
+ V(VisitRoots) \
+ V(VisitStackRoots) \
+ V(VisitRememberedSets)
#define FOR_ALL_CONCURRENT_SCOPES(V) \
- V(ConcurrentMark) \
- V(ConcurrentSweep)
+ V(ConcurrentMarkingStep) \
+ V(ConcurrentSweepingStep)
// Manages counters and statistics across garbage collection cycles.
//
// Usage:
// ThreadHeapStatsCollector stats_collector;
-// stats_collector.NotifyMarkingStarted(<BlinkGC::GCReason>);
+// stats_collector.NotifyMarkingStarted(<BlinkGC::CollectionType>,
+// <BlinkGC::GCReason>);
// // Use tracer.
// stats_collector.NotifySweepingCompleted();
// // Previous event is available using stats_collector.previous().
@@ -96,12 +100,13 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
kNumConcurrentScopeIds
};
- constexpr static const char* ToString(Id id) {
+ constexpr static const char* ToString(Id id, BlinkGC::CollectionType type) {
switch (id) {
-#define CASE(name) \
- case k##name: \
- return "BlinkGC." #name;
-
+#define CASE(name) \
+ case k##name: \
+ return type == BlinkGC::CollectionType::kMajor ? "BlinkGC." #name \
+ : "BlinkGC." #name \
+ ".Minor";
FOR_ALL_SCOPES(CASE)
#undef CASE
default:
@@ -110,12 +115,14 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
return nullptr;
}
- constexpr static const char* ToString(ConcurrentId id) {
+ constexpr static const char* ToString(ConcurrentId id,
+ BlinkGC::CollectionType type) {
switch (id) {
-#define CASE(name) \
- case k##name: \
- return "BlinkGC." #name;
-
+#define CASE(name) \
+ case k##name: \
+ return type == BlinkGC::CollectionType::kMajor ? "BlinkGC." #name \
+ : "BlinkGC." #name \
+ ".Minor";
FOR_ALL_CONCURRENT_SCOPES(CASE)
#undef CASE
default:
@@ -140,60 +147,31 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
public:
template <typename... Args>
- inline InternalScope(ThreadHeapStatsCollector* tracer,
- IdType id,
- Args... args)
+ InternalScope(ThreadHeapStatsCollector* tracer, IdType id, Args... args)
: tracer_(tracer), start_time_(base::TimeTicks::Now()), id_(id) {
- StartTrace(id, args...);
+ StartTrace(args...);
}
- inline ~InternalScope() {
- StopTrace(id_);
+ ~InternalScope() {
+ StopTrace();
IncreaseScopeTime(id_);
}
private:
- constexpr static const char* TraceCategory() {
- switch (trace_category) {
- case kEnabled:
- return "blink_gc";
- case kDisabled:
- return TRACE_DISABLED_BY_DEFAULT("blink_gc");
- case kDevTools:
- return "blink_gc,devtools.timeline";
- }
- }
-
- void StartTrace(IdType id) {
- TRACE_EVENT_BEGIN0(TraceCategory(), ToString(id));
- }
+ inline constexpr static const char* TraceCategory();
+ inline void StartTrace();
template <typename Value1>
- void StartTrace(IdType id, const char* k1, Value1 v1) {
- TRACE_EVENT_BEGIN1(TraceCategory(), ToString(id), k1, v1);
- }
-
+ inline void StartTrace(const char* k1, Value1 v1);
template <typename Value1, typename Value2>
- void StartTrace(IdType id,
- const char* k1,
- Value1 v1,
- const char* k2,
- Value2 v2) {
- TRACE_EVENT_BEGIN2(TraceCategory(), ToString(id), k1, v1, k2, v2);
- }
+ inline void StartTrace(const char* k1,
+ Value1 v1,
+ const char* k2,
+ Value2 v2);
+ inline void StopTrace();
- void StopTrace(IdType id) {
- TRACE_EVENT_END0(TraceCategory(), ToString(id));
- }
-
- void IncreaseScopeTime(Id) {
- tracer_->IncreaseScopeTime(id_, base::TimeTicks::Now() - start_time_);
- }
-
- void IncreaseScopeTime(ConcurrentId) {
- tracer_->IncreaseConcurrentScopeTime(
- id_, base::TimeTicks::Now() - start_time_);
- }
+ inline void IncreaseScopeTime(Id);
+ inline void IncreaseScopeTime(ConcurrentId);
ThreadHeapStatsCollector* const tracer_;
const base::TimeTicks start_time_;
@@ -250,6 +228,9 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
// Time spent in the final atomic pause in sweeping and compacting the heap.
base::TimeDelta atomic_sweep_and_compact_time() const;
+ // Time spent marking the roots.
+ base::TimeDelta roots_marking_time() const;
+
// Time spent incrementally marking the heap.
base::TimeDelta incremental_marking_time() const;
@@ -278,9 +259,11 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
size_t marked_bytes = 0;
size_t compaction_freed_bytes = 0;
size_t compaction_freed_pages = 0;
+ bool compaction_recorded_events = false;
base::TimeDelta scope_data[kNumScopeIds];
base::subtle::Atomic32 concurrent_scope_data[kNumConcurrentScopeIds]{0};
BlinkGC::GCReason reason = static_cast<BlinkGC::GCReason>(0);
+ BlinkGC::CollectionType collection_type = BlinkGC::CollectionType::kMajor;
size_t object_size_in_bytes_before_sweeping = 0;
size_t allocated_space_in_bytes_before_sweeping = 0;
size_t partition_alloc_bytes_before_sweeping = 0;
@@ -290,7 +273,7 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
};
// Indicates a new garbage collection cycle.
- void NotifyMarkingStarted(BlinkGC::GCReason);
+ void NotifyMarkingStarted(BlinkGC::CollectionType, BlinkGC::GCReason);
// Indicates that marking of the current garbage collection cycle is
// completed.
@@ -405,6 +388,71 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, StopResetsCurrent);
};
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+constexpr const char*
+ThreadHeapStatsCollector::InternalScope<trace_category,
+ scope_category>::TraceCategory() {
+ switch (trace_category) {
+ case kEnabled:
+ return "blink_gc";
+ case kDisabled:
+ return TRACE_DISABLED_BY_DEFAULT("blink_gc");
+ case kDevTools:
+ return "blink_gc,devtools.timeline";
+ }
+}
+
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+void ThreadHeapStatsCollector::InternalScope<trace_category,
+ scope_category>::StartTrace() {
+ TRACE_EVENT_BEGIN0(TraceCategory(),
+ ToString(id_, tracer_->current_.collection_type));
+}
+
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+template <typename Value1>
+void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>::
+ StartTrace(const char* k1, Value1 v1) {
+ TRACE_EVENT_BEGIN1(TraceCategory(),
+ ToString(id_, tracer_->current_.collection_type), k1, v1);
+}
+
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+template <typename Value1, typename Value2>
+void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>::
+ StartTrace(const char* k1, Value1 v1, const char* k2, Value2 v2) {
+ TRACE_EVENT_BEGIN2(TraceCategory(),
+ ToString(id_, tracer_->current_.collection_type), k1, v1,
+ k2, v2);
+}
+
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+void ThreadHeapStatsCollector::InternalScope<trace_category,
+ scope_category>::StopTrace() {
+ TRACE_EVENT_END0(TraceCategory(),
+ ToString(id_, tracer_->current_.collection_type));
+}
+
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>::
+ IncreaseScopeTime(Id) {
+ tracer_->IncreaseScopeTime(id_, base::TimeTicks::Now() - start_time_);
+}
+
+template <ThreadHeapStatsCollector::TraceCategory trace_category,
+ ThreadHeapStatsCollector::ScopeContext scope_category>
+void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>::
+ IncreaseScopeTime(ConcurrentId) {
+ tracer_->IncreaseConcurrentScopeTime(id_,
+ base::TimeTicks::Now() - start_time_);
+}
+
#undef FOR_ALL_SCOPES
#undef FOR_ALL_CONCURRENT_SCOPES
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
index 314f68f9520..493a5d1658b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
@@ -21,7 +21,8 @@ constexpr size_t kNoMarkedBytes = 0;
TEST(ThreadHeapStatsCollectorTest, InitialEmpty) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
for (int i = 0; i < ThreadHeapStatsCollector::kNumScopeIds; i++) {
EXPECT_EQ(base::TimeDelta(), stats_collector.current().scope_data[i]);
}
@@ -31,7 +32,8 @@ TEST(ThreadHeapStatsCollectorTest, InitialEmpty) {
TEST(ThreadHeapStatsCollectorTest, IncreaseScopeTime) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStep,
base::TimeDelta::FromMilliseconds(1));
@@ -44,7 +46,8 @@ TEST(ThreadHeapStatsCollectorTest, IncreaseScopeTime) {
TEST(ThreadHeapStatsCollectorTest, StopMovesCurrentToPrevious) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStep,
base::TimeDelta::FromMilliseconds(1));
@@ -57,7 +60,8 @@ TEST(ThreadHeapStatsCollectorTest, StopMovesCurrentToPrevious) {
TEST(ThreadHeapStatsCollectorTest, StopResetsCurrent) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStep,
base::TimeDelta::FromMilliseconds(1));
@@ -71,7 +75,8 @@ TEST(ThreadHeapStatsCollectorTest, StopResetsCurrent) {
TEST(ThreadHeapStatsCollectorTest, StartStop) {
ThreadHeapStatsCollector stats_collector;
EXPECT_FALSE(stats_collector.is_started());
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_TRUE(stats_collector.is_started());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
@@ -81,12 +86,14 @@ TEST(ThreadHeapStatsCollectorTest, StartStop) {
TEST(ThreadHeapStatsCollectorTest, ScopeToString) {
EXPECT_STREQ("BlinkGC.IncrementalMarkingStartMarking",
ThreadHeapStatsCollector::ToString(
- ThreadHeapStatsCollector::kIncrementalMarkingStartMarking));
+ ThreadHeapStatsCollector::kIncrementalMarkingStartMarking,
+ BlinkGC::CollectionType::kMajor));
}
TEST(ThreadHeapStatsCollectorTest, UpdateReason) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.UpdateReason(BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifySweepingCompleted();
@@ -96,7 +103,8 @@ TEST(ThreadHeapStatsCollectorTest, UpdateReason) {
TEST(ThreadHeapStatsCollectorTest, InitialEstimatedObjectSize) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_EQ(0u, stats_collector.object_size_in_bytes());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
@@ -104,7 +112,8 @@ TEST(ThreadHeapStatsCollectorTest, InitialEstimatedObjectSize) {
TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeNoMarkedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseAllocatedObjectSizeForTesting(512);
EXPECT_EQ(512u, stats_collector.object_size_in_bytes());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
@@ -113,10 +122,12 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeNoMarkedBytes) {
TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeWithMarkedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.IncreaseAllocatedObjectSizeForTesting(512);
EXPECT_EQ(640u, stats_collector.object_size_in_bytes());
@@ -126,10 +137,12 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeWithMarkedBytes) {
TEST(ThreadHeapStatsCollectorTest,
EstimatedObjectSizeDoNotCountCurrentlyMarkedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
// Currently marked bytes should not account to the estimated object size.
stats_collector.IncreaseAllocatedObjectSizeForTesting(512);
@@ -141,7 +154,8 @@ TEST(ThreadHeapStatsCollectorTest, PreInitializedEstimatedMarkingTime) {
// Checks that a marking time estimate can be retrieved before the first
// garbage collection triggers.
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_LT(0u, stats_collector.estimated_marking_time_in_seconds());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
@@ -149,13 +163,15 @@ TEST(ThreadHeapStatsCollectorTest, PreInitializedEstimatedMarkingTime) {
TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime1) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure,
base::TimeDelta::FromSeconds(1));
stats_collector.NotifyMarkingCompleted(1024);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_DOUBLE_EQ(1.0, stats_collector.estimated_marking_time_in_seconds());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
@@ -163,13 +179,15 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime1) {
TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime2) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure,
base::TimeDelta::FromSeconds(1));
stats_collector.NotifyMarkingCompleted(1024);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseAllocatedObjectSizeForTesting(512);
EXPECT_DOUBLE_EQ(1.5, stats_collector.estimated_marking_time_in_seconds());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
@@ -178,7 +196,8 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime2) {
TEST(ThreadHeapStatsCollectorTest, SubMilliSecondMarkingTime) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStartMarking,
base::TimeDelta::FromMillisecondsD(.5));
@@ -191,7 +210,8 @@ TEST(ThreadHeapStatsCollectorTest, SubMilliSecondMarkingTime) {
TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesInitialZero) {
ThreadHeapStatsCollector stats_collector;
EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
@@ -218,7 +238,8 @@ TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesDecrease) {
TEST(ThreadHeapStatsCollectorTest, EventPrevGCMarkedObjectSize) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(1024);
stats_collector.NotifySweepingCompleted();
EXPECT_EQ(1024u, stats_collector.previous().marked_bytes);
@@ -227,7 +248,8 @@ TEST(ThreadHeapStatsCollectorTest, EventPrevGCMarkedObjectSize) {
TEST(ThreadHeapStatsCollectorTest,
EventMarkingTimeFromIncrementalStandAloneGC) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStartMarking,
base::TimeDelta::FromMilliseconds(7));
@@ -245,7 +267,8 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeFromIncrementalUnifiedGC) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStartMarking,
base::TimeDelta::FromMilliseconds(7));
@@ -272,7 +295,8 @@ TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeFromIncrementalUnifiedGC) {
TEST(ThreadHeapStatsCollectorTest, EventMarkingTime) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kIncrementalMarkingStep,
base::TimeDelta::FromMilliseconds(2));
@@ -287,7 +311,8 @@ TEST(ThreadHeapStatsCollectorTest, EventMarkingTime) {
TEST(ThreadHeapStatsCollectorTest, EventAtomicMarkingTime) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kAtomicPauseMarkPrologue,
base::TimeDelta::FromMilliseconds(5));
@@ -305,7 +330,8 @@ TEST(ThreadHeapStatsCollectorTest, EventAtomicMarkingTime) {
TEST(ThreadHeapStatsCollectorTest, EventAtomicPause) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure,
base::TimeDelta::FromMilliseconds(17));
@@ -320,7 +346,8 @@ TEST(ThreadHeapStatsCollectorTest, EventAtomicPause) {
TEST(ThreadHeapStatsCollectorTest, EventMarkingTimePerByteInS) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseScopeTime(
ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure,
base::TimeDelta::FromSeconds(1));
@@ -332,7 +359,8 @@ TEST(ThreadHeapStatsCollectorTest, EventMarkingTimePerByteInS) {
TEST(ThreadHeapStatsCollectorTest, EventSweepingTime) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle,
base::TimeDelta::FromMilliseconds(1));
@@ -352,7 +380,8 @@ TEST(ThreadHeapStatsCollectorTest, EventSweepingTime) {
TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.IncreaseCompactionFreedSize(512);
stats_collector.NotifySweepingCompleted();
@@ -361,7 +390,8 @@ TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedBytes) {
TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedPages) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.IncreaseCompactionFreedPages(3);
stats_collector.NotifySweepingCompleted();
@@ -370,7 +400,8 @@ TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedPages) {
TEST(ThreadHeapStatsCollectorTest, EventInitialEstimatedLiveObjectRate) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate);
@@ -379,10 +410,12 @@ TEST(ThreadHeapStatsCollectorTest, EventInitialEstimatedLiveObjectRate) {
TEST(ThreadHeapStatsCollectorTest,
EventEstimatedLiveObjectRateSameMarkedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(1.0, stats_collector.previous().live_object_rate);
@@ -391,10 +424,12 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest,
EventEstimatedLiveObjectRateHalfMarkedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(256);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(0.5, stats_collector.previous().live_object_rate);
@@ -402,10 +437,12 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateNoMarkedBytes) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(256);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate);
}
@@ -413,11 +450,13 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateNoMarkedBytes) {
TEST(ThreadHeapStatsCollectorTest,
EventEstimatedLiveObjectRateWithAllocatedBytes1) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
stats_collector.IncreaseAllocatedObjectSize(128);
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(.5, stats_collector.previous().live_object_rate);
@@ -426,11 +465,13 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest,
EventEstimatedLiveObjectRateWithAllocatedBytes2) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
stats_collector.IncreaseAllocatedObjectSize(128);
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(1.0, stats_collector.previous().live_object_rate);
@@ -439,7 +480,8 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest,
EventEstimatedLiveObjectRateWithAllocatedBytes3) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate);
@@ -448,10 +490,12 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest,
EventEstimatedLiveObjectRateWithAllocatedBytes4) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(128);
stats_collector.NotifySweepingCompleted();
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate);
@@ -459,7 +503,8 @@ TEST(ThreadHeapStatsCollectorTest,
TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping1) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseAllocatedSpace(1024);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.IncreaseAllocatedSpace(2048);
@@ -471,7 +516,8 @@ TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping1) {
TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping2) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector.IncreaseAllocatedSpace(1024);
stats_collector.NotifyMarkingCompleted(kNoMarkedBytes);
stats_collector.DecreaseAllocatedSpace(1024);
@@ -497,7 +543,8 @@ class MockThreadHeapStatsObserver : public ThreadHeapStatsObserver {
};
void FakeGC(ThreadHeapStatsCollector* stats_collector, size_t marked_bytes) {
- stats_collector->NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting);
+ stats_collector->NotifyMarkingStarted(BlinkGC::CollectionType::kMajor,
+ BlinkGC::GCReason::kForcedGCForTesting);
stats_collector->NotifyMarkingCompleted(marked_bytes);
stats_collector->NotifySweepingCompleted();
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
index b9bf108f948..bc9a3c031e7 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -45,9 +45,9 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/buildflags.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/heap/heap_linked_stack.h"
#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/marking_visitor.h"
@@ -76,7 +76,7 @@ class IntWrapper : public GarbageCollected<IntWrapper> {
}
static std::atomic_int destructor_calls_;
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
int Value() const { return x_; }
@@ -262,14 +262,17 @@ class TestGCScope : public TestGCCollectGarbageScope {
explicit TestGCScope(BlinkGC::StackState state)
: TestGCCollectGarbageScope(state) {
ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted(
+ BlinkGC::CollectionType::kMajor,
BlinkGC::GCReason::kForcedGCForTesting);
ThreadState::Current()->AtomicPauseMarkPrologue(
- state, BlinkGC::kAtomicMarking, BlinkGC::GCReason::kPreciseGC);
+ BlinkGC::CollectionType::kMajor, state, BlinkGC::kAtomicMarking,
+ BlinkGC::GCReason::kPreciseGC);
}
~TestGCScope() {
ThreadState::Current()->AtomicPauseMarkEpilogue(BlinkGC::kAtomicMarking);
- ThreadState::Current()->AtomicPauseSweepAndCompact(BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping);
+ ThreadState::Current()->AtomicPauseSweepAndCompact(
+ BlinkGC::CollectionType::kMajor, BlinkGC::kAtomicMarking,
+ BlinkGC::kEagerSweeping);
ThreadState::Current()->AtomicPauseEpilogue();
}
};
@@ -277,7 +280,7 @@ class TestGCScope : public TestGCCollectGarbageScope {
class SimpleObject : public GarbageCollected<SimpleObject> {
public:
SimpleObject() = default;
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
char GetPayload(int i) { return payload[i]; }
// This virtual method is unused but it is here to make sure
// that this object has a vtable. This object is used
@@ -297,7 +300,7 @@ class HeapTestSuperClass : public GarbageCollected<HeapTestSuperClass> {
virtual ~HeapTestSuperClass() { ++destructor_calls_; }
static int destructor_calls_;
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
int HeapTestSuperClass::destructor_calls_ = 0;
@@ -335,7 +338,7 @@ class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
}
int8_t at(size_t i) { return array_[i]; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
static const int kArraySize = 1000;
@@ -533,7 +536,7 @@ class ThreadPersistentHeapTester : public ThreadedTesterBase {
public:
Local() = default;
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
class PersistentChain;
@@ -561,7 +564,7 @@ class ThreadPersistentHeapTester : public ThreadedTesterBase {
ref_counted_chain_ = base::AdoptRef(RefCountedChain::Create(count));
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
scoped_refptr<RefCountedChain> ref_counted_chain_;
@@ -590,7 +593,7 @@ class TraceCounter final : public GarbageCollected<TraceCounter> {
public:
TraceCounter() : trace_count_(0) {}
- void Trace(blink::Visitor* visitor) { trace_count_++; }
+ void Trace(Visitor* visitor) { trace_count_++; }
int TraceCount() const { return trace_count_; }
private:
@@ -601,7 +604,7 @@ TEST_F(HeapTest, IsHeapObjectAliveForConstPointer) {
// See http://crbug.com/661363.
auto* object = MakeGarbageCollected<SimpleObject>();
HeapObjectHeader* header = HeapObjectHeader::FromPayload(object);
- header->Mark();
+ EXPECT_TRUE(header->TryMark());
EXPECT_TRUE(ThreadHeap::IsHeapObjectAlive(object));
const SimpleObject* const_object = const_cast<const SimpleObject*>(object);
EXPECT_TRUE(ThreadHeap::IsHeapObjectAlive(const_object));
@@ -611,9 +614,7 @@ class ClassWithMember : public GarbageCollected<ClassWithMember> {
public:
ClassWithMember() : trace_counter_(MakeGarbageCollected<TraceCounter>()) {}
- void Trace(blink::Visitor* visitor) {
- visitor->Trace(trace_counter_);
- }
+ void Trace(Visitor* visitor) { visitor->Trace(trace_counter_); }
int TraceCount() const { return trace_counter_->TraceCount(); }
private:
@@ -628,7 +629,7 @@ class SimpleFinalizedObject final
static int destructor_calls_;
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
int SimpleFinalizedObject::destructor_calls_ = 0;
@@ -654,7 +655,7 @@ class IntNode : public GarbageCollected<IntNode> {
static IntNode* Create(int i) { return new IntNode(i); }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
int Value() { return value_; }
@@ -674,7 +675,7 @@ class Bar : public GarbageCollected<Bar> {
}
bool HasBeenFinalized() const { return !magic_; }
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
static unsigned live_;
protected:
@@ -688,7 +689,7 @@ class Baz : public GarbageCollected<Baz> {
public:
explicit Baz(Bar* bar) : bar_(bar) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(bar_); }
+ void Trace(Visitor* visitor) { visitor->Trace(bar_); }
void Clear() { bar_.Release(); }
@@ -705,16 +706,16 @@ class Foo : public Bar {
Foo(Foo* foo) : Bar(), bar_(foo), points_to_foo_(true) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
if (points_to_foo_)
- visitor->Trace(static_cast<Foo*>(bar_));
+ visitor->Trace(static_cast<const Foo*>(bar_));
else
visitor->Trace(bar_);
}
private:
- Bar* bar_;
- bool points_to_foo_;
+ const Bar* bar_;
+ const bool points_to_foo_;
};
class Bars : public Bar {
@@ -726,7 +727,7 @@ class Bars : public Bar {
}
}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
for (unsigned i = 0; i < width_; i++)
visitor->Trace(bars_[i]);
}
@@ -746,7 +747,7 @@ class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
int_wrapper_ = MakeGarbageCollected<IntWrapper>(42);
}
- void Trace(blink::Visitor* visitor) { visitor->Trace(int_wrapper_); }
+ void Trace(Visitor* visitor) { visitor->Trace(int_wrapper_); }
private:
Member<IntWrapper> int_wrapper_;
@@ -760,7 +761,7 @@ class LargeHeapObject final : public GarbageCollected<LargeHeapObject> {
char Get(size_t i) { return data_[i]; }
void Set(size_t i, char c) { data_[i] = c; }
size_t length() { return kLength; }
- void Trace(blink::Visitor* visitor) { visitor->Trace(int_wrapper_); }
+ void Trace(Visitor* visitor) { visitor->Trace(int_wrapper_); }
static int destructor_calls_;
private:
@@ -805,7 +806,7 @@ class RefCountedAndGarbageCollected final
keep_alive_.Clear();
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static int destructor_calls_;
@@ -840,7 +841,7 @@ class RefCountedAndGarbageCollected2 final
keep_alive_.Clear();
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static int destructor_calls_;
@@ -856,7 +857,7 @@ class Weak : public Bar {
Weak(Bar* strong_bar, Bar* weak_bar)
: Bar(), strong_bar_(strong_bar), weak_bar_(weak_bar) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(strong_bar_);
visitor->template RegisterWeakCallbackMethod<Weak, &Weak::ZapWeakMembers>(
this);
@@ -880,7 +881,7 @@ class WithWeakMember : public Bar {
WithWeakMember(Bar* strong_bar, Bar* weak_bar)
: Bar(), strong_bar_(strong_bar), weak_bar_(weak_bar) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(strong_bar_);
visitor->Trace(weak_bar_);
}
@@ -899,7 +900,7 @@ class Observable final : public GarbageCollected<Observable> {
public:
explicit Observable(Bar* bar) : bar_(bar), was_destructed_(false) {}
~Observable() { was_destructed_ = true; }
- void Trace(blink::Visitor* visitor) { visitor->Trace(bar_); }
+ void Trace(Visitor* visitor) { visitor->Trace(bar_); }
// willFinalize is called by FinalizationObserver. willFinalize can touch
// other on-heap objects.
@@ -924,7 +925,7 @@ class ObservableWithPreFinalizer final
public:
ObservableWithPreFinalizer() : was_destructed_(false) {}
~ObservableWithPreFinalizer() { was_destructed_ = true; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
void Dispose() {
EXPECT_FALSE(was_destructed_);
dispose_was_called_ = true;
@@ -947,7 +948,7 @@ class PreFinalizerBase : public GarbageCollected<PreFinalizerBase> {
public:
PreFinalizerBase() : was_destructed_(false) {}
virtual ~PreFinalizerBase() { was_destructed_ = true; }
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
void Dispose() {
EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base);
EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class);
@@ -965,7 +966,7 @@ class PreFinalizerMixin : public GarbageCollectedMixin {
public:
~PreFinalizerMixin() { was_destructed_ = true; }
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
void Dispose() {
EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base);
EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class);
@@ -986,7 +987,7 @@ class PreFinalizerSubClass : public PreFinalizerBase, public PreFinalizerMixin {
public:
PreFinalizerSubClass() : was_destructed_(false) {}
~PreFinalizerSubClass() override { was_destructed_ = true; }
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
void Dispose() {
EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base);
EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_sub_class);
@@ -1006,7 +1007,7 @@ class FinalizationObserver : public GarbageCollected<FinalizationObserver<T>> {
bool DidCallWillFinalize() const { return did_call_will_finalize_; }
- void Trace(blink::Visitor* visitor) {
+ void Trace(Visitor* visitor) {
visitor->template RegisterWeakCallbackMethod<
FinalizationObserver<T>, &FinalizationObserver<T>::ZapWeakMembers>(
this);
@@ -1087,7 +1088,7 @@ class PointsBack final : public GarbageCollected<PointsBack> {
SuperClass* BackPointer() const { return back_pointer_; }
- void Trace(blink::Visitor* visitor) { visitor->Trace(back_pointer_); }
+ void Trace(Visitor* visitor) { visitor->Trace(back_pointer_); }
static int alive_count_;
@@ -1113,7 +1114,7 @@ class SuperClass : public GarbageCollected<SuperClass> {
EXPECT_EQ(super_class_count, SuperClass::alive_count_);
}
- virtual void Trace(blink::Visitor* visitor) { visitor->Trace(points_back_); }
+ virtual void Trace(Visitor* visitor) { visitor->Trace(points_back_); }
PointsBack* GetPointsBack() const { return points_back_.Get(); }
@@ -1129,7 +1130,7 @@ class SubData final : public GarbageCollected<SubData> {
SubData() { ++alive_count_; }
~SubData() { --alive_count_; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static int alive_count_;
};
@@ -1144,7 +1145,7 @@ class SubClass : public SuperClass {
}
~SubClass() override { --alive_count_; }
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(data_);
SuperClass::Trace(visitor);
}
@@ -1159,7 +1160,7 @@ int SubClass::alive_count_ = 0;
class Mixin : public GarbageCollectedMixin {
public:
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
virtual char GetPayload(int i) { return padding_[i]; }
@@ -1179,7 +1180,7 @@ class UseMixin : public SimpleObject, public Mixin {
}
static int trace_count_;
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
SimpleObject::Trace(visitor);
Mixin::Trace(visitor);
++trace_count_;
@@ -1194,7 +1195,7 @@ class VectorObject {
public:
VectorObject() { value_ = MakeGarbageCollected<SimpleFinalizedObject>(); }
- void Trace(blink::Visitor* visitor) { visitor->Trace(value_); }
+ void Trace(Visitor* visitor) { visitor->Trace(value_); }
private:
Member<SimpleFinalizedObject> value_;
@@ -1221,7 +1222,7 @@ class TerminatedArrayItem {
TerminatedArrayItem(IntWrapper* payload)
: payload_(payload), is_last_(false) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(payload_); }
+ void Trace(Visitor* visitor) { visitor->Trace(payload_); }
bool IsLastInArray() const { return is_last_; }
void SetLastInArray(bool value) { is_last_ = value; }
@@ -1247,7 +1248,7 @@ class OneKiloByteObject final : public GarbageCollected<OneKiloByteObject> {
public:
~OneKiloByteObject() { destructor_calls_++; }
char* Data() { return data_; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static int destructor_calls_;
private:
@@ -1268,7 +1269,7 @@ class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
uint8_t Get(int i) { return *(reinterpret_cast<uint8_t*>(this) + i); }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
DynamicallySizedObject() = default;
@@ -1288,7 +1289,7 @@ class FinalizationAllocator final
MakeGarbageCollected<LargeHeapObject>();
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
Persistent<IntWrapper>* wrapper_;
@@ -1333,7 +1334,7 @@ class PreFinalizerBackingShrinkForbidden final
EXPECT_EQ(0ul, map_.Capacity());
}
- void Trace(blink::Visitor* visitor) {
+ void Trace(Visitor* visitor) {
visitor->Trace(vector_);
visitor->Trace(map_);
}
@@ -1369,7 +1370,7 @@ class PreFinalizerVectorBackingExpandForbidden final
}
}
- void Trace(blink::Visitor* visitor) { visitor->Trace(vector_); }
+ void Trace(Visitor* visitor) { visitor->Trace(vector_); }
private:
HeapVector<Member<IntWrapper>> vector_;
@@ -1398,7 +1399,7 @@ class PreFinalizerHashTableBackingExpandForbidden final
}
}
- void Trace(blink::Visitor* visitor) { visitor->Trace(map_); }
+ void Trace(Visitor* visitor) { visitor->Trace(map_); }
private:
HeapHashMap<int, Member<IntWrapper>> map_;
@@ -1422,7 +1423,7 @@ class PreFinalizerAllocationForbidden
#endif // DCHECK_IS_ON()
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
TEST(HeapDeathTest, PreFinalizerAllocationForbidden) {
@@ -1827,8 +1828,8 @@ TEST_F(HeapTest, LazySweepingPages) {
for (int i = 0; i < 1000; i++)
MakeGarbageCollected<SimpleFinalizedObject>();
ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
for (int i = 0; i < 10000; i++)
@@ -1861,8 +1862,8 @@ TEST_F(HeapTest, LazySweepingLargeObjectPages) {
for (int i = 0; i < 10; i++)
MakeGarbageCollected<LargeHeapObject>();
ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
for (int i = 0; i < 10; i++) {
@@ -1873,8 +1874,8 @@ TEST_F(HeapTest, LazySweepingLargeObjectPages) {
MakeGarbageCollected<LargeHeapObject>();
EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
PreciselyCollectGarbage();
@@ -2242,10 +2243,8 @@ class Container final : public GarbageCollected<Container> {
HeapVector<Member<IntWrapper>, 2> vector;
HeapVector<PairWrappedUnwrapped, 2> vector_wu;
HeapVector<PairUnwrappedWrapped, 2> vector_uw;
- HeapDeque<Member<IntWrapper>, 0> deque;
- HeapDeque<PairWrappedUnwrapped, 0> deque_wu;
- HeapDeque<PairUnwrappedWrapped, 0> deque_uw;
- void Trace(blink::Visitor* visitor) {
+ HeapDeque<Member<IntWrapper>> deque;
+ void Trace(Visitor* visitor) {
visitor->Trace(map);
visitor->Trace(set);
visitor->Trace(set2);
@@ -2254,14 +2253,12 @@ class Container final : public GarbageCollected<Container> {
visitor->Trace(vector_wu);
visitor->Trace(vector_uw);
visitor->Trace(deque);
- visitor->Trace(deque_wu);
- visitor->Trace(deque_uw);
}
};
struct NeedsTracingTrait {
explicit NeedsTracingTrait(IntWrapper* wrapper) : wrapper_(wrapper) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(wrapper_); }
+ void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
Member<IntWrapper> wrapper_;
};
@@ -2406,9 +2403,9 @@ TEST_F(HeapTest, HeapVectorOnStackLargeObjectPageSized) {
ConservativelyCollectGarbage();
}
-template <typename T, wtf_size_t inlineCapacity, typename U>
-bool DequeContains(HeapDeque<T, inlineCapacity>& deque, U u) {
- typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
+template <typename T, typename U>
+bool DequeContains(HeapDeque<T>& deque, U u) {
+ typedef typename HeapDeque<T>::iterator iterator;
for (iterator it = deque.begin(); it != deque.end(); ++it) {
if (*it == u)
return true;
@@ -2427,12 +2424,10 @@ TEST_F(HeapTest, HeapCollectionTypes) {
typedef HeapHashCountedSet<Member<IntWrapper>> MemberCountedSet;
typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
- typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
+ typedef HeapDeque<Member<IntWrapper>> MemberDeque;
typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
- typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
- typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
Persistent<MemberMember> member_member = MakeGarbageCollected<MemberMember>();
Persistent<MemberMember> member_member2 =
@@ -2454,10 +2449,6 @@ TEST_F(HeapTest, HeapCollectionTypes) {
Persistent<VectorUW> vector_uw2 = MakeGarbageCollected<VectorUW>();
Persistent<MemberDeque> deque = MakeGarbageCollected<MemberDeque>();
Persistent<MemberDeque> deque2 = MakeGarbageCollected<MemberDeque>();
- Persistent<DequeWU> deque_wu = MakeGarbageCollected<DequeWU>();
- Persistent<DequeWU> deque_wu2 = MakeGarbageCollected<DequeWU>();
- Persistent<DequeUW> deque_uw = MakeGarbageCollected<DequeUW>();
- Persistent<DequeUW> deque_uw2 = MakeGarbageCollected<DequeUW>();
Persistent<Container> container = MakeGarbageCollected<Container>();
ClearOutOldGarbage();
@@ -2475,18 +2466,14 @@ TEST_F(HeapTest, HeapCollectionTypes) {
auto* three_c(MakeGarbageCollected<IntWrapper>(3));
auto* three_d(MakeGarbageCollected<IntWrapper>(3));
auto* three_e(MakeGarbageCollected<IntWrapper>(3));
- auto* three_f(MakeGarbageCollected<IntWrapper>(3));
auto* three(MakeGarbageCollected<IntWrapper>(3));
auto* four_b(MakeGarbageCollected<IntWrapper>(4));
auto* four_c(MakeGarbageCollected<IntWrapper>(4));
auto* four_d(MakeGarbageCollected<IntWrapper>(4));
auto* four_e(MakeGarbageCollected<IntWrapper>(4));
- auto* four_f(MakeGarbageCollected<IntWrapper>(4));
auto* four(MakeGarbageCollected<IntWrapper>(4));
auto* five_c(MakeGarbageCollected<IntWrapper>(5));
auto* five_d(MakeGarbageCollected<IntWrapper>(5));
- auto* five_e(MakeGarbageCollected<IntWrapper>(5));
- auto* five_f(MakeGarbageCollected<IntWrapper>(5));
// Member Collections.
member_member2->insert(one, two);
@@ -2515,21 +2502,13 @@ TEST_F(HeapTest, HeapCollectionTypes) {
deque2->push_back(three_e);
deque2->push_back(four_e);
vector_wu->push_back(PairWrappedUnwrapped(&*one_c, 42));
- deque_wu->push_back(PairWrappedUnwrapped(&*one_e, 42));
vector_wu2->push_back(PairWrappedUnwrapped(&*three_c, 43));
vector_wu2->push_back(PairWrappedUnwrapped(&*four_c, 44));
vector_wu2->push_back(PairWrappedUnwrapped(&*five_c, 45));
- deque_wu2->push_back(PairWrappedUnwrapped(&*three_e, 43));
- deque_wu2->push_back(PairWrappedUnwrapped(&*four_e, 44));
- deque_wu2->push_back(PairWrappedUnwrapped(&*five_e, 45));
vector_uw->push_back(PairUnwrappedWrapped(1, &*one_d));
vector_uw2->push_back(PairUnwrappedWrapped(103, &*three_d));
vector_uw2->push_back(PairUnwrappedWrapped(104, &*four_d));
vector_uw2->push_back(PairUnwrappedWrapped(105, &*five_d));
- deque_uw->push_back(PairUnwrappedWrapped(1, &*one_f));
- deque_uw2->push_back(PairUnwrappedWrapped(103, &*three_f));
- deque_uw2->push_back(PairUnwrappedWrapped(104, &*four_f));
- deque_uw2->push_back(PairUnwrappedWrapped(105, &*five_f));
EXPECT_TRUE(DequeContains(*deque, one_b));
@@ -2554,10 +2533,6 @@ TEST_F(HeapTest, HeapCollectionTypes) {
EXPECT_EQ(3u, vector_uw2->size());
EXPECT_EQ(1u, deque->size());
EXPECT_EQ(2u, deque2->size());
- EXPECT_EQ(1u, deque_wu->size());
- EXPECT_EQ(3u, deque_wu2->size());
- EXPECT_EQ(1u, deque_uw->size());
- EXPECT_EQ(3u, deque_uw2->size());
MemberVector& cvec = container->vector;
cvec.swap(*vector.Get());
@@ -2579,16 +2554,6 @@ TEST_F(HeapTest, HeapCollectionTypes) {
deque2->Swap(c_deque);
deque->Swap(c_deque);
- DequeWU& c_deque_wu = container->deque_wu;
- c_deque_wu.Swap(*deque_wu.Get());
- deque_wu2->Swap(c_deque_wu);
- deque_wu->Swap(c_deque_wu);
-
- DequeUW& c_deque_uw = container->deque_uw;
- c_deque_uw.Swap(*deque_uw.Get());
- deque_uw2->Swap(c_deque_uw);
- deque_uw->Swap(c_deque_uw);
-
// Swap set and set2 in a roundabout way.
MemberSet& cset1 = container->set;
MemberSet& cset2 = container->set2;
@@ -2645,22 +2610,6 @@ TEST_F(HeapTest, HeapCollectionTypes) {
EXPECT_TRUE(vector_uw->Contains(PairUnwrappedWrapped(105, &*five_d)));
EXPECT_TRUE(vector_uw2->Contains(PairUnwrappedWrapped(1, &*one_d)));
EXPECT_FALSE(vector_uw2->Contains(PairUnwrappedWrapped(103, &*three_d)));
- EXPECT_TRUE(
- DequeContains(*deque_wu, PairWrappedUnwrapped(&*three_e, 43)));
- EXPECT_TRUE(DequeContains(*deque_wu, PairWrappedUnwrapped(&*four_e, 44)));
- EXPECT_TRUE(DequeContains(*deque_wu, PairWrappedUnwrapped(&*five_e, 45)));
- EXPECT_TRUE(DequeContains(*deque_wu2, PairWrappedUnwrapped(&*one_e, 42)));
- EXPECT_FALSE(
- DequeContains(*deque_wu2, PairWrappedUnwrapped(&*three_e, 43)));
- EXPECT_TRUE(
- DequeContains(*deque_uw, PairUnwrappedWrapped(103, &*three_f)));
- EXPECT_TRUE(
- DequeContains(*deque_uw, PairUnwrappedWrapped(104, &*four_f)));
- EXPECT_TRUE(
- DequeContains(*deque_uw, PairUnwrappedWrapped(105, &*five_f)));
- EXPECT_TRUE(DequeContains(*deque_uw2, PairUnwrappedWrapped(1, &*one_f)));
- EXPECT_FALSE(
- DequeContains(*deque_uw2, PairUnwrappedWrapped(103, &*three_f)));
}
PreciselyCollectGarbage();
@@ -2678,7 +2627,6 @@ TEST_F(HeapTest, HeapCollectionTypes) {
EXPECT_EQ(1u, vector2->size());
EXPECT_EQ(2u, deque->size());
EXPECT_EQ(1u, deque2->size());
- EXPECT_EQ(3u, deque_uw->size());
EXPECT_EQ(1u, deque2->size());
EXPECT_TRUE(member_member->at(one) == two);
@@ -2713,10 +2661,6 @@ TEST_F(HeapTest, HeapCollectionTypes) {
EXPECT_EQ(1u, vector_uw2->size());
EXPECT_EQ(2u, deque->size());
EXPECT_EQ(1u, deque2->size());
- EXPECT_EQ(3u, deque_wu->size());
- EXPECT_EQ(1u, deque_wu2->size());
- EXPECT_EQ(3u, deque_uw->size());
- EXPECT_EQ(1u, deque_uw2->size());
}
TEST_F(HeapTest, PersistentVector) {
@@ -2962,7 +2906,7 @@ class NonTrivialObject final {
deque_.push_back(MakeGarbageCollected<IntWrapper>(num));
vector_.push_back(MakeGarbageCollected<IntWrapper>(num));
}
- void Trace(blink::Visitor* visitor) {
+ void Trace(Visitor* visitor) {
visitor->Trace(deque_);
visitor->Trace(vector_);
}
@@ -3184,6 +3128,9 @@ TEST_F(HeapTest, HeapWeakLinkedHashSet) {
OrderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper>>>(false);
ClearOutOldGarbage();
OrderedSetHelper<HeapListHashSet<Member<IntWrapper>>>(true);
+ ClearOutOldGarbage();
+ // TODO(keinakashima): add a test case for WeakMember once it's supported
+ OrderedSetHelper<HeapNewLinkedHashSet<Member<IntWrapper>>>(true);
}
class ThingWithDestructor {
@@ -3311,6 +3258,7 @@ typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
+// TODO(bartekn): add HeapNewLinkedHashSet cases once WeakMember is supported
typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
@@ -3383,70 +3331,6 @@ void CheckPairSets(Persistent<WSSet>& weak_strong,
EXPECT_TRUE(unwrapped_weak->Contains(PairUnwrappedWeak(2, &*two)));
}
-template <typename WSSet, typename SWSet, typename WUSet, typename UWSet>
-void WeakPairsHelper() {
- IntWrapper::destructor_calls_ = 0;
-
- Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
- MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
-
- Persistent<WSSet> weak_strong = MakeGarbageCollected<WSSet>();
- Persistent<SWSet> strong_weak = MakeGarbageCollected<SWSet>();
- Persistent<WUSet> weak_unwrapped = MakeGarbageCollected<WUSet>();
- Persistent<UWSet> unwrapped_weak = MakeGarbageCollected<UWSet>();
-
- Persistent<IntWrapper> two = MakeGarbageCollected<IntWrapper>(2);
-
- weak_strong->insert(
- PairWeakStrong(MakeGarbageCollected<IntWrapper>(1), &*two));
- weak_strong->insert(PairWeakStrong(&*two, &*two));
- strong_weak->insert(
- PairStrongWeak(&*two, MakeGarbageCollected<IntWrapper>(1)));
- strong_weak->insert(PairStrongWeak(&*two, &*two));
- weak_unwrapped->insert(
- PairWeakUnwrapped(MakeGarbageCollected<IntWrapper>(1), 2));
- weak_unwrapped->insert(PairWeakUnwrapped(&*two, 2));
- unwrapped_weak->insert(
- PairUnwrappedWeak(2, MakeGarbageCollected<IntWrapper>(1)));
- unwrapped_weak->insert(PairUnwrappedWeak(2, &*two));
-
- CheckPairSets<WSSet, SWSet, WUSet, UWSet>(
- weak_strong, strong_weak, weak_unwrapped, unwrapped_weak, true, two);
-
- TestSupportingGC::PreciselyCollectGarbage();
- CheckPairSets<WSSet, SWSet, WUSet, UWSet>(
- weak_strong, strong_weak, weak_unwrapped, unwrapped_weak, false, two);
-}
-
-TEST_F(HeapTest, HeapWeakPairs) {
- {
- typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
- typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
- typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
- typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
- WeakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet,
- UnwrappedWeakSet>();
- }
-
- {
- typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
- typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
- typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
- typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
- WeakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet,
- UnwrappedWeakSet>();
- }
-
- {
- typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
- typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
- typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
- typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
- WeakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet,
- UnwrappedWeakSet>();
- }
-}
-
TEST_F(HeapTest, HeapWeakCollectionTypes) {
IntWrapper::destructor_calls_ = 0;
@@ -3455,6 +3339,7 @@ TEST_F(HeapTest, HeapWeakCollectionTypes) {
typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper>> WeakWeak;
typedef HeapHashSet<WeakMember<IntWrapper>> WeakSet;
typedef HeapLinkedHashSet<WeakMember<IntWrapper>> WeakOrderedSet;
+ // TODO(bartekn): add HeapNewLinkedHashSet case once WeakMember is supported
ClearOutOldGarbage();
@@ -4026,28 +3911,19 @@ TEST_F(HeapTest, CollectionNesting3) {
ClearOutOldGarbage();
IntWrapper::destructor_calls_ = 0;
typedef HeapVector<Member<IntWrapper>> IntVector;
- typedef HeapDeque<Member<IntWrapper>> IntDeque;
HeapVector<IntVector>* vector = MakeGarbageCollected<HeapVector<IntVector>>();
- HeapDeque<IntDeque>* deque = MakeGarbageCollected<HeapDeque<IntDeque>>();
vector->push_back(IntVector());
- deque->push_back(IntDeque());
HeapVector<IntVector>::iterator it = vector->begin();
- HeapDeque<IntDeque>::iterator it2 = deque->begin();
EXPECT_EQ(0u, it->size());
- EXPECT_EQ(0u, it2->size());
it->push_back(MakeGarbageCollected<IntWrapper>(42));
- it2->push_back(MakeGarbageCollected<IntWrapper>(42));
EXPECT_EQ(1u, it->size());
- EXPECT_EQ(1u, it2->size());
Persistent<HeapVector<IntVector>> keep_alive(vector);
- Persistent<HeapDeque<IntDeque>> keep_alive2(deque);
PreciselyCollectGarbage();
EXPECT_EQ(1u, it->size());
- EXPECT_EQ(1u, it2->size());
EXPECT_EQ(0, IntWrapper::destructor_calls_);
}
@@ -4080,42 +3956,13 @@ TEST_F(HeapTest, EmbeddedInVector) {
EXPECT_EQ(6, SimpleFinalizedObject::destructor_calls_);
}
-TEST_F(HeapTest, EmbeddedInDeque) {
- ClearOutOldGarbage();
- SimpleFinalizedObject::destructor_calls_ = 0;
- {
- Persistent<HeapDeque<VectorObject, 2>> inline_deque =
- MakeGarbageCollected<HeapDeque<VectorObject, 2>>();
- Persistent<HeapDeque<VectorObject>> outline_deque =
- MakeGarbageCollected<HeapDeque<VectorObject>>();
- VectorObject i1, i2;
- inline_deque->push_back(i1);
- inline_deque->push_back(i2);
-
- VectorObject o1, o2;
- outline_deque->push_back(o1);
- outline_deque->push_back(o2);
-
- Persistent<HeapDeque<VectorObjectInheritedTrace>> deque_inherited_trace =
- MakeGarbageCollected<HeapDeque<VectorObjectInheritedTrace>>();
- VectorObjectInheritedTrace it1, it2;
- deque_inherited_trace->push_back(it1);
- deque_inherited_trace->push_back(it2);
-
- PreciselyCollectGarbage();
- EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
- }
- PreciselyCollectGarbage();
- EXPECT_EQ(6, SimpleFinalizedObject::destructor_calls_);
-}
-
class InlinedVectorObject {
DISALLOW_NEW();
public:
InlinedVectorObject() = default;
~InlinedVectorObject() { destructor_calls_++; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static int destructor_calls_;
};
@@ -4129,7 +3976,7 @@ class InlinedVectorObjectWithVtable {
InlinedVectorObjectWithVtable() = default;
virtual ~InlinedVectorObjectWithVtable() { destructor_calls_++; }
virtual void VirtualMethod() {}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static int destructor_calls_;
};
@@ -4155,7 +4002,7 @@ class InlinedVectorObjectWrapper final
vector3_.push_back(i2);
}
- void Trace(blink::Visitor* visitor) {
+ void Trace(Visitor* visitor) {
visitor->Trace(vector1_);
visitor->Trace(vector2_);
visitor->Trace(vector3_);
@@ -4180,7 +4027,7 @@ class InlinedVectorObjectWithVtableWrapper final
vector3_.push_back(i2);
}
- void Trace(blink::Visitor* visitor) {
+ void Trace(Visitor* visitor) {
visitor->Trace(vector1_);
visitor->Trace(vector2_);
visitor->Trace(vector3_);
@@ -4298,34 +4145,6 @@ void RawPtrInHashHelper() {
}
}
-TEST_F(HeapTest, HeapLinkedStack) {
- ClearOutOldGarbage();
- IntWrapper::destructor_calls_ = 0;
-
- HeapLinkedStack<TerminatedArrayItem>* stack =
- MakeGarbageCollected<HeapLinkedStack<TerminatedArrayItem>>();
-
- const wtf_size_t kStackSize = 10;
-
- for (wtf_size_t i = 0; i < kStackSize; i++)
- stack->Push(TerminatedArrayItem(MakeGarbageCollected<IntWrapper>(i)));
-
- ConservativelyCollectGarbage();
- EXPECT_EQ(0, IntWrapper::destructor_calls_);
- EXPECT_EQ(kStackSize, stack->size());
- while (!stack->IsEmpty()) {
- EXPECT_EQ(stack->size() - 1,
- static_cast<size_t>(stack->Peek().Payload()->Value()));
- stack->Pop();
- }
-
- Persistent<HeapLinkedStack<TerminatedArrayItem>> p_stack = stack;
-
- PreciselyCollectGarbage();
- EXPECT_EQ(kStackSize, static_cast<size_t>(IntWrapper::destructor_calls_));
- EXPECT_EQ(0u, p_stack->size());
-}
-
TEST_F(HeapTest, AllocationDuringFinalization) {
ClearOutOldGarbage();
IntWrapper::destructor_calls_ = 0;
@@ -4430,7 +4249,7 @@ TEST_F(HeapTest, DestructorsCalled) {
class MixinA : public GarbageCollectedMixin {
public:
MixinA() : obj_(MakeGarbageCollected<IntWrapper>(100)) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
trace_count_++;
visitor->Trace(obj_);
}
@@ -4445,7 +4264,7 @@ int MixinA::trace_count_ = 0;
class MixinB : public GarbageCollectedMixin {
public:
MixinB() : obj_(MakeGarbageCollected<IntWrapper>(101)) {}
- void Trace(blink::Visitor* visitor) override { visitor->Trace(obj_); }
+ void Trace(Visitor* visitor) override { visitor->Trace(obj_); }
Member<IntWrapper> obj_;
};
@@ -4456,7 +4275,7 @@ class MultipleMixins : public GarbageCollected<MultipleMixins>,
public:
MultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(102)) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(obj_);
MixinA::Trace(visitor);
MixinB::Trace(visitor);
@@ -4468,7 +4287,7 @@ class DerivedMultipleMixins : public MultipleMixins {
public:
DerivedMultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(103)) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
trace_called_++;
visitor->Trace(obj_);
MultipleMixins::Trace(visitor);
@@ -4686,7 +4505,7 @@ TEST_F(HeapTest, EphemeronsInEphemerons) {
class EphemeronWrapper : public GarbageCollected<EphemeronWrapper> {
public:
- void Trace(blink::Visitor* visitor) { visitor->Trace(map_); }
+ void Trace(Visitor* visitor) { visitor->Trace(map_); }
typedef HeapHashMap<WeakMember<IntWrapper>, Member<EphemeronWrapper>> Map;
Map& GetMap() { return map_; }
@@ -4778,7 +4597,7 @@ class Link1 : public GarbageCollected<Link1> {
public:
Link1(IntWrapper* link) : link_(link) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(link_); }
+ void Trace(Visitor* visitor) { visitor->Trace(link_); }
IntWrapper* Link() { return link_; }
@@ -4820,9 +4639,7 @@ class TraceIfNeededTester final
TraceIfNeededTester() = default;
explicit TraceIfNeededTester(const T& obj) : obj_(obj) {}
- void Trace(blink::Visitor* visitor) {
- TraceIfNeeded<T>::Trace(visitor, obj_);
- }
+ void Trace(Visitor* visitor) { TraceIfNeeded<T>::Trace(visitor, obj_); }
T& Obj() { return obj_; }
~TraceIfNeededTester() = default;
@@ -4835,7 +4652,7 @@ class PartObject {
public:
PartObject() : obj_(MakeGarbageCollected<SimpleObject>()) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(obj_); }
+ void Trace(Visitor* visitor) { visitor->Trace(obj_); }
private:
Member<SimpleObject> obj_;
@@ -4864,7 +4681,7 @@ class AllocatesOnAssignment {
inline bool IsDeleted() const { return value_.IsHashTableDeletedValue(); }
- void Trace(blink::Visitor* visitor) { visitor->Trace(value_); }
+ void Trace(Visitor* visitor) { visitor->Trace(value_); }
int Value() { return value_->Value(); }
@@ -4940,14 +4757,14 @@ TEST_F(HeapTest, GCInHashMapOperations) {
class PartObjectWithVirtualMethod {
public:
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
};
class ObjectWithVirtualPartObject
: public GarbageCollected<ObjectWithVirtualPartObject> {
public:
ObjectWithVirtualPartObject() : dummy_(AllocateAndReturnBool()) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(part_); }
+ void Trace(Visitor* visitor) { visitor->Trace(part_); }
private:
bool dummy_;
@@ -4965,7 +4782,7 @@ class AllocInSuperConstructorArgumentSuper
public:
AllocInSuperConstructorArgumentSuper(bool value) : value_(value) {}
virtual ~AllocInSuperConstructorArgumentSuper() = default;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
bool Value() { return value_; }
private:
@@ -4995,7 +4812,7 @@ class NonNodeAllocatingNodeInDestructor final
node_ = new Persistent<IntNode>(IntNode::Create(10));
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
static Persistent<IntNode>* node_;
};
@@ -5014,7 +4831,7 @@ class DeepEagerly final : public GarbageCollected<DeepEagerly> {
public:
DeepEagerly(DeepEagerly* next) : next_(next) {}
- void Trace(blink::Visitor* visitor) {
+ void Trace(Visitor* visitor) {
int calls = ++s_trace_calls_;
if (s_trace_lazy_ <= 2)
visitor->Trace(next_);
@@ -5118,7 +4935,7 @@ class PartObjectWithRef {
public:
PartObjectWithRef(int i) : value_(SimpleRefValue::Create(i)) {}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
int Value() const { return value_->Value(); }
@@ -5132,68 +4949,6 @@ WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::PartObjectWithRef)
namespace blink {
-TEST_F(HeapTest, DequePartObjectsExpand) {
- // Test expansion of HeapDeque<PartObject>
-
- using PartDeque = HeapDeque<PartObjectWithRef>;
-
- Persistent<PartDeque> deque = MakeGarbageCollected<PartDeque>();
- // Auxillary Deque used to prevent 'inline' buffer expansion.
- Persistent<PartDeque> deque_unused = MakeGarbageCollected<PartDeque>();
-
- // Append a sequence, bringing about repeated expansions of the
- // deque's buffer.
- int i = 0;
- for (; i < 60; ++i) {
- deque->push_back(PartObjectWithRef(i));
- deque_unused->push_back(PartObjectWithRef(i));
- }
-
- EXPECT_EQ(60u, deque->size());
- i = 0;
- for (const PartObjectWithRef& part : *deque) {
- EXPECT_EQ(i, part.Value());
- i++;
- }
-
- // Remove most of the queued objects and have the buffer's start index
- // 'point' somewhere into the buffer, just behind the end index.
- for (i = 0; i < 50; ++i)
- deque->TakeFirst();
-
- EXPECT_EQ(10u, deque->size());
- i = 0;
- for (const PartObjectWithRef& part : *deque) {
- EXPECT_EQ(50 + i, part.Value());
- i++;
- }
-
- // Append even more, eventually causing an expansion of the underlying
- // buffer once the end index wraps around and reaches the start index.
- for (i = 0; i < 70; ++i)
- deque->push_back(PartObjectWithRef(60 + i));
-
- // Verify that the final buffer expansion copied the start and end segments
- // of the old buffer to both ends of the expanded buffer, along with
- // re-adjusting both start&end indices in terms of that expanded buffer.
- EXPECT_EQ(80u, deque->size());
- i = 0;
- for (const PartObjectWithRef& part : *deque) {
- EXPECT_EQ(i + 50, part.Value());
- i++;
- }
-
- for (i = 0; i < 70; ++i)
- deque->push_back(PartObjectWithRef(130 + i));
-
- EXPECT_EQ(150u, deque->size());
- i = 0;
- for (const PartObjectWithRef& part : *deque) {
- EXPECT_EQ(i + 50, part.Value());
- i++;
- }
-}
-
TEST_F(HeapTest, HeapVectorPartObjects) {
HeapVector<PartObjectWithRef> vector1;
HeapVector<PartObjectWithRef> vector2;
@@ -5234,7 +4989,7 @@ class TestMixinAllocationA : public GarbageCollected<TestMixinAllocationA>,
public:
TestMixinAllocationA() = default;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
class TestMixinAllocationB : public TestMixinAllocationA {
@@ -5245,7 +5000,7 @@ class TestMixinAllocationB : public TestMixinAllocationA {
// Construct object during a mixin construction.
: a_(MakeGarbageCollected<TestMixinAllocationA>()) {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(a_);
TestMixinAllocationA::Trace(visitor);
}
@@ -5260,7 +5015,7 @@ class TestMixinAllocationC final : public TestMixinAllocationB {
public:
TestMixinAllocationC() { DCHECK(!ThreadState::Current()->IsGCForbidden()); }
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
TestMixinAllocationB::Trace(visitor);
}
};
@@ -5368,7 +5123,7 @@ class ThreadedClearOnShutdownTester::HeapObject final
GetHeapObjectSet().insert(MakeGarbageCollected<HeapObject>(false));
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
bool test_destructor_;
@@ -5415,7 +5170,7 @@ class WithWeakConstObject final : public GarbageCollected<WithWeakConstObject> {
public:
WithWeakConstObject(const IntWrapper* int_wrapper) : wrapper_(int_wrapper) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(wrapper_); }
+ void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
const IntWrapper* Value() const { return wrapper_; }
@@ -5473,6 +5228,9 @@ TEST_F(HeapTest, IsGarbageCollected) {
static_assert(
WTF::IsGarbageCollectedType<HeapLinkedHashSet<Member<IntWrapper>>>::value,
"HeapLinkedHashSet");
+ static_assert(WTF::IsGarbageCollectedType<
+ HeapNewLinkedHashSet<Member<IntWrapper>>>::value,
+ "HeapNewLinkedHashSet");
static_assert(
WTF::IsGarbageCollectedType<HeapListHashSet<Member<IntWrapper>>>::value,
"HeapListHashSet");
@@ -5549,6 +5307,8 @@ TEST_F(HeapTest, GarbageCollectedMixinIsAliveDuringConstruction) {
using P = HeapVector<Member<HeapLinkedHashSet<Member<IntWrapper>>>>;
MakeGarbageCollected<P>();
+ using Q = HeapVector<Member<HeapNewLinkedHashSet<Member<IntWrapper>>>>;
+ MakeGarbageCollected<Q>();
}
TEST_F(HeapTest, PersistentAssignsDeletedValue) {
@@ -5602,7 +5362,8 @@ TEST_F(HeapTest, AccessDeletedBackingStore) {
}
BaseArena* map_arena = PageFromObject(map)->Arena();
// Sweep normal arena, but don't call finalizers.
- map_arena->ConcurrentSweepWithDeadline(base::TimeTicks::Max());
+ while (!map_arena->ConcurrentSweepOnePage()) {
+ }
// Now complete sweeping with PerformIdleLazySweep and call finalizers.
while (thread_state->IsSweepingInProgress()) {
thread_state->PerformIdleLazySweep(base::TimeTicks::Max());
@@ -5629,4 +5390,25 @@ TEST_F(HeapTest, CallMostDerivedFinalizer) {
EXPECT_EQ(1, GCDerived::destructor_called);
}
+#if defined(ADDRESS_SANITIZER)
+TEST(HeapDeathTest, DieOnPoisonedObjectHeaderAccess) {
+ auto* ptr = MakeGarbageCollected<IntWrapper>(1);
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(ptr);
+ auto* low = reinterpret_cast<uint16_t*>(header);
+ auto access = [low] {
+ volatile uint16_t half = WTF::AsAtomicPtr(low)->load();
+ WTF::AsAtomicPtr(low)->store(half);
+ };
+ EXPECT_DEATH(access(), "");
+}
+
+TEST_F(HeapTest, SuccessfulUnsanitizedAccessToObjectHeader) {
+ auto* ptr = MakeGarbageCollected<IntWrapper>(1);
+ HeapObjectHeader* header = HeapObjectHeader::FromPayload(ptr);
+ auto* low = reinterpret_cast<uint16_t*>(header);
+ volatile uint16_t half = internal::AsUnsanitizedAtomic(low)->load();
+ internal::AsUnsanitizedAtomic(low)->store(half);
+}
+#endif // ADDRESS_SANITIZER
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
index 3292be44245..2efb5e40779 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
@@ -11,11 +11,14 @@
namespace blink {
+std::atomic_int IntegerObject::destructor_calls{0};
+
// static
void TestSupportingGC::PreciselyCollectGarbage(
BlinkGC::SweepingType sweeping_type) {
ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, sweeping_type,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, sweeping_type,
BlinkGC::GCReason::kForcedGCForTesting);
}
@@ -23,10 +26,16 @@ void TestSupportingGC::PreciselyCollectGarbage(
void TestSupportingGC::ConservativelyCollectGarbage(
BlinkGC::SweepingType sweeping_type) {
ThreadState::Current()->CollectGarbage(
- BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking, sweeping_type,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, sweeping_type,
BlinkGC::GCReason::kForcedGCForTesting);
}
+TestSupportingGC::~TestSupportingGC() {
+ // Complete sweeping before |task_environment_| is destroyed.
+ CompleteSweepingIfNeeded();
+}
+
void TestSupportingGC::ClearOutOldGarbage() {
PreciselyCollectGarbage();
ThreadHeap& heap = ThreadState::Current()->Heap();
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h
index a9d37305606..a2a53e2e96e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h
@@ -29,6 +29,8 @@ class TestSupportingGC : public testing::Test {
static void ConservativelyCollectGarbage(
BlinkGC::SweepingType sweeping_type = BlinkGC::kEagerSweeping);
+ ~TestSupportingGC() override;
+
// Performs multiple rounds of garbage collections until no more memory can be
// freed. This is useful to avoid other garbage collections having to deal
// with stale memory.
@@ -171,7 +173,15 @@ class IncrementalMarkingTestDriver {
class IntegerObject : public GarbageCollected<IntegerObject> {
public:
- void Trace(blink::Visitor* visitor) {}
+ static std::atomic_int destructor_calls;
+
+ explicit IntegerObject(int x) : x_(x) {}
+
+ virtual ~IntegerObject() {
+ destructor_calls.fetch_add(1, std::memory_order_relaxed);
+ }
+
+ virtual void Trace(Visitor* visitor) {}
int Value() const { return x_; }
@@ -181,8 +191,6 @@ class IntegerObject : public GarbageCollected<IntegerObject> {
unsigned GetHash() { return IntHash<int>::GetHash(x_); }
- explicit IntegerObject(int x) : x_(x) {}
-
private:
int x_;
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc
index 80ef9b05470..c1fbe2d720b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc
@@ -17,7 +17,13 @@
namespace blink {
class HeapThreadTest : public TestSupportingGC {};
-class HeapThreadDeathTest : public TestSupportingGC {};
+
+class HeapThreadDeathTest : public TestSupportingGC {
+ public:
+ HeapThreadDeathTest() {
+ testing::FLAGS_gtest_death_test_style = "threadsafe";
+ }
+};
namespace heap_thread_test {
@@ -69,7 +75,7 @@ static void ParkWorkerThread() {
class Object : public GarbageCollected<Object> {
public:
Object() {}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
class AlternatingThreadTester {
@@ -136,14 +142,10 @@ class MemberSameThreadCheckTester : public AlternatingThreadTester {
};
#if DCHECK_IS_ON()
-// TODO(keishi) This test is flaky on mac-rel bot.
-// crbug.com/709069
-#if !defined(OS_MACOSX)
TEST_F(HeapThreadDeathTest, MemberSameThreadCheck) {
EXPECT_DEATH(MemberSameThreadCheckTester().Test(), "");
}
#endif
-#endif
class PersistentSameThreadCheckTester : public AlternatingThreadTester {
private:
@@ -159,20 +161,16 @@ class PersistentSameThreadCheckTester : public AlternatingThreadTester {
};
#if DCHECK_IS_ON()
-// TODO(keishi) This test is flaky on mac-rel bot.
-// crbug.com/709069
-#if !defined(OS_MACOSX)
TEST_F(HeapThreadDeathTest, PersistentSameThreadCheck) {
EXPECT_DEATH(PersistentSameThreadCheckTester().Test(), "");
}
#endif
-#endif
class MarkingSameThreadCheckTester : public AlternatingThreadTester {
private:
class MainThreadObject final : public GarbageCollected<MainThreadObject> {
public:
- void Trace(blink::Visitor* visitor) { visitor->Trace(set_); }
+ void Trace(Visitor* visitor) { visitor->Trace(set_); }
void AddToSet(Object* object) { set_.insert(42, object); }
private:
@@ -199,8 +197,6 @@ class MarkingSameThreadCheckTester : public AlternatingThreadTester {
};
#if DCHECK_IS_ON()
-// TODO(keishi) This test is flaky on mac-rel bot. https://crbug.com/709069, and
-// times out on other bots. https://crbug.com/993148.
TEST_F(HeapThreadDeathTest, DISABLED_MarkingSameThreadCheck) {
// This will crash during marking, at the DCHECK in Visitor::markHeader() or
// earlier.
@@ -215,7 +211,7 @@ class DestructorLockingObject
virtual ~DestructorLockingObject() { ++destructor_calls_; }
static int destructor_calls_;
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
int DestructorLockingObject::destructor_calls_ = 0;
@@ -254,8 +250,9 @@ class CrossThreadWeakPersistentTester : public AlternatingThreadTester {
// Step 4: Run a GC.
ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting);
+ BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
+ BlinkGC::GCReason::kForcedGCForTesting);
SwitchToMainThread();
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_traits_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_traits_test.cc
index 539c26c3757..2e50a064992 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_traits_test.cc
@@ -22,12 +22,12 @@ struct Empty {};
// Similar to an IDL union or dictionary, which have Trace() methods but are
// not garbage-collected types themselves.
struct StructWithTraceMethod {
- void Trace(blink::Visitor*) {}
+ void Trace(Visitor*) {}
};
struct GarbageCollectedStruct
: public GarbageCollected<GarbageCollectedStruct> {
- void Trace(blink::Visitor*) {}
+ void Trace(Visitor*) {}
};
// AddMemberIfNeeded<T>
diff --git a/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index c3725ad1524..5132cc58f40 100644
--- a/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -39,12 +39,11 @@ class BackingVisitor : public Visitor {
void ProcessBackingStore(HeapObjectHeader* header) {
EXPECT_TRUE(header->IsMarked());
header->Unmark();
- GCInfoTable::Get()
- .GCInfoFromIndex(header->GcInfoIndex())
- ->trace(this, header->Payload());
+
+ GCInfo::From(header->GcInfoIndex()).trace(this, header->Payload());
}
- void Visit(void* obj, TraceDescriptor desc) final {
+ void Visit(const void* obj, TraceDescriptor desc) final {
EXPECT_TRUE(obj);
auto** pos = std::find(objects_->begin(), objects_->end(), obj);
if (objects_->end() != pos)
@@ -53,12 +52,12 @@ class BackingVisitor : public Visitor {
HeapObjectHeader* const header =
HeapObjectHeader::FromPayload(desc.base_object_payload);
if (!header->IsMarked())
- header->Mark();
+ EXPECT_TRUE(header->TryMark());
}
bool VisitEphemeronKeyValuePair(
- void* key,
- void* value,
+ const void* key,
+ const void* value,
EphemeronTracingCallback key_trace_callback,
EphemeronTracingCallback value_trace_callback) final {
const bool key_is_dead = key_trace_callback(this, key);
@@ -70,22 +69,23 @@ class BackingVisitor : public Visitor {
}
// Unused overrides.
- void VisitWeak(void* object,
- void* object_weak_ref,
+ void VisitWeak(const void* object,
+ const void* object_weak_ref,
TraceDescriptor desc,
WeakCallback callback) final {}
- void VisitBackingStoreStrongly(void* object,
- void** object_slot,
+ void VisitBackingStoreStrongly(const void* object,
+ const void* const* object_slot,
TraceDescriptor desc) final {}
- void VisitBackingStoreWeakly(void*,
- void**,
+ void VisitBackingStoreWeakly(const void*,
+ const void* const*,
TraceDescriptor,
TraceDescriptor,
WeakCallback,
- void*) final {}
- void VisitBackingStoreOnly(void*, void**) final {}
- void RegisterBackingStoreCallback(void* slot, MovingObjectCallback) final {}
- void RegisterWeakCallback(WeakCallback, void*) final {}
+ const void*) final {}
+ void VisitBackingStoreOnly(const void*, const void* const*) final {}
+ void RegisterBackingStoreCallback(const void* slot,
+ MovingObjectCallback) final {}
+ void RegisterWeakCallback(WeakCallback, const void*) final {}
void Visit(const TraceWrapperV8Reference<v8::Value>&) final {}
private:
@@ -103,7 +103,7 @@ class IncrementalMarkingScopeBase {
thread_state_->IsSweepingInProgress()) {
TestSupportingGC::PreciselyCollectGarbage();
}
- heap_.SetupWorklists();
+ heap_.SetupWorklists(false);
}
~IncrementalMarkingScopeBase() {
@@ -280,6 +280,20 @@ class Object : public LinkedObject {
void Trace(Visitor* visitor) { LinkedObject::Trace(visitor); }
};
+class RawPtrObjectWithManualWriteBarrier
+ : public GarbageCollected<RawPtrObjectWithManualWriteBarrier> {
+ public:
+ void Trace(Visitor* v) { v->Trace(object_); }
+
+ void Set(Object* object) {
+ object_ = object;
+ MarkingVisitor::WriteBarrier(&object_);
+ }
+
+ private:
+ Object* object_ = nullptr;
+};
+
// =============================================================================
// Basic infrastructure support. ===============================================
// =============================================================================
@@ -294,20 +308,22 @@ TEST_F(IncrementalMarkingTest, EnableDisableBarrier) {
}
TEST_F(IncrementalMarkingTest, ManualWriteBarrierTriggersWhenMarkingIsOn) {
- auto* object = MakeGarbageCollected<Object>();
+ auto* object1 = MakeGarbageCollected<Object>();
+ auto* object2 = MakeGarbageCollected<RawPtrObjectWithManualWriteBarrier>();
{
- ExpectWriteBarrierFires scope(ThreadState::Current(), {object});
- EXPECT_FALSE(object->IsMarked());
- MarkingVisitor::WriteBarrier(object);
- EXPECT_TRUE(object->IsMarked());
+ ExpectWriteBarrierFires scope(ThreadState::Current(), {object1});
+ EXPECT_FALSE(object1->IsMarked());
+ object2->Set(object1);
+ EXPECT_TRUE(object1->IsMarked());
}
}
TEST_F(IncrementalMarkingTest, ManualWriteBarrierBailoutWhenMarkingIsOff) {
- auto* object = MakeGarbageCollected<Object>();
- EXPECT_FALSE(object->IsMarked());
- MarkingVisitor::WriteBarrier(object);
- EXPECT_FALSE(object->IsMarked());
+ auto* object1 = MakeGarbageCollected<Object>();
+ auto* object2 = MakeGarbageCollected<RawPtrObjectWithManualWriteBarrier>();
+ EXPECT_FALSE(object1->IsMarked());
+ object2->Set(object1);
+ EXPECT_FALSE(object1->IsMarked());
}
// =============================================================================
@@ -328,7 +344,7 @@ TEST_F(IncrementalMarkingTest, MemberSetUnmarkedObject) {
TEST_F(IncrementalMarkingTest, MemberSetMarkedObjectNoBarrier) {
auto* parent = MakeGarbageCollected<Object>();
auto* child = MakeGarbageCollected<Object>();
- HeapObjectHeader::FromPayload(child)->Mark();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(child)->TryMark());
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {child});
parent->set_next(child);
@@ -349,10 +365,10 @@ TEST_F(IncrementalMarkingTest, MemberInitializingStoreNoBarrier) {
}
TEST_F(IncrementalMarkingTest, MemberReferenceAssignMember) {
- auto* obj = MakeGarbageCollected<Object>();
- Member<Object> m1;
- Member<Object>& m2 = m1;
- Member<Object> m3(obj);
+ auto* obj = MakeGarbageCollected<LinkedObject>();
+ auto* ref_obj = MakeGarbageCollected<LinkedObject>();
+ Member<LinkedObject>& m2 = ref_obj->next_ref();
+ Member<LinkedObject> m3(obj);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
m2 = m3;
@@ -360,7 +376,8 @@ TEST_F(IncrementalMarkingTest, MemberReferenceAssignMember) {
}
TEST_F(IncrementalMarkingTest, MemberSetDeletedValueNoBarrier) {
- Member<Object> m;
+ auto* obj = MakeGarbageCollected<LinkedObject>();
+ Member<LinkedObject>& m = obj->next_ref();
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {});
m = WTF::kHashTableDeletedValue;
@@ -368,26 +385,32 @@ TEST_F(IncrementalMarkingTest, MemberSetDeletedValueNoBarrier) {
}
TEST_F(IncrementalMarkingTest, MemberCopyDeletedValueNoBarrier) {
- Member<Object> m1(WTF::kHashTableDeletedValue);
+ auto* obj1 = MakeGarbageCollected<LinkedObject>();
+ Member<LinkedObject>& m1 = obj1->next_ref();
+ m1 = WTF::kHashTableDeletedValue;
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {});
- Member<Object> m2(m1);
+ auto* obj2 = MakeGarbageCollected<LinkedObject>();
+ obj2->next_ref() = m1;
}
}
TEST_F(IncrementalMarkingTest, MemberHashTraitConstructDeletedValueNoBarrier) {
- Member<Object> m1;
+ auto* obj = MakeGarbageCollected<LinkedObject>();
+ Member<LinkedObject>& m = obj->next_ref();
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {});
- HashTraits<Member<Object>>::ConstructDeletedValue(m1, false);
+ HashTraits<Member<LinkedObject>>::ConstructDeletedValue(m, false);
}
}
TEST_F(IncrementalMarkingTest, MemberHashTraitIsDeletedValueNoBarrier) {
- Member<Object> m1(MakeGarbageCollected<Object>());
+ auto* obj =
+ MakeGarbageCollected<LinkedObject>(MakeGarbageCollected<LinkedObject>());
+ Member<LinkedObject>& m = obj->next_ref();
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {});
- EXPECT_FALSE(HashTraits<Member<Object>>::IsDeletedValue(m1));
+ EXPECT_FALSE(HashTraits<Member<LinkedObject>>::IsDeletedValue(m));
}
}
@@ -402,7 +425,7 @@ class Mixin : public GarbageCollectedMixin {
Mixin() : next_(nullptr) {}
virtual ~Mixin() {}
- void Trace(blink::Visitor* visitor) override { visitor->Trace(next_); }
+ void Trace(Visitor* visitor) override { visitor->Trace(next_); }
virtual void Bar() {}
@@ -424,7 +447,7 @@ class Child : public GarbageCollected<Child>,
Child() : ClassWithVirtual(), Mixin() {}
~Child() override {}
- void Trace(blink::Visitor* visitor) override { Mixin::Trace(visitor); }
+ void Trace(Visitor* visitor) override { Mixin::Trace(visitor); }
void Foo() override {}
void Bar() override {}
@@ -436,7 +459,7 @@ class ParentWithMixinPointer : public GarbageCollected<ParentWithMixinPointer> {
void set_mixin(Mixin* mixin) { mixin_ = mixin; }
- virtual void Trace(blink::Visitor* visitor) { visitor->Trace(mixin_); }
+ virtual void Trace(Visitor* visitor) { visitor->Trace(mixin_); }
protected:
Member<Mixin> mixin_;
@@ -460,7 +483,7 @@ TEST_F(IncrementalMarkingTest, NoWriteBarrierOnMarkedMixinApplication) {
ParentWithMixinPointer* parent =
MakeGarbageCollected<ParentWithMixinPointer>();
auto* child = MakeGarbageCollected<Child>();
- HeapObjectHeader::FromPayload(child)->Mark();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(child)->TryMark());
Mixin* mixin = static_cast<Mixin*>(child);
EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin));
{
@@ -484,7 +507,7 @@ class NonGarbageCollectedContainer {
NonGarbageCollectedContainer(Object* obj, int y) : obj_(obj), y_(y) {}
virtual ~NonGarbageCollectedContainer() {}
- virtual void Trace(blink::Visitor* visitor) { visitor->Trace(obj_); }
+ virtual void Trace(Visitor* visitor) { visitor->Trace(obj_); }
private:
Member<Object> obj_;
@@ -499,7 +522,7 @@ class NonGarbageCollectedContainerRoot {
: next_(obj1, y), obj_(obj2) {}
virtual ~NonGarbageCollectedContainerRoot() {}
- virtual void Trace(blink::Visitor* visitor) {
+ virtual void Trace(Visitor* visitor) {
visitor->Trace(next_);
visitor->Trace(obj_);
}
@@ -513,158 +536,168 @@ class NonGarbageCollectedContainerRoot {
TEST_F(IncrementalMarkingTest, HeapVectorPushBackMember) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<Member<Object>> vec;
+ auto* vec = MakeGarbageCollected<HeapVector<Member<Object>>>();
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- vec.push_back(obj);
+ vec->push_back(obj);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorPushBackNonGCedContainer) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<NonGarbageCollectedContainer> vec;
+ auto* vec = MakeGarbageCollected<HeapVector<NonGarbageCollectedContainer>>();
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- vec.push_back(NonGarbageCollectedContainer(obj, 1));
+ vec->push_back(NonGarbageCollectedContainer(obj, 1));
}
}
TEST_F(IncrementalMarkingTest, HeapVectorPushBackStdPair) {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec;
+ auto* vec = MakeGarbageCollected<
+ HeapVector<std::pair<Member<Object>, Member<Object>>>>();
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- vec.push_back(std::make_pair(Member<Object>(obj1), Member<Object>(obj2)));
+ vec->push_back(std::make_pair(Member<Object>(obj1), Member<Object>(obj2)));
}
}
TEST_F(IncrementalMarkingTest, HeapVectorEmplaceBackMember) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<Member<Object>> vec;
+ auto* vec = MakeGarbageCollected<HeapVector<Member<Object>>>();
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- vec.emplace_back(obj);
+ vec->emplace_back(obj);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorEmplaceBackNonGCedContainer) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<NonGarbageCollectedContainer> vec;
+ auto* vec = MakeGarbageCollected<HeapVector<NonGarbageCollectedContainer>>();
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- vec.emplace_back(obj, 1);
+ vec->emplace_back(obj, 1);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorEmplaceBackStdPair) {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec;
+ auto* vec = MakeGarbageCollected<
+ HeapVector<std::pair<Member<Object>, Member<Object>>>>();
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- vec.emplace_back(obj1, obj2);
+ vec->emplace_back(obj1, obj2);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorCopyMember) {
auto* object = MakeGarbageCollected<Object>();
- HeapVector<Member<Object>> vec1;
- vec1.push_back(object);
+ auto* vec1 = MakeGarbageCollected<HeapVector<Member<Object>>>();
+ vec1->push_back(object);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {object});
- HeapVector<Member<Object>> vec2(vec1);
+ MakeGarbageCollected<HeapVector<Member<Object>>>(*vec1);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorCopyNonGCedContainer) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<NonGarbageCollectedContainer> vec1;
- vec1.emplace_back(obj, 1);
+ auto* vec1 = MakeGarbageCollected<HeapVector<NonGarbageCollectedContainer>>();
+ vec1->emplace_back(obj, 1);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- HeapVector<NonGarbageCollectedContainer> vec2(vec1);
+ MakeGarbageCollected<HeapVector<NonGarbageCollectedContainer>>(*vec1);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorCopyStdPair) {
+ using ValueType = std::pair<Member<Object>, Member<Object>>;
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec1;
- vec1.emplace_back(obj1, obj2);
+ auto* vec1 = MakeGarbageCollected<HeapVector<ValueType>>();
+ vec1->emplace_back(obj1, obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec2(vec1);
+ MakeGarbageCollected<HeapVector<ValueType>>(*vec1);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorMoveMember) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<Member<Object>> vec1;
- vec1.push_back(obj);
+ auto* vec1 = MakeGarbageCollected<HeapVector<Member<Object>>>();
+ vec1->push_back(obj);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- HeapVector<Member<Object>> vec2(std::move(vec1));
+ MakeGarbageCollected<HeapVector<Member<Object>>>(std::move(*vec1));
}
}
TEST_F(IncrementalMarkingTest, HeapVectorMoveNonGCedContainer) {
auto* obj = MakeGarbageCollected<Object>();
- HeapVector<NonGarbageCollectedContainer> vec1;
- vec1.emplace_back(obj, 1);
+ auto* vec1 = MakeGarbageCollected<HeapVector<NonGarbageCollectedContainer>>();
+ vec1->emplace_back(obj, 1);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- HeapVector<NonGarbageCollectedContainer> vec2(std::move(vec1));
+ MakeGarbageCollected<HeapVector<NonGarbageCollectedContainer>>(
+ std::move(*vec1));
}
}
TEST_F(IncrementalMarkingTest, HeapVectorMoveStdPair) {
+ using ValueType = std::pair<Member<Object>, Member<Object>>;
+ using VectorType = HeapVector<ValueType>;
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec1;
- vec1.emplace_back(obj1, obj2);
+ auto* vec1 = MakeGarbageCollected<VectorType>();
+ vec1->emplace_back(obj1, obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec2(std::move(vec1));
+ MakeGarbageCollected<VectorType>(std::move(*vec1));
}
}
TEST_F(IncrementalMarkingTest, HeapVectorSwapMember) {
+ using VectorType = HeapVector<Member<Object>>;
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<Member<Object>> vec1;
- vec1.push_back(obj1);
- HeapVector<Member<Object>> vec2;
- vec2.push_back(obj2);
+ auto* vec1 = MakeGarbageCollected<VectorType>();
+ vec1->push_back(obj1);
+ auto* vec2 = MakeGarbageCollected<VectorType>();
+ vec2->push_back(obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- std::swap(vec1, vec2);
+ std::swap(*vec1, *vec2);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorSwapNonGCedContainer) {
+ using VectorType = HeapVector<NonGarbageCollectedContainer>;
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<NonGarbageCollectedContainer> vec1;
- vec1.emplace_back(obj1, 1);
- HeapVector<NonGarbageCollectedContainer> vec2;
- vec2.emplace_back(obj2, 2);
+ auto* vec1 = MakeGarbageCollected<VectorType>();
+ vec1->emplace_back(obj1, 1);
+ auto* vec2 = MakeGarbageCollected<VectorType>();
+ vec2->emplace_back(obj2, 2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- std::swap(vec1, vec2);
+ std::swap(*vec1, *vec2);
}
}
TEST_F(IncrementalMarkingTest, HeapVectorSwapStdPair) {
+ using ValueType = std::pair<Member<Object>, Member<Object>>;
+ using VectorType = HeapVector<ValueType>;
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec1;
- vec1.emplace_back(obj1, nullptr);
- HeapVector<std::pair<Member<Object>, Member<Object>>> vec2;
- vec2.emplace_back(nullptr, obj2);
+ auto* vec1 = MakeGarbageCollected<VectorType>();
+ vec1->emplace_back(obj1, nullptr);
+ auto* vec2 = MakeGarbageCollected<VectorType>();
+ vec2->emplace_back(nullptr, obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- std::swap(vec1, vec2);
+ std::swap(*vec1, *vec2);
}
}
@@ -826,23 +859,23 @@ void CopyNoBarrier() {
template <typename Container>
void Move() {
auto* obj = MakeGarbageCollected<Object>();
- Container container1;
- Container container2;
- container1.insert(obj);
+ auto* container1 = MakeGarbageCollected<Container>();
+ auto* container2 = MakeGarbageCollected<Container>();
+ container1->insert(obj);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- container2 = std::move(container1);
+ *container2 = std::move(*container1);
}
}
template <typename Container>
void MoveNoBarrier() {
auto* obj = MakeGarbageCollected<Object>();
- Container container1;
- container1.insert(obj);
+ auto* container1 = MakeGarbageCollected<Container>();
+ container1->insert(obj);
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {obj});
- Container container2(std::move(container1));
+ auto* container2 = MakeGarbageCollected<Container>(std::move(*container1));
}
}
@@ -850,13 +883,13 @@ template <typename Container>
void Swap() {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- Container container1;
- container1.insert(obj1);
- Container container2;
- container2.insert(obj2);
+ auto* container1 = MakeGarbageCollected<Container>();
+ container1->insert(obj1);
+ auto* container2 = MakeGarbageCollected<Container>();
+ container2->insert(obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- std::swap(container1, container2);
+ std::swap(*container1, *container2);
}
}
@@ -864,13 +897,13 @@ template <typename Container>
void SwapNoBarrier() {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- Container container1;
- container1.insert(obj1);
- Container container2;
- container2.insert(obj2);
+ auto* container1 = MakeGarbageCollected<Container>();
+ container1->insert(obj1);
+ auto* container2 = MakeGarbageCollected<Container>();
+ container2->insert(obj2);
{
ExpectNoWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- std::swap(container1, container2);
+ std::swap(*container1, *container2);
}
}
@@ -928,6 +961,9 @@ TEST_F(IncrementalMarkingTest, HeapLinkedHashSetSwap) {
Swap<HeapLinkedHashSet<WeakMember<Object>>>();
}
+// TODO(keinakashima): add tests for NewLinkedHashSet after supporting
+// WeakMember
+
// =============================================================================
// HeapHashCountedSet support. =================================================
// =============================================================================
@@ -945,26 +981,30 @@ TEST_F(IncrementalMarkingTest, HeapHashCountedSetSwap) {
{
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapHashCountedSet<Member<Object>> container1;
- container1.insert(obj1);
- HeapHashCountedSet<Member<Object>> container2;
- container2.insert(obj2);
+ auto* container1 =
+ MakeGarbageCollected<HeapHashCountedSet<Member<Object>>>();
+ container1->insert(obj1);
+ auto* container2 =
+ MakeGarbageCollected<HeapHashCountedSet<Member<Object>>>();
+ container2->insert(obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- container1.swap(container2);
+ container1->swap(*container2);
}
}
{
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapHashCountedSet<WeakMember<Object>> container1;
- container1.insert(obj1);
- HeapHashCountedSet<WeakMember<Object>> container2;
- container2.insert(obj2);
+ auto* container1 =
+ MakeGarbageCollected<HeapHashCountedSet<WeakMember<Object>>>();
+ container1->insert(obj1);
+ auto* container2 =
+ MakeGarbageCollected<HeapHashCountedSet<WeakMember<Object>>>();
+ container2->insert(obj2);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- container1.swap(container2);
+ container1->swap(*container2);
}
}
}
@@ -1132,47 +1172,55 @@ TEST_F(IncrementalMarkingTest, HeapHashMapCopyWeakMemberMember) {
TEST_F(IncrementalMarkingTest, HeapHashMapMoveMember) {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapHashMap<Member<Object>, Member<Object>> map1;
- map1.insert(obj1, obj2);
+ auto* map1 =
+ MakeGarbageCollected<HeapHashMap<Member<Object>, Member<Object>>>();
+ map1->insert(obj1, obj2);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- HeapHashMap<Member<Object>, Member<Object>> map2(std::move(map1));
+ MakeGarbageCollected<HeapHashMap<Member<Object>, Member<Object>>>(
+ std::move(*map1));
}
}
TEST_F(IncrementalMarkingTest, HeapHashMapMoveWeakMember) {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapHashMap<WeakMember<Object>, WeakMember<Object>> map1;
- map1.insert(obj1, obj2);
+ auto* map1 = MakeGarbageCollected<
+ HeapHashMap<WeakMember<Object>, WeakMember<Object>>>();
+ map1->insert(obj1, obj2);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- HeapHashMap<WeakMember<Object>, WeakMember<Object>> map2(std::move(map1));
+ MakeGarbageCollected<HeapHashMap<WeakMember<Object>, WeakMember<Object>>>(
+ std::move(*map1));
}
}
TEST_F(IncrementalMarkingTest, HeapHashMapMoveMemberWeakMember) {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapHashMap<Member<Object>, WeakMember<Object>> map1;
- map1.insert(obj1, obj2);
+ auto* map1 =
+ MakeGarbageCollected<HeapHashMap<Member<Object>, WeakMember<Object>>>();
+ map1->insert(obj1, obj2);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- HeapHashMap<Member<Object>, WeakMember<Object>> map2(std::move(map1));
+ MakeGarbageCollected<HeapHashMap<Member<Object>, WeakMember<Object>>>(
+ std::move(*map1));
}
}
TEST_F(IncrementalMarkingTest, HeapHashMapMoveWeakMemberMember) {
auto* obj1 = MakeGarbageCollected<Object>();
auto* obj2 = MakeGarbageCollected<Object>();
- HeapHashMap<WeakMember<Object>, Member<Object>> map1;
- map1.insert(obj1, obj2);
+ auto* map1 =
+ MakeGarbageCollected<HeapHashMap<WeakMember<Object>, Member<Object>>>();
+ map1->insert(obj1, obj2);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2});
- HeapHashMap<WeakMember<Object>, Member<Object>> map2(std::move(map1));
+ MakeGarbageCollected<HeapHashMap<WeakMember<Object>, Member<Object>>>(
+ std::move(*map1));
}
}
@@ -1181,14 +1229,16 @@ TEST_F(IncrementalMarkingTest, HeapHashMapSwapMemberMember) {
auto* obj2 = MakeGarbageCollected<Object>();
auto* obj3 = MakeGarbageCollected<Object>();
auto* obj4 = MakeGarbageCollected<Object>();
- HeapHashMap<Member<Object>, Member<Object>> map1;
- map1.insert(obj1, obj2);
- HeapHashMap<Member<Object>, Member<Object>> map2;
- map2.insert(obj3, obj4);
+ auto* map1 =
+ MakeGarbageCollected<HeapHashMap<Member<Object>, Member<Object>>>();
+ map1->insert(obj1, obj2);
+ auto* map2 =
+ MakeGarbageCollected<HeapHashMap<Member<Object>, Member<Object>>>();
+ map2->insert(obj3, obj4);
{
ExpectWriteBarrierFires scope(ThreadState::Current(),
{obj1, obj2, obj3, obj4});
- std::swap(map1, map2);
+ std::swap(*map1, *map2);
}
}
@@ -1197,15 +1247,17 @@ TEST_F(IncrementalMarkingTest, HeapHashMapSwapWeakMemberWeakMember) {
auto* obj2 = MakeGarbageCollected<Object>();
auto* obj3 = MakeGarbageCollected<Object>();
auto* obj4 = MakeGarbageCollected<Object>();
- HeapHashMap<WeakMember<Object>, WeakMember<Object>> map1;
- map1.insert(obj1, obj2);
- HeapHashMap<WeakMember<Object>, WeakMember<Object>> map2;
- map2.insert(obj3, obj4);
+ auto* map1 = MakeGarbageCollected<
+ HeapHashMap<WeakMember<Object>, WeakMember<Object>>>();
+ map1->insert(obj1, obj2);
+ auto* map2 = MakeGarbageCollected<
+ HeapHashMap<WeakMember<Object>, WeakMember<Object>>>();
+ map2->insert(obj3, obj4);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(),
{obj1, obj2, obj3, obj4});
- std::swap(map1, map2);
+ std::swap(*map1, *map2);
}
}
@@ -1214,15 +1266,17 @@ TEST_F(IncrementalMarkingTest, HeapHashMapSwapMemberWeakMember) {
auto* obj2 = MakeGarbageCollected<Object>();
auto* obj3 = MakeGarbageCollected<Object>();
auto* obj4 = MakeGarbageCollected<Object>();
- HeapHashMap<Member<Object>, WeakMember<Object>> map1;
- map1.insert(obj1, obj2);
- HeapHashMap<Member<Object>, WeakMember<Object>> map2;
- map2.insert(obj3, obj4);
+ auto* map1 =
+ MakeGarbageCollected<HeapHashMap<Member<Object>, WeakMember<Object>>>();
+ map1->insert(obj1, obj2);
+ auto* map2 =
+ MakeGarbageCollected<HeapHashMap<Member<Object>, WeakMember<Object>>>();
+ map2->insert(obj3, obj4);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(),
{obj1, obj2, obj3, obj4});
- std::swap(map1, map2);
+ std::swap(*map1, *map2);
}
}
@@ -1231,15 +1285,17 @@ TEST_F(IncrementalMarkingTest, HeapHashMapSwapWeakMemberMember) {
auto* obj2 = MakeGarbageCollected<Object>();
auto* obj3 = MakeGarbageCollected<Object>();
auto* obj4 = MakeGarbageCollected<Object>();
- HeapHashMap<WeakMember<Object>, Member<Object>> map1;
- map1.insert(obj1, obj2);
- HeapHashMap<WeakMember<Object>, Member<Object>> map2;
- map2.insert(obj3, obj4);
+ auto* map1 =
+ MakeGarbageCollected<HeapHashMap<WeakMember<Object>, Member<Object>>>();
+ map1->insert(obj1, obj2);
+ auto* map2 =
+ MakeGarbageCollected<HeapHashMap<WeakMember<Object>, Member<Object>>>();
+ map2->insert(obj3, obj4);
{
// Weak references are strongified for the current cycle.
ExpectWriteBarrierFires scope(ThreadState::Current(),
{obj1, obj2, obj3, obj4});
- std::swap(map1, map2);
+ std::swap(*map1, *map2);
}
}
@@ -1415,57 +1471,21 @@ TEST_F(IncrementalMarkingTest, DropBackingStore) {
driver.FinishGC();
}
-TEST_F(IncrementalMarkingTest, WeakCallbackDoesNotReviveDeletedValue) {
- // Regression test: https://crbug.com/870196
-
- // std::pair avoids treating the hashset backing as weak backing.
- using WeakStore = HeapHashCountedSet<std::pair<WeakMember<Object>, size_t>>;
-
- Persistent<WeakStore> persistent(MakeGarbageCollected<WeakStore>());
- // Create at least two entries to avoid completely emptying out the data
- // structure. The values for .second are chosen to be non-null as they
- // would otherwise count as empty and be skipped during iteration after the
- // first part died.
- persistent->insert({MakeGarbageCollected<Object>(), 1});
- persistent->insert({MakeGarbageCollected<Object>(), 2});
- IncrementalMarkingTestDriver driver(ThreadState::Current());
- driver.Start();
- // The backing is not treated as weak backing and thus eagerly processed,
- // effectively registering the slots of WeakMembers.
- driver.FinishSteps();
- // The following deletes the first found entry. The second entry is left
- // untouched.
- for (auto& entries : *persistent) {
- persistent->erase(entries.key);
- break;
- }
- driver.FinishGC();
-
- size_t count = 0;
- for (const auto& entry : *persistent) {
- count++;
- // Use the entry to keep compilers happy.
- if (entry.key.second > 0) {
- }
- }
- CHECK_EQ(1u, count);
-}
-
TEST_F(IncrementalMarkingTest, NoBackingFreeDuringIncrementalMarking) {
// Regression test: https://crbug.com/870306
// Only reproduces in ASAN configurations.
- using WeakStore = HeapHashCountedSet<std::pair<WeakMember<Object>, size_t>>;
+ using WeakStore = HeapHashCountedSet<WeakMember<Object>>;
Persistent<WeakStore> persistent(MakeGarbageCollected<WeakStore>());
- // Prefill the collection to grow backing store. A new backing store allocaton
- // would trigger the write barrier, mitigating the bug where a backing store
- // is promptly freed.
+ // Prefill the collection to grow backing store. A new backing store
+ // allocationwould trigger the write barrier, mitigating the bug where
+ // a backing store is promptly freed.
for (size_t i = 0; i < 8; i++) {
- persistent->insert({MakeGarbageCollected<Object>(), i});
+ persistent->insert(MakeGarbageCollected<Object>());
}
IncrementalMarkingTestDriver driver(ThreadState::Current());
driver.Start();
- persistent->insert({MakeGarbageCollected<Object>(), 8});
+ persistent->insert(MakeGarbageCollected<Object>());
// Is not allowed to free the backing store as the previous insert may have
// registered a slot.
persistent->clear();
@@ -1536,8 +1556,9 @@ TEST_F(IncrementalMarkingTest, ConservativeGCWhileCompactionScheduled) {
driver.Start();
driver.FinishSteps();
ThreadState::Current()->CollectGarbage(
- BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping, BlinkGC::GCReason::kConservativeGC);
+ BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
+ BlinkGC::GCReason::kConservativeGC);
// Heap compaction should be canceled if incremental marking finishes with a
// conservative GC.
@@ -1792,11 +1813,12 @@ class Destructed final : public GarbageCollected<Destructed> {
size_t Destructed::n_destructed = 0;
-class Wrapper final : public GarbageCollected<Wrapper> {
+class LinkedHashSetWrapper final
+ : public GarbageCollected<LinkedHashSetWrapper> {
public:
using HashType = HeapLinkedHashSet<Member<Destructed>>;
- Wrapper() {
+ LinkedHashSetWrapper() {
for (size_t i = 0; i < 10; ++i) {
hash_set_.insert(MakeGarbageCollected<Destructed>());
}
@@ -1812,7 +1834,7 @@ class Wrapper final : public GarbageCollected<Wrapper> {
HashType hash_set_;
};
-TEST_F(IncrementalMarkingTest, MovingCallback) {
+TEST_F(IncrementalMarkingTest, LinkedHashSetMovingCallback) {
ClearOutOldGarbage();
Destructed::n_destructed = 0;
@@ -1820,14 +1842,15 @@ TEST_F(IncrementalMarkingTest, MovingCallback) {
HeapHashSet<Member<Destructed>> to_be_destroyed;
to_be_destroyed.ReserveCapacityForSize(100);
}
- Persistent<Wrapper> wrapper = MakeGarbageCollected<Wrapper>();
+ Persistent<LinkedHashSetWrapper> wrapper =
+ MakeGarbageCollected<LinkedHashSetWrapper>();
IncrementalMarkingTestDriver driver(ThreadState::Current());
ThreadState::Current()->EnableCompactionForNextGCForTesting();
driver.Start();
driver.FinishSteps();
- // Destroy the link between original HeapLinkedHashSet object and its backign
+ // Destroy the link between original HeapLinkedHashSet object and its backing
// store.
wrapper->Swap();
DCHECK(wrapper->hash_set_.IsEmpty());
@@ -1837,5 +1860,52 @@ TEST_F(IncrementalMarkingTest, MovingCallback) {
EXPECT_EQ(10u, Destructed::n_destructed);
}
+class NewLinkedHashSetWrapper final
+ : public GarbageCollected<NewLinkedHashSetWrapper> {
+ public:
+ using HashType = HeapNewLinkedHashSet<Member<Destructed>>;
+
+ NewLinkedHashSetWrapper() {
+ for (size_t i = 0; i < 10; ++i) {
+ hash_set_.insert(MakeGarbageCollected<Destructed>());
+ }
+ }
+
+ void Trace(Visitor* v) { v->Trace(hash_set_); }
+
+ void Swap() {
+ HashType hash_set;
+ hash_set_.Swap(hash_set);
+ }
+
+ HashType hash_set_;
+};
+
+TEST_F(IncrementalMarkingTest, NewLinkedHashSetMovingCallback) {
+ ClearOutOldGarbage();
+
+ Destructed::n_destructed = 0;
+ {
+ HeapHashSet<Member<Destructed>> to_be_destroyed;
+ to_be_destroyed.ReserveCapacityForSize(100);
+ }
+ Persistent<NewLinkedHashSetWrapper> wrapper =
+ MakeGarbageCollected<NewLinkedHashSetWrapper>();
+
+ IncrementalMarkingTestDriver driver(ThreadState::Current());
+ ThreadState::Current()->EnableCompactionForNextGCForTesting();
+ driver.Start();
+ driver.FinishSteps();
+
+ // Destroy the link between original NewHeapLinkedHashSet object and its
+ // backing store.
+ wrapper->Swap();
+ DCHECK(wrapper->hash_set_.IsEmpty());
+
+ PreciselyCollectGarbage();
+
+ EXPECT_EQ(10u, Destructed::n_destructed);
+}
+
} // namespace incremental_marking_test
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_verifier.cc b/chromium/third_party/blink/renderer/platform/heap/marking_verifier.cc
index 5e0e7fed6db..eb900719237 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_verifier.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_verifier.cc
@@ -14,22 +14,21 @@ void MarkingVerifier::VerifyObject(HeapObjectHeader* header) {
if (header->IsFree() || !header->IsMarked())
return;
- const GCInfo* info =
- GCInfoTable::Get().GCInfoFromIndex(header->GcInfoIndex());
+ const GCInfo& info = GCInfo::From(header->GcInfoIndex());
const bool can_verify =
- !info->has_v_table || blink::VTableInitialized(header->Payload());
+ !info.has_v_table || blink::VTableInitialized(header->Payload());
if (can_verify) {
parent_ = header;
- info->trace(this, header->Payload());
+ info.trace(this, header->Payload());
}
}
-void MarkingVerifier::Visit(void* object, TraceDescriptor desc) {
+void MarkingVerifier::Visit(const void* object, TraceDescriptor desc) {
VerifyChild(object, desc.base_object_payload);
}
-void MarkingVerifier::VisitWeak(void* object,
- void* object_weak_ref,
+void MarkingVerifier::VisitWeak(const void* object,
+ const void* object_weak_ref,
TraceDescriptor desc,
WeakCallback callback) {
// Weak objects should have been cleared at this point. As a consequence, all
@@ -38,8 +37,8 @@ void MarkingVerifier::VisitWeak(void* object,
VerifyChild(object, desc.base_object_payload);
}
-void MarkingVerifier::VisitBackingStoreStrongly(void* object,
- void**,
+void MarkingVerifier::VisitBackingStoreStrongly(const void* object,
+ const void* const*,
TraceDescriptor desc) {
if (!object)
return;
@@ -50,12 +49,12 @@ void MarkingVerifier::VisitBackingStoreStrongly(void* object,
VerifyChild(object, desc.base_object_payload);
}
-void MarkingVerifier::VisitBackingStoreWeakly(void* object,
- void**,
+void MarkingVerifier::VisitBackingStoreWeakly(const void* object,
+ const void* const*,
TraceDescriptor strong_desc,
TraceDescriptor weak_desc,
WeakCallback,
- void*) {
+ const void*) {
if (!object)
return;
@@ -67,7 +66,8 @@ void MarkingVerifier::VisitBackingStoreWeakly(void* object,
VerifyChild(object, weak_desc.base_object_payload);
}
-void MarkingVerifier::VerifyChild(void* object, void* base_object_payload) {
+void MarkingVerifier::VerifyChild(const void* object,
+ const void* base_object_payload) {
CHECK(object);
// Verification may check objects that are currently under construction and
// would require vtable access to figure out their headers. A nullptr in
@@ -82,15 +82,10 @@ void MarkingVerifier::VerifyChild(void* object, void* base_object_payload) {
// ones.
CHECK(child_header);
if (!child_header->IsMarked()) {
- // Pre-finalizers may allocate. In that case the newly allocated objects
- // reside on a page that is not scheduled for sweeping.
- if (PageFromObject(child_header->Payload())->HasBeenSwept())
- return;
-
+ CHECK(!PageFromObject(child_header->Payload())->HasBeenSwept());
LOG(FATAL) << "MarkingVerifier: Encountered unmarked object. " << std::endl
<< std::endl
- << "Hint (use v8_enable_raw_heap_snapshots for better naming): "
- << std::endl
+ << "Hint: " << std::endl
<< parent_->Name() << std::endl
<< "\\-> " << child_header->Name() << std::endl;
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h b/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h
index 14e53676d96..495e8dd4c1b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h
@@ -17,29 +17,31 @@ class MarkingVerifier final : public Visitor {
void VerifyObject(HeapObjectHeader* header);
- void Visit(void* object, TraceDescriptor desc) final;
- void VisitWeak(void* object,
- void* object_weak_ref,
+ void Visit(const void* object, TraceDescriptor desc) final;
+ void VisitWeak(const void* object,
+ const void* object_weak_ref,
TraceDescriptor desc,
WeakCallback callback) final;
- void VisitBackingStoreStrongly(void*, void**, TraceDescriptor) final;
+ void VisitBackingStoreStrongly(const void*,
+ const void* const*,
+ TraceDescriptor) final;
- void VisitBackingStoreWeakly(void*,
- void**,
+ void VisitBackingStoreWeakly(const void*,
+ const void* const*,
TraceDescriptor,
TraceDescriptor,
WeakCallback,
- void*) final;
+ const void*) final;
// Unused overrides.
- void VisitBackingStoreOnly(void*, void**) final {}
- void RegisterBackingStoreCallback(void*, MovingObjectCallback) final {}
- void RegisterWeakCallback(WeakCallback, void*) final {}
+ void VisitBackingStoreOnly(const void*, const void* const*) final {}
+ void RegisterBackingStoreCallback(const void*, MovingObjectCallback) final {}
+ void RegisterWeakCallback(WeakCallback, const void*) final {}
void Visit(const TraceWrapperV8Reference<v8::Value>&) final {}
private:
- void VerifyChild(void* object, void* base_object_payload);
+ void VerifyChild(const void* object, const void* base_object_payload);
HeapObjectHeader* parent_ = nullptr;
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
index 8ed5a880494..d0c5db8b742 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
@@ -10,19 +10,12 @@
namespace blink {
-namespace {
-
-ALWAYS_INLINE bool IsHashTableDeleteValue(const void* value) {
- return value == reinterpret_cast<void*>(-1);
-}
-
-} // namespace
-
MarkingVisitorCommon::MarkingVisitorCommon(ThreadState* state,
MarkingMode marking_mode,
int task_id)
: Visitor(state),
marking_worklist_(Heap().GetMarkingWorklist(), task_id),
+ write_barrier_worklist_(Heap().GetWriteBarrierWorklist(), task_id),
not_fully_constructed_worklist_(Heap().GetNotFullyConstructedWorklist(),
task_id),
weak_callback_worklist_(Heap().GetWeakCallbackWorklist(), task_id),
@@ -35,38 +28,38 @@ MarkingVisitorCommon::MarkingVisitorCommon(ThreadState* state,
task_id_(task_id) {}
void MarkingVisitorCommon::FlushCompactionWorklists() {
+ if (marking_mode_ != kGlobalMarkingWithCompaction)
+ return;
movable_reference_worklist_.FlushToGlobal();
backing_store_callback_worklist_.FlushToGlobal();
}
void MarkingVisitorCommon::RegisterWeakCallback(WeakCallback callback,
- void* object) {
+ const void* object) {
weak_callback_worklist_.Push({callback, object});
}
-void MarkingVisitorCommon::RegisterBackingStoreReference(void** slot) {
+void MarkingVisitorCommon::RegisterBackingStoreReference(
+ const void* const* slot) {
if (marking_mode_ != kGlobalMarkingWithCompaction)
return;
- MovableReference* movable_reference =
- reinterpret_cast<MovableReference*>(slot);
- if (Heap().ShouldRegisterMovingAddress(
- reinterpret_cast<Address>(movable_reference))) {
- movable_reference_worklist_.Push(movable_reference);
+ if (Heap().ShouldRegisterMovingAddress()) {
+ movable_reference_worklist_.Push(slot);
}
}
void MarkingVisitorCommon::RegisterBackingStoreCallback(
- void* backing,
+ const void* backing,
MovingObjectCallback callback) {
if (marking_mode_ != kGlobalMarkingWithCompaction)
return;
- if (Heap().ShouldRegisterMovingAddress(reinterpret_cast<Address>(backing))) {
+ if (Heap().ShouldRegisterMovingAddress()) {
backing_store_callback_worklist_.Push({backing, callback});
}
}
-void MarkingVisitorCommon::VisitWeak(void* object,
- void* object_weak_ref,
+void MarkingVisitorCommon::VisitWeak(const void* object,
+ const void* object_weak_ref,
TraceDescriptor desc,
WeakCallback callback) {
// Filter out already marked values. The write barrier for WeakMember
@@ -79,9 +72,10 @@ void MarkingVisitorCommon::VisitWeak(void* object,
RegisterWeakCallback(callback, object_weak_ref);
}
-void MarkingVisitorCommon::VisitBackingStoreStrongly(void* object,
- void** object_slot,
- TraceDescriptor desc) {
+void MarkingVisitorCommon::VisitBackingStoreStrongly(
+ const void* object,
+ const void* const* object_slot,
+ TraceDescriptor desc) {
RegisterBackingStoreReference(object_slot);
if (!object)
return;
@@ -90,24 +84,30 @@ void MarkingVisitorCommon::VisitBackingStoreStrongly(void* object,
// All work is registered through RegisterWeakCallback.
void MarkingVisitorCommon::VisitBackingStoreWeakly(
- void* object,
- void** object_slot,
+ const void* object,
+ const void* const* object_slot,
TraceDescriptor strong_desc,
TraceDescriptor weak_desc,
WeakCallback weak_callback,
- void* weak_callback_parameter) {
+ const void* weak_callback_parameter) {
RegisterBackingStoreReference(object_slot);
+
+ // In case there's no object present, weakness processing is omitted. The GC
+ // relies on the fact that in such cases touching the weak data structure will
+ // strongify its references.
if (!object)
return;
- RegisterWeakCallback(weak_callback, weak_callback_parameter);
+ // Register final weak processing of the backing store.
+ RegisterWeakCallback(weak_callback, weak_callback_parameter);
+ // Register ephemeron callbacks if necessary.
if (weak_desc.callback)
weak_table_worklist_.Push(weak_desc);
}
bool MarkingVisitorCommon::VisitEphemeronKeyValuePair(
- void* key,
- void* value,
+ const void* key,
+ const void* value,
EphemeronTracingCallback key_trace_callback,
EphemeronTracingCallback value_trace_callback) {
const bool key_is_dead = key_trace_callback(this, key);
@@ -118,8 +118,9 @@ bool MarkingVisitorCommon::VisitEphemeronKeyValuePair(
return false;
}
-void MarkingVisitorCommon::VisitBackingStoreOnly(void* object,
- void** object_slot) {
+void MarkingVisitorCommon::VisitBackingStoreOnly(
+ const void* object,
+ const void* const* object_slot) {
RegisterBackingStoreReference(object_slot);
if (!object)
return;
@@ -129,19 +130,9 @@ void MarkingVisitorCommon::VisitBackingStoreOnly(void* object,
}
// static
-bool MarkingVisitor::WriteBarrierSlow(void* value) {
- if (!value || IsHashTableDeleteValue(value))
- return false;
-
- // It is guaranteed that managed references point to either GarbageCollected
- // or GarbageCollectedMixin. Mixins are restricted to regular objects sizes.
- // It is thus possible to get to the page header by aligning properly.
- BasePage* base_page = PageFromObject(value);
-
- ThreadState* const thread_state = base_page->thread_state();
- if (!thread_state->IsIncrementalMarking())
- return false;
-
+bool MarkingVisitor::MarkValue(void* value,
+ BasePage* base_page,
+ ThreadState* thread_state) {
HeapObjectHeader* header;
if (LIKELY(!base_page->IsLargeObjectPage())) {
header = reinterpret_cast<HeapObjectHeader*>(
@@ -169,7 +160,47 @@ bool MarkingVisitor::WriteBarrierSlow(void* value) {
return true;
}
-void MarkingVisitor::TraceMarkedBackingStoreSlow(void* value) {
+// static
+bool MarkingVisitor::WriteBarrierSlow(void* value) {
+ if (!value || IsHashTableDeleteValue(value))
+ return false;
+
+ // It is guaranteed that managed references point to either GarbageCollected
+ // or GarbageCollectedMixin. Mixins are restricted to regular objects sizes.
+ // It is thus possible to get to the page header by aligning properly.
+ BasePage* base_page = PageFromObject(value);
+
+ ThreadState* const thread_state = base_page->thread_state();
+ if (!thread_state->IsIncrementalMarking())
+ return false;
+
+ return MarkValue(value, base_page, thread_state);
+}
+
+void MarkingVisitor::GenerationalBarrierSlow(Address slot,
+ ThreadState* thread_state) {
+ BasePage* slot_page = thread_state->Heap().LookupPageForAddress(slot);
+ DCHECK(slot_page);
+
+ if (UNLIKELY(slot_page->IsLargeObjectPage())) {
+ auto* large_page = static_cast<LargeObjectPage*>(slot_page);
+ if (UNLIKELY(large_page->ObjectHeader()->IsOld())) {
+ large_page->SetRemembered(true);
+ }
+ return;
+ }
+
+ auto* normal_page = static_cast<NormalPage*>(slot_page);
+ const HeapObjectHeader* source_header = reinterpret_cast<HeapObjectHeader*>(
+ normal_page->object_start_bit_map()->FindHeader(slot));
+ DCHECK_LT(0u, source_header->GcInfoIndex());
+ DCHECK_GT(source_header->PayloadEnd(), slot);
+ if (UNLIKELY(source_header->IsOld())) {
+ normal_page->MarkCard(slot);
+ }
+}
+
+void MarkingVisitor::TraceMarkedBackingStoreSlow(const void* value) {
if (!value)
return;
@@ -183,33 +214,29 @@ void MarkingVisitor::TraceMarkedBackingStoreSlow(void* value) {
DCHECK(thread_state->CurrentVisitor());
// No weak handling for write barriers. Modifying weakly reachable objects
// strongifies them for the current cycle.
- GCInfoTable::Get()
- .GCInfoFromIndex(header->GcInfoIndex())
- ->trace(thread_state->CurrentVisitor(), value);
+
+ GCInfo::From(header->GcInfoIndex())
+ .trace(thread_state->CurrentVisitor(), value);
}
MarkingVisitor::MarkingVisitor(ThreadState* state, MarkingMode marking_mode)
- : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MutatorThread),
- write_barrier_worklist_(Heap().GetWriteBarrierWorklist(),
- WorklistTaskId::MutatorThread) {
+ : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MutatorThread) {
DCHECK(state->InAtomicMarkingPause());
DCHECK(state->CheckThread());
}
-void MarkingVisitor::DynamicallyMarkAddress(Address address) {
+void MarkingVisitor::DynamicallyMarkAddress(ConstAddress address) {
HeapObjectHeader* const header = HeapObjectHeader::FromInnerAddress(address);
DCHECK(header);
DCHECK(!IsInConstruction(header));
- const GCInfo* gc_info =
- GCInfoTable::Get().GCInfoFromIndex(header->GcInfoIndex());
if (MarkHeaderNoTracing(header)) {
- marking_worklist_.Push(
- {reinterpret_cast<void*>(header->Payload()), gc_info->trace});
+ marking_worklist_.Push({reinterpret_cast<void*>(header->Payload()),
+ GCInfo::From(header->GcInfoIndex()).trace});
}
}
void MarkingVisitor::ConservativelyMarkAddress(BasePage* page,
- Address address) {
+ ConstAddress address) {
#if DCHECK_IS_ON()
DCHECK(page->Contains(address));
#endif
@@ -223,10 +250,9 @@ void MarkingVisitor::ConservativelyMarkAddress(BasePage* page,
// Simple case for fully constructed objects. This just adds the object to the
// regular marking worklist.
- const GCInfo* gc_info =
- GCInfoTable::Get().GCInfoFromIndex(header->GcInfoIndex());
if (!IsInConstruction(header)) {
- MarkHeader(header, {header->Payload(), gc_info->trace});
+ MarkHeader(header,
+ {header->Payload(), GCInfo::From(header->GcInfoIndex()).trace});
return;
}
@@ -260,14 +286,18 @@ void MarkingVisitor::ConservativelyMarkAddress(BasePage* page,
AccountMarkedBytes(header);
}
-void MarkingVisitor::FlushMarkingWorklist() {
+void MarkingVisitor::FlushMarkingWorklists() {
marking_worklist_.FlushToGlobal();
+ write_barrier_worklist_.FlushToGlobal();
}
ConcurrentMarkingVisitor::ConcurrentMarkingVisitor(ThreadState* state,
MarkingMode marking_mode,
int task_id)
- : MarkingVisitorBase(state, marking_mode, task_id) {
+ : MarkingVisitorBase(state, marking_mode, task_id),
+ not_safe_to_concurrently_trace_worklist_(
+ Heap().GetNotSafeToConcurrentlyTraceWorklist(),
+ task_id) {
DCHECK(!state->CheckThread());
DCHECK_NE(WorklistTaskId::MutatorThread, task_id);
}
@@ -275,12 +305,16 @@ ConcurrentMarkingVisitor::ConcurrentMarkingVisitor(ThreadState* state,
void ConcurrentMarkingVisitor::FlushWorklists() {
// Flush marking worklists for further marking on the mutator thread.
marking_worklist_.FlushToGlobal();
+ write_barrier_worklist_.FlushToGlobal();
not_fully_constructed_worklist_.FlushToGlobal();
weak_callback_worklist_.FlushToGlobal();
weak_table_worklist_.FlushToGlobal();
+ not_safe_to_concurrently_trace_worklist_.FlushToGlobal();
// Flush compaction worklists.
- movable_reference_worklist_.FlushToGlobal();
- backing_store_callback_worklist_.FlushToGlobal();
+ if (marking_mode_ == kGlobalMarkingWithCompaction) {
+ movable_reference_worklist_.FlushToGlobal();
+ backing_store_callback_worklist_.FlushToGlobal();
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
index 0bb441d6b6a..24ff86413cb 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -12,6 +12,14 @@
namespace blink {
+namespace {
+
+ALWAYS_INLINE bool IsHashTableDeleteValue(const void* value) {
+ return value == reinterpret_cast<void*>(-1);
+}
+
+} // namespace
+
class BasePage;
// Base visitor used to mark Oilpan objects on any thread.
@@ -24,23 +32,25 @@ class PLATFORM_EXPORT MarkingVisitorCommon : public Visitor {
kGlobalMarkingWithCompaction,
};
- void VisitWeak(void*, void*, TraceDescriptor, WeakCallback) final;
- void VisitBackingStoreStrongly(void*, void**, TraceDescriptor) final;
- void VisitBackingStoreWeakly(void*,
- void**,
+ void VisitWeak(const void*, const void*, TraceDescriptor, WeakCallback) final;
+ void VisitBackingStoreStrongly(const void*,
+ const void* const*,
+ TraceDescriptor) final;
+ void VisitBackingStoreWeakly(const void*,
+ const void* const*,
TraceDescriptor,
TraceDescriptor,
WeakCallback,
- void*) final;
- bool VisitEphemeronKeyValuePair(void*,
- void*,
+ const void*) final;
+ bool VisitEphemeronKeyValuePair(const void*,
+ const void*,
EphemeronTracingCallback,
EphemeronTracingCallback) final;
// Used to only mark the backing store when it has been registered for weak
// processing. In this case, the contents are processed separately using
// the corresponding traits but the backing store requires marking.
- void VisitBackingStoreOnly(void*, void**) final;
+ void VisitBackingStoreOnly(const void*, const void* const*) final;
// This callback mechanism is needed to account for backing store objects
// containing intra-object pointers, all of which must be relocated/rebased
@@ -48,8 +58,8 @@ class PLATFORM_EXPORT MarkingVisitorCommon : public Visitor {
//
// For Blink, |HeapLinkedHashSet<>| is currently the only abstraction which
// relies on this feature.
- void RegisterBackingStoreCallback(void*, MovingObjectCallback) final;
- void RegisterWeakCallback(WeakCallback, void*) final;
+ void RegisterBackingStoreCallback(const void*, MovingObjectCallback) final;
+ void RegisterWeakCallback(WeakCallback, const void*) final;
// Flush private segments remaining in visitor's worklists to global pools.
void FlushCompactionWorklists();
@@ -71,9 +81,10 @@ class PLATFORM_EXPORT MarkingVisitorCommon : public Visitor {
// marked upon calling.
bool MarkHeaderNoTracing(HeapObjectHeader*);
- void RegisterBackingStoreReference(void** slot);
+ void RegisterBackingStoreReference(const void* const* slot);
MarkingWorklist::View marking_worklist_;
+ WriteBarrierWorklist::View write_barrier_worklist_;
NotFullyConstructedWorklist::View not_fully_constructed_worklist_;
WeakCallbackWorklist::View weak_callback_worklist_;
MovableReferenceWorklist::View movable_reference_worklist_;
@@ -88,7 +99,8 @@ ALWAYS_INLINE void MarkingVisitorCommon::AccountMarkedBytes(
HeapObjectHeader* header) {
marked_bytes_ +=
header->IsLargeObject()
- ? reinterpret_cast<LargeObjectPage*>(PageFromObject(header))->size()
+ ? reinterpret_cast<LargeObjectPage*>(PageFromObject(header))
+ ->ObjectSize()
: header->size();
}
@@ -110,7 +122,7 @@ ALWAYS_INLINE bool MarkingVisitorCommon::MarkHeaderNoTracing(
template <class Specialized>
class PLATFORM_EXPORT MarkingVisitorBase : public MarkingVisitorCommon {
public:
- void Visit(void* object, TraceDescriptor desc) final;
+ void Visit(const void* object, TraceDescriptor desc) final;
// Unused cross-component visit methods.
void Visit(const TraceWrapperV8Reference<v8::Value>&) override {}
@@ -125,7 +137,7 @@ class PLATFORM_EXPORT MarkingVisitorBase : public MarkingVisitorCommon {
};
template <class Specialized>
-inline void MarkingVisitorBase<Specialized>::Visit(void* object,
+inline void MarkingVisitorBase<Specialized>::Visit(const void* object,
TraceDescriptor desc) {
DCHECK(object);
if (desc.base_object_payload == BlinkGC::kNotFullyConstructedObject) {
@@ -161,17 +173,20 @@ class PLATFORM_EXPORT MarkingVisitor
// Returns whether an object is in construction.
static bool IsInConstruction(HeapObjectHeader* header);
- // Write barrier that adds |value| to the set of marked objects. The barrier
- // bails out if marking is off or the object is not yet marked. Returns true
- // if the object was marked on this call.
- static bool WriteBarrier(void* value);
+ // Write barrier that adds a value the |slot| refers to to the set of marked
+ // objects. The barrier bails out if marking is off or the object is not yet
+ // marked. Returns true if the value has been marked on this call.
+ template <typename T>
+ static bool WriteBarrier(T** slot);
+
+ static void GenerationalBarrier(Address slot, ThreadState* state);
// Eagerly traces an already marked backing store ensuring that all its
// children are discovered by the marker. The barrier bails out if marking
// is off and on individual objects reachable if they are already marked. The
// barrier uses the callback function through GcInfo, so it will not inline
// any templated type-specific code.
- static void TraceMarkedBackingStore(void* value);
+ static void TraceMarkedBackingStore(const void* value);
MarkingVisitor(ThreadState*, MarkingMode);
~MarkingVisitor() override = default;
@@ -179,21 +194,21 @@ class PLATFORM_EXPORT MarkingVisitor
// Conservatively marks an object if pointed to by Address. The object may
// be in construction as the scan is conservative without relying on a
// Trace method.
- void ConservativelyMarkAddress(BasePage*, Address);
+ void ConservativelyMarkAddress(BasePage*, ConstAddress);
// Marks an object dynamically using any address within its body and adds a
// tracing callback for processing of the object. The object is not allowed
// to be in construction.
- void DynamicallyMarkAddress(Address);
+ void DynamicallyMarkAddress(ConstAddress);
- void FlushMarkingWorklist();
+ void FlushMarkingWorklists();
private:
- // Exact version of the marking write barriers.
+ // Exact version of the marking and generational write barriers.
static bool WriteBarrierSlow(void*);
- static void TraceMarkedBackingStoreSlow(void*);
-
- WriteBarrierWorklist::View write_barrier_worklist_;
+ static void GenerationalBarrierSlow(Address, ThreadState*);
+ static bool MarkValue(void*, BasePage*, ThreadState*);
+ static void TraceMarkedBackingStoreSlow(const void*);
};
// static
@@ -204,17 +219,45 @@ ALWAYS_INLINE bool MarkingVisitor::IsInConstruction(HeapObjectHeader* header) {
}
// static
-ALWAYS_INLINE bool MarkingVisitor::WriteBarrier(void* value) {
+template <typename T>
+ALWAYS_INLINE bool MarkingVisitor::WriteBarrier(T** slot) {
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ void* value = *slot;
+ if (!value || IsHashTableDeleteValue(value))
+ return false;
+
+ // Dijkstra barrier if concurrent marking is in progress.
+ BasePage* value_page = PageFromObject(value);
+ ThreadState* thread_state = value_page->thread_state();
+
+ if (UNLIKELY(thread_state->IsIncrementalMarking()))
+ return MarkValue(value, value_page, thread_state);
+
+ GenerationalBarrier(reinterpret_cast<Address>(slot), thread_state);
+ return false;
+#else
if (!ThreadState::IsAnyIncrementalMarking())
return false;
// Avoid any further checks and dispatch to a call at this point. Aggressive
// inlining otherwise pollutes the regular execution paths.
- return WriteBarrierSlow(value);
+ return WriteBarrierSlow(*slot);
+#endif
}
// static
-ALWAYS_INLINE void MarkingVisitor::TraceMarkedBackingStore(void* value) {
+ALWAYS_INLINE void MarkingVisitor::GenerationalBarrier(Address slot,
+ ThreadState* state) {
+ // First, check if the source object is in the last allocated region of heap.
+ if (LIKELY(state->Heap().IsInLastAllocatedRegion(slot)))
+ return;
+ if (UNLIKELY(state->IsOnStack(slot)))
+ return;
+ GenerationalBarrierSlow(slot, state);
+}
+
+// static
+ALWAYS_INLINE void MarkingVisitor::TraceMarkedBackingStore(const void* value) {
if (!ThreadState::IsAnyIncrementalMarking())
return;
@@ -234,8 +277,30 @@ class PLATFORM_EXPORT ConcurrentMarkingVisitor
~ConcurrentMarkingVisitor() override = default;
virtual void FlushWorklists();
+
+ // Concurrent variant of MarkingVisitorCommon::AccountMarkedBytes.
+ void AccountMarkedBytesSafe(HeapObjectHeader*);
+
+ bool IsConcurrent() const override { return true; }
+
+ bool ConcurrentTracingBailOut(TraceDescriptor desc) override {
+ not_safe_to_concurrently_trace_worklist_.Push(desc);
+ return true;
+ }
+
+ private:
+ NotSafeToConcurrentlyTraceWorklist::View
+ not_safe_to_concurrently_trace_worklist_;
};
+ALWAYS_INLINE void ConcurrentMarkingVisitor::AccountMarkedBytesSafe(
+ HeapObjectHeader* header) {
+ marked_bytes_ +=
+ header->IsLargeObject<HeapObjectHeader::AccessMode::kAtomic>()
+ ? static_cast<LargeObjectPage*>(PageFromObject(header))->ObjectSize()
+ : header->size<HeapObjectHeader::AccessMode::kAtomic>();
+}
+
// static
ALWAYS_INLINE bool ConcurrentMarkingVisitor::IsInConstruction(
HeapObjectHeader* header) {
diff --git a/chromium/third_party/blink/renderer/platform/heap/member.h b/chromium/third_party/blink/renderer/platform/heap/member.h
index 6c6f324271f..1610b12d7f2 100644
--- a/chromium/third_party/blink/renderer/platform/heap/member.h
+++ b/chromium/third_party/blink/renderer/platform/heap/member.h
@@ -113,21 +113,21 @@ class MemberBase {
MemberBase(const MemberBase& other) : raw_(other) {
SaveCreationThreadState();
CheckPointer();
- WriteBarrier();
+ // No write barrier for initializing stores.
}
template <typename U>
MemberBase(const Persistent<U>& other) : raw_(other) {
SaveCreationThreadState();
CheckPointer();
- WriteBarrier();
+ // No write barrier for initializing stores.
}
template <typename U>
MemberBase(const MemberBase<U>& other) : raw_(other) {
SaveCreationThreadState();
CheckPointer();
- WriteBarrier();
+ // No write barrier for initializing stores.
}
template <typename U>
@@ -195,16 +195,37 @@ class MemberBase {
return result;
}
+ static bool IsMemberHashTableDeletedValue(const T* t) {
+ return t == reinterpret_cast<T*>(kHashTableDeletedRawValue);
+ }
+
bool IsHashTableDeletedValue() const {
- return GetRaw() == reinterpret_cast<T*>(kHashTableDeletedRawValue);
+ return IsMemberHashTableDeletedValue(GetRaw());
}
protected:
static constexpr intptr_t kHashTableDeletedRawValue = -1;
+ enum class AtomicCtorTag { Atomic };
+
+ // MemberBase ctors that use atomic write to set raw_.
+
+ MemberBase(AtomicCtorTag, T* raw) {
+ SetRaw(raw);
+ SaveCreationThreadState();
+ CheckPointer();
+ // No write barrier for initializing stores.
+ }
+
+ MemberBase(AtomicCtorTag, T& raw) {
+ SetRaw(&raw);
+ SaveCreationThreadState();
+ CheckPointer();
+ // No write barrier for initializing stores.
+ }
+
void WriteBarrier() const {
- MarkingVisitor::WriteBarrier(
- const_cast<typename std::remove_const<T>::type*>(GetRaw()));
+ MarkingVisitor::WriteBarrier(const_cast<std::remove_const_t<T>**>(&raw_));
}
void CheckPointer() {
@@ -224,10 +245,7 @@ class MemberBase {
}
ALWAYS_INLINE void SetRaw(T* raw) {
- // TOOD(omerkatz): replace this cast with std::atomic_ref (C++20) once it
- // becomes available
- reinterpret_cast<std::atomic<T*>*>(&raw_)->store(raw,
- std::memory_order_relaxed);
+ WTF::AsAtomicPtr(&raw_)->store(raw, std::memory_order_relaxed);
}
ALWAYS_INLINE T* GetRaw() const { return raw_; }
@@ -235,17 +253,10 @@ class MemberBase {
// Thread safe version of Get() for marking visitors.
// This is used to prevent data races between concurrent marking visitors
// and writes on the main thread.
- T* GetSafe() const {
+ const T* GetSafe() const {
// TOOD(omerkatz): replace this cast with std::atomic_ref (C++20) once it
// becomes available
- return reinterpret_cast<std::atomic<T*>*>(
- const_cast<typename std::remove_const<T>::type**>(&raw_))
- ->load(std::memory_order_relaxed);
- }
-
- // Thread safe version of IsHashTableDeletedValue for use while tracing.
- bool IsHashTableDeletedValueSafe() const {
- return GetSafe() == reinterpret_cast<T*>(kHashTableDeletedRawValue);
+ return WTF::AsAtomicPtr(&raw_)->load(std::memory_order_relaxed);
}
T* raw_;
@@ -321,7 +332,11 @@ class Member : public MemberBase<T, TracenessMemberConfiguration::kTraced> {
return *this;
}
- protected:
+ private:
+ using typename Parent::AtomicCtorTag;
+ Member(AtomicCtorTag atomic, T* raw) : Parent(atomic, raw) {}
+ Member(AtomicCtorTag atomic, T& raw) : Parent(atomic, raw) {}
+
template <typename P, typename Traits, typename Allocator>
friend class WTF::ConstructTraits;
};
@@ -404,6 +419,12 @@ class UntracedMember final
UntracedMember(WTF::HashTableDeletedValueType x) : Parent(x) {}
+ UntracedMember& operator=(const UntracedMember& other) {
+ this->SetRaw(other);
+ this->CheckPointer();
+ return *this;
+ }
+
template <typename U>
UntracedMember& operator=(const Persistent<U>& other) {
this->SetRaw(other);
@@ -500,7 +521,12 @@ class ConstructTraits<blink::Member<T>, Traits, Allocator> {
template <typename... Args>
static blink::Member<T>* ConstructAndNotifyElement(void* location,
Args&&... args) {
- blink::Member<T>* object = Construct(location, std::forward<Args>(args)...);
+ // ConstructAndNotifyElement updates an existing Member which might
+ // also be comncurrently traced while we update it. The regular ctors
+ // for Member don't use an atomic write which can lead to data races.
+ blink::Member<T>* object =
+ Construct(location, blink::Member<T>::AtomicCtorTag::Atomic,
+ std::forward<Args>(args)...);
NotifyNewElement(object);
return object;
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/minor_gc_test.cc b/chromium/third_party/blink/renderer/platform/heap/minor_gc_test.cc
new file mode 100644
index 00000000000..c30e976d294
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/minor_gc_test.cc
@@ -0,0 +1,295 @@
+// 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 "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/heap/heap_page.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+namespace {
+
+class SimpleGCedBase : public GarbageCollected<SimpleGCedBase> {
+ public:
+ static size_t destructed_objects;
+
+ virtual ~SimpleGCedBase() { ++destructed_objects; }
+
+ void Trace(Visitor* v) { v->Trace(next); }
+
+ Member<SimpleGCedBase> next;
+};
+
+size_t SimpleGCedBase::destructed_objects;
+
+template <size_t Size>
+class SimpleGCed final : public SimpleGCedBase {
+ char array[Size];
+};
+
+using Small = SimpleGCed<64>;
+using Large = SimpleGCed<1024 * 1024>;
+
+template <typename Type>
+struct OtherType;
+template <>
+struct OtherType<Small> {
+ using Type = Large;
+};
+template <>
+struct OtherType<Large> {
+ using Type = Small;
+};
+
+class MinorGCTest : public TestSupportingGC {
+ public:
+ MinorGCTest() {
+ ClearOutOldGarbage();
+ SimpleGCedBase::destructed_objects = 0;
+ }
+
+ static size_t DestructedObjects() {
+ return SimpleGCedBase::destructed_objects;
+ }
+
+ static void CollectMinor() { Collect(BlinkGC::CollectionType::kMinor); }
+ static void CollectMajor() { Collect(BlinkGC::CollectionType::kMajor); }
+
+ private:
+ static void Collect(BlinkGC::CollectionType type) {
+ ThreadState::Current()->CollectGarbage(
+ type, BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting);
+ }
+};
+
+template <typename SmallOrLarge>
+class MinorGCTestForType : public MinorGCTest {
+ public:
+ using Type = SmallOrLarge;
+};
+
+} // namespace
+
+using ObjectTypes = ::testing::Types<Small, Large>;
+TYPED_TEST_SUITE(MinorGCTestForType, ObjectTypes);
+
+TYPED_TEST(MinorGCTestForType, MinorCollection) {
+ using Type = typename TestFixture::Type;
+
+ MakeGarbageCollected<Type>();
+ EXPECT_EQ(0u, TestFixture::DestructedObjects());
+ MinorGCTest::CollectMinor();
+ EXPECT_EQ(1u, TestFixture::DestructedObjects());
+
+ Type* prev = nullptr;
+ for (size_t i = 0; i < 64; ++i) {
+ auto* ptr = MakeGarbageCollected<Type>();
+ ptr->next = prev;
+ prev = ptr;
+ }
+
+ MinorGCTest::CollectMinor();
+ EXPECT_EQ(65u, TestFixture::DestructedObjects());
+}
+
+TYPED_TEST(MinorGCTestForType, StickyBits) {
+ using Type = typename TestFixture::Type;
+
+ Persistent<Type> p1 = MakeGarbageCollected<Type>();
+ TestFixture::CollectMinor();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(p1.Get())->IsOld());
+ TestFixture::CollectMajor();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(p1.Get())->IsOld());
+ EXPECT_EQ(0u, TestFixture::DestructedObjects());
+}
+
+TYPED_TEST(MinorGCTestForType, OldObjectIsNotVisited) {
+ using Type = typename TestFixture::Type;
+
+ Persistent<Type> p = MakeGarbageCollected<Type>();
+ TestFixture::CollectMinor();
+ EXPECT_EQ(0u, TestFixture::DestructedObjects());
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(p.Get())->IsOld());
+
+ // Check that the old deleted object won't be visited during minor GC.
+ Type* raw = p.Release();
+ TestFixture::CollectMinor();
+ EXPECT_EQ(0u, TestFixture::DestructedObjects());
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(raw)->IsOld());
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(raw)->IsFree());
+
+ // Check that the old deleted object will be revisited in major GC.
+ TestFixture::CollectMajor();
+ EXPECT_EQ(1u, TestFixture::DestructedObjects());
+}
+
+template <typename Type1, typename Type2>
+void InterGenerationalPointerTest() {
+ Persistent<Type1> old = MakeGarbageCollected<Type1>();
+ MinorGCTest::CollectMinor();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(old.Get())->IsOld());
+
+ // Allocate young objects.
+ Type2* young = nullptr;
+ for (size_t i = 0; i < 64; ++i) {
+ auto* ptr = MakeGarbageCollected<Type2>();
+ ptr->next = young;
+ young = ptr;
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(young)->IsOld());
+ }
+
+ // Issue generational barrier.
+ old->next = young;
+
+ // Check that the remembered set is visited.
+ MinorGCTest::CollectMinor();
+ EXPECT_EQ(0u, MinorGCTest::DestructedObjects());
+ for (size_t i = 0; i < 64; ++i) {
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(young)->IsOld());
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(young)->IsFree());
+ young = static_cast<Type2*>(young->next.Get());
+ }
+
+ old.Release();
+ MinorGCTest::CollectMajor();
+ EXPECT_EQ(65u, MinorGCTest::DestructedObjects());
+}
+
+TYPED_TEST(MinorGCTestForType, InterGenerationalPointerForSamePageTypes) {
+ using Type = typename TestFixture::Type;
+ InterGenerationalPointerTest<Type, Type>();
+}
+
+TYPED_TEST(MinorGCTestForType, InterGenerationalPointerForDifferentPageTypes) {
+ using Type = typename TestFixture::Type;
+ InterGenerationalPointerTest<Type, typename OtherType<Type>::Type>();
+}
+
+TYPED_TEST(MinorGCTestForType, InterGenerationalPointerInCollection) {
+ using Type = typename TestFixture::Type;
+
+ static constexpr size_t kCollectionSize = 128;
+ Persistent<HeapVector<Member<Type>>> old =
+ MakeGarbageCollected<HeapVector<Member<Type>>>();
+ old->resize(kCollectionSize);
+ void* raw_backing = old->data();
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(raw_backing)->IsOld());
+ MinorGCTest::CollectMinor();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(raw_backing)->IsOld());
+
+ // Issue barrier for every second member.
+ size_t i = 0;
+ for (auto& member : *old) {
+ if (i % 2) {
+ member = MakeGarbageCollected<Type>();
+ } else {
+ MakeGarbageCollected<Type>();
+ }
+ ++i;
+ }
+
+ // Check that the remembered set is visited.
+ MinorGCTest::CollectMinor();
+ EXPECT_EQ(kCollectionSize / 2, MinorGCTest::DestructedObjects());
+ for (const auto& member : *old) {
+ if (member) {
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(member.Get())->IsOld());
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(member.Get())->IsFree());
+ }
+ }
+
+ old.Release();
+ MinorGCTest::CollectMajor();
+ EXPECT_EQ(kCollectionSize, MinorGCTest::DestructedObjects());
+}
+
+TYPED_TEST(MinorGCTestForType, InterGenerationalPointerInPlaceBarrier) {
+ using Type = typename TestFixture::Type;
+ using ValueType = std::pair<WTF::String, Member<Type>>;
+ using CollectionType = HeapVector<ValueType>;
+
+ static constexpr size_t kCollectionSize = 1;
+
+ Persistent<CollectionType> old = MakeGarbageCollected<CollectionType>();
+ old->ReserveInitialCapacity(kCollectionSize);
+
+ void* raw_backing = old->data();
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(raw_backing)->IsOld());
+ MinorGCTest::CollectMinor();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(raw_backing)->IsOld());
+
+ // Issue barrier (in HeapAllocator::NotifyNewElement).
+ old->push_back(std::make_pair("test", MakeGarbageCollected<Type>()));
+
+ // Check that the remembered set is visited.
+ MinorGCTest::CollectMinor();
+
+ // No objects destructed.
+ EXPECT_EQ(0u, MinorGCTest::DestructedObjects());
+ EXPECT_EQ(1u, old->size());
+
+ {
+ Type* member = (*old)[0].second;
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(member)->IsOld());
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(member)->IsFree());
+ }
+
+ old.Release();
+ MinorGCTest::CollectMajor();
+ EXPECT_EQ(1u, MinorGCTest::DestructedObjects());
+}
+
+TYPED_TEST(MinorGCTestForType,
+ InterGenerationalPointerNotifyingBunchOfElements) {
+ using Type = typename TestFixture::Type;
+ using ValueType = std::pair<int, Member<Type>>;
+ using CollectionType = HeapVector<ValueType>;
+ static_assert(WTF::VectorTraits<ValueType>::kCanCopyWithMemcpy,
+ "Only when copying with memcpy the "
+ "Allocator::NotifyNewElements is called");
+
+ Persistent<CollectionType> old = MakeGarbageCollected<CollectionType>();
+ old->ReserveInitialCapacity(1);
+
+ void* raw_backing = old->data();
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(raw_backing)->IsOld());
+
+ // Mark old backing.
+ MinorGCTest::CollectMinor();
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(raw_backing)->IsOld());
+
+ Persistent<CollectionType> young = MakeGarbageCollected<CollectionType>();
+
+ // Add a single element to the young container.
+ young->push_back(std::make_pair(1, MakeGarbageCollected<Type>()));
+
+ // Copy young container and issue barrier in HeapAllocator::NotifyNewElements.
+ *old = *young;
+
+ // Release young container.
+ young.Release();
+
+ // Check that the remembered set is visited.
+ MinorGCTest::CollectMinor();
+
+ // Nothing must be destructed since the old vector backing was revisited.
+ EXPECT_EQ(0u, MinorGCTest::DestructedObjects());
+ EXPECT_EQ(1u, old->size());
+
+ {
+ Type* member = (*old)[0].second;
+ EXPECT_TRUE(HeapObjectHeader::FromPayload(member)->IsOld());
+ EXPECT_FALSE(HeapObjectHeader::FromPayload(member)->IsFree());
+ }
+
+ old.Release();
+ MinorGCTest::CollectMajor();
+ EXPECT_EQ(1u, MinorGCTest::DestructedObjects());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/page_memory.cc b/chromium/third_party/blink/renderer/platform/heap/page_memory.cc
index c94a5866657..6552456eebc 100644
--- a/chromium/third_party/blink/renderer/platform/heap/page_memory.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/page_memory.cc
@@ -56,7 +56,8 @@ void PageMemoryRegion::PageDeleted(Address page) {
// we should probably have a way to distinguish physical memory OOM from
// virtual address space OOM.
static NOINLINE void BlinkGCOutOfMemory() {
- OOM_CRASH();
+ // TODO(lizeb): Add the real allocation size here as well.
+ OOM_CRASH(0);
}
PageMemoryRegion* PageMemoryRegion::Allocate(size_t size,
@@ -72,7 +73,7 @@ PageMemoryRegion* PageMemoryRegion::Allocate(size_t size,
return new PageMemoryRegion(base, size, num_pages, region_tree);
}
-PageMemoryRegion* RegionTree::Lookup(Address address) {
+PageMemoryRegion* RegionTree::Lookup(ConstAddress address) {
auto it = set_.upper_bound(address);
// This check also covers set_.size() > 0, since for empty vectors it is
// guaranteed that begin() == end().
diff --git a/chromium/third_party/blink/renderer/platform/heap/page_memory.h b/chromium/third_party/blink/renderer/platform/heap/page_memory.h
index 40884d69b93..249a1eb668c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/page_memory.h
+++ b/chromium/third_party/blink/renderer/platform/heap/page_memory.h
@@ -24,7 +24,7 @@ class MemoryRegion {
DCHECK_GT(size, 0u);
}
- bool Contains(Address addr) const {
+ bool Contains(ConstAddress addr) const {
return base_ <= addr && addr < (base_ + size_);
}
@@ -73,7 +73,7 @@ class PageMemoryRegion : public MemoryRegion {
region_tree);
}
- BasePage* PageFromAddress(Address address) {
+ BasePage* PageFromAddress(ConstAddress address) {
DCHECK(Contains(address));
if (!in_use_[Index(address)])
return nullptr;
@@ -85,11 +85,11 @@ class PageMemoryRegion : public MemoryRegion {
private:
PageMemoryRegion(Address base, size_t, unsigned num_pages, RegionTree*);
- unsigned Index(Address address) const {
+ unsigned Index(ConstAddress address) const {
DCHECK(Contains(address));
if (is_large_page_)
return 0;
- size_t offset = BlinkPageAddress(address) - Base();
+ size_t offset = BlinkPageAddress(const_cast<Address>(address)) - Base();
DCHECK_EQ(offset % kBlinkPageSize, 0u);
return static_cast<unsigned>(offset / kBlinkPageSize);
}
@@ -112,12 +112,12 @@ class RegionTree {
public:
void Add(PageMemoryRegion*);
void Remove(PageMemoryRegion*);
- PageMemoryRegion* Lookup(Address);
+ PageMemoryRegion* Lookup(ConstAddress);
private:
// Using flat_map allows to improve locality to minimize cache misses and
// balance binary lookup.
- base::flat_map<Address, PageMemoryRegion*> set_;
+ base::flat_map<ConstAddress, PageMemoryRegion*> set_;
};
// Representation of the memory used for a Blink heap page.
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent.h b/chromium/third_party/blink/renderer/platform/heap/persistent.h
index 0b098c10186..fdc613835af 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent.h
@@ -39,10 +39,16 @@ class PersistentLocation final {
base::Location location_;
};
-#if BUILDFLAG(RAW_HEAP_SNAPSHOTS)
+#if !BUILDFLAG(FROM_HERE_USES_LOCATION_BUILTINS) && \
+ BUILDFLAG(RAW_HEAP_SNAPSHOTS)
+#if !BUILDFLAG(ENABLE_LOCATION_SOURCE)
+#define PERSISTENT_FROM_HERE \
+ PersistentLocation(::base::Location::CreateFromHere(__FILE__))
+#else
#define PERSISTENT_FROM_HERE \
PersistentLocation( \
::base::Location::CreateFromHere(__func__, __FILE__, __LINE__))
+#endif
#else
#define PERSISTENT_FROM_HERE PersistentLocation()
#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS)
@@ -298,7 +304,7 @@ class PersistentBase {
UninitializeUnsafe();
}
- void TracePersistent(Visitor* visitor) {
+ void TracePersistent(Visitor* visitor) const {
static_assert(sizeof(T), "T must be fully defined");
static_assert(IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
@@ -385,11 +391,12 @@ class PersistentBase {
}
static void HandleWeakPersistent(const WeakCallbackInfo&,
- void* persistent_pointer) {
+ const void* persistent_pointer) {
using Base =
PersistentBase<typename std::remove_const<T>::type,
weaknessConfiguration, crossThreadnessConfiguration>;
- Base* persistent = reinterpret_cast<Base*>(persistent_pointer);
+ Base* persistent =
+ reinterpret_cast<Base*>(const_cast<void*>(persistent_pointer));
T* object = persistent->Get();
if (object && !ThreadHeap::IsHeapObjectAlive(object))
ClearWeakPersistent(persistent);
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc b/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
index a0a6bb8c996..1449205eeb5 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
@@ -15,7 +15,7 @@ namespace {
class DummyGCBase final : public GarbageCollected<DummyGCBase> {
public:
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_node.h b/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
index bc76a0174b1..b591db1e793 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -74,7 +74,7 @@ class PersistentNode final {
// Instead we call the constructor with a TraceCallback which knows the
// type of the most specific child and calls trace directly. See
// TraceMethodDelegate in Visitor.h for how this is done.
- void TracePersistentNode(Visitor* visitor) {
+ void TracePersistentNode(Visitor* visitor) const {
DCHECK(!IsUnused());
DCHECK(trace_);
trace_(visitor, self_);
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_test.cc b/chromium/third_party/blink/renderer/platform/heap/persistent_test.cc
index bc30d02baba..474509cd185 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_test.cc
@@ -21,7 +21,7 @@ class Receiver : public GarbageCollected<Receiver> {
public:
void Increment(int* counter) { ++*counter; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
};
TEST_F(PersistentTest, BindCancellation) {
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state.cc b/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
index 27c2a8b8d19..477223077e2 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -109,7 +109,7 @@ constexpr base::TimeDelta kConcurrentMarkingStepDuration =
//
// TODO(omerkatz): kNumberOfMarkingTasks should be set heuristically
// instead of a constant.
-constexpr uint8_t kNumberOfConcurrentMarkingTasks = 1u;
+constexpr uint8_t kNumberOfConcurrentMarkingTasks = 3u;
constexpr size_t kMaxTerminationGCLoops = 20;
@@ -127,8 +127,6 @@ class WorkerPoolTaskRunner : public base::TaskRunner {
worker_pool::PostTask(location, WTF::CrossThreadBindOnce(std::move(task)));
return true;
}
-
- bool RunsTasksInCurrentSequence() const override { return false; }
};
} // namespace
@@ -147,6 +145,11 @@ class ThreadState::IncrementalMarkingScheduler {
ScheduleTask();
}
+ void Restart() {
+ DCHECK(!task_.IsActive());
+ ScheduleTask();
+ }
+
// Cancels incremental marking task in case there is any pending.
void Cancel() { task_.Cancel(); }
@@ -169,16 +172,15 @@ class ThreadState::IncrementalMarkingScheduler {
void Dispatch() {
switch (thread_state_->GetGCState()) {
- case ThreadState::kIncrementalGCScheduled:
- thread_state_->IncrementalMarkingStart(reason_);
- ScheduleTask();
- break;
case ThreadState::kIncrementalMarkingStepScheduled:
thread_state_->IncrementalMarkingStep(
BlinkGC::kNoHeapPointersOnStack,
next_incremental_marking_step_duration_);
UpdateIncrementalMarkingStepDuration();
- ScheduleTask();
+ if (thread_state_->GetGCState() !=
+ ThreadState::kIncrementalMarkingStepPaused) {
+ ScheduleTask();
+ }
break;
case ThreadState::kIncrementalMarkingFinalizeScheduled:
thread_state_->IncrementalMarkingFinalize();
@@ -221,8 +223,6 @@ ThreadState::ThreadState()
incremental_marking_scheduler_(
std::make_unique<IncrementalMarkingScheduler>(this)),
marker_scheduler_(std::make_unique<CancelableTaskScheduler>(
- base::MakeRefCounted<WorkerPoolTaskRunner>())),
- sweeper_scheduler_(std::make_unique<CancelableTaskScheduler>(
base::MakeRefCounted<WorkerPoolTaskRunner>())) {
DCHECK(CheckThread());
DCHECK(!**thread_specific_);
@@ -265,6 +265,7 @@ void ThreadState::AttachToIsolate(
v8_build_embedder_graph_ = v8_build_embedder_graph;
unified_heap_controller_.reset(new UnifiedHeapController(this));
isolate_->SetEmbedderHeapTracer(unified_heap_controller_.get());
+ unified_heap_controller_.get()->SetStackStart(WTF::GetStackStart());
if (v8::HeapProfiler* profiler = isolate->GetHeapProfiler()) {
profiler->AddBuildEmbedderGraphCallback(v8_build_embedder_graph, nullptr);
}
@@ -288,7 +289,8 @@ void ThreadState::RunTerminationGC() {
DCHECK(!IsMainThread());
DCHECK(CheckThread());
- FinishIncrementalMarkingIfRunning(BlinkGC::kNoHeapPointersOnStack,
+ FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType::kMajor,
+ BlinkGC::kNoHeapPointersOnStack,
BlinkGC::kIncrementalAndConcurrentMarking,
BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kThreadTerminationGC);
@@ -309,7 +311,8 @@ void ThreadState::RunTerminationGC() {
int current_count = GetPersistentRegion()->NodesInUse();
DCHECK_GE(current_count, 0);
while (current_count != old_count) {
- CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+ CollectGarbage(BlinkGC::CollectionType::kMajor,
+ BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
BlinkGC::kEagerSweeping,
BlinkGC::GCReason::kThreadTerminationGC);
// Release the thread-local static persistents that were
@@ -328,7 +331,8 @@ void ThreadState::RunTerminationGC() {
i < kMaxTerminationGCLoops && GetPersistentRegion()->NodesInUse();
i++) {
GetPersistentRegion()->PrepareForThreadStateTermination(this);
- CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+ CollectGarbage(BlinkGC::CollectionType::kMajor,
+ BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
BlinkGC::kEagerSweeping,
BlinkGC::GCReason::kThreadTerminationGC);
}
@@ -375,7 +379,9 @@ void ThreadState::VisitAsanFakeStackForPointer(MarkingVisitor* visitor,
NO_SANITIZE_ADDRESS
NO_SANITIZE_HWADDRESS
NO_SANITIZE_THREAD
-void ThreadState::VisitStack(MarkingVisitor* visitor, Address* end_of_stack) {
+void ThreadState::VisitStackImpl(MarkingVisitor* visitor,
+ Address* start_of_stack,
+ Address* end_of_stack) {
DCHECK_EQ(current_gc_data_.stack_state, BlinkGC::kHeapPointersOnStack);
// Ensure that current is aligned by address size otherwise the loop below
@@ -383,7 +389,7 @@ void ThreadState::VisitStack(MarkingVisitor* visitor, Address* end_of_stack) {
Address* current = reinterpret_cast<Address*>(
reinterpret_cast<intptr_t>(end_of_stack) & ~(sizeof(Address) - 1));
- for (; current < start_of_stack_; ++current) {
+ for (; current < start_of_stack; ++current) {
Address ptr = *current;
#if defined(MEMORY_SANITIZER)
// |ptr| may be uninitialized by design. Mark it as initialized to keep
@@ -394,10 +400,22 @@ void ThreadState::VisitStack(MarkingVisitor* visitor, Address* end_of_stack) {
__msan_unpoison(&ptr, sizeof(ptr));
#endif
heap_->CheckAndMarkPointer(visitor, ptr);
- VisitAsanFakeStackForPointer(visitor, ptr, start_of_stack_, end_of_stack);
+ VisitAsanFakeStackForPointer(visitor, ptr, start_of_stack, end_of_stack);
}
}
+void ThreadState::VisitStack(MarkingVisitor* visitor, Address* end_of_stack) {
+ VisitStackImpl(visitor, start_of_stack_, end_of_stack);
+}
+
+void ThreadState::VisitUnsafeStack(MarkingVisitor* visitor) {
+#if HAS_FEATURE(safe_stack)
+ VisitStackImpl(visitor,
+ static_cast<Address*>(__builtin___get_unsafe_stack_top()),
+ static_cast<Address*>(__builtin___get_unsafe_stack_ptr()));
+#endif // HAS_FEATURE(safe_stack)
+}
+
void ThreadState::VisitDOMWrappers(Visitor* visitor) {
if (v8_trace_roots_) {
ThreadHeapStatsCollector::Scope stats_scope(
@@ -424,6 +442,12 @@ void ThreadState::VisitPersistents(Visitor* visitor) {
}
}
+void ThreadState::VisitRememberedSets(MarkingVisitor* visitor) {
+ ThreadHeapStatsCollector::EnabledScope stats_scope(
+ Heap().stats_collector(), ThreadHeapStatsCollector::kVisitRememberedSets);
+ Heap().VisitRememberedSets(visitor);
+}
+
void ThreadState::VisitWeakPersistents(Visitor* visitor) {
ProcessHeap::GetCrossThreadWeakPersistentRegion().TraceNodes(visitor);
weak_persistent_region_->TraceNodes(visitor);
@@ -503,8 +527,7 @@ void ThreadState::PerformIdleLazySweep(base::TimeTicks deadline) {
ThreadHeapStatsCollector::EnabledScope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kLazySweepInIdle,
"idleDeltaInSeconds", (deadline - base::TimeTicks::Now()).InSecondsF());
- sweep_completed =
- Heap().AdvanceSweep(ThreadHeap::SweepingType::kMutator, deadline);
+ sweep_completed = Heap().AdvanceLazySweep(deadline);
// We couldn't finish the sweeping within the deadline.
// We request another idle task for the remaining sweeping.
if (sweep_completed) {
@@ -519,28 +542,15 @@ void ThreadState::PerformIdleLazySweep(base::TimeTicks deadline) {
}
}
-void ThreadState::PerformConcurrentSweep() {
+void ThreadState::PerformConcurrentSweep(base::JobDelegate* job) {
VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] "
<< "ConcurrentSweep";
- // As opposed to PerformIdleLazySweep, this function doesn't receive deadline
- // from the scheduler, but defines it itself.
- static constexpr base::TimeDelta kConcurrentSweepStepDuration =
- base::TimeDelta::FromMilliseconds(2);
- // Concurrent sweeper doesn't call finalizers - this guarantees that sweeping
- // is not called recursively.
ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope(
- Heap().stats_collector(), ThreadHeapStatsCollector::kConcurrentSweep);
- const bool finished = Heap().AdvanceSweep(
- ThreadHeap::SweepingType::kConcurrent,
- base::TimeTicks::Now() + kConcurrentSweepStepDuration);
- if (!finished) {
- // Reschedule itself. It is safe even if the task timeouts and reposts
- // itself while the mutator thread is waiting on CancelAndWait(). The
- // mutator thread will simply wake up and cancel the newly post task itself.
- sweeper_scheduler_->ScheduleTask(
- WTF::CrossThreadBindOnce(&ThreadState::PerformConcurrentSweep,
- WTF::CrossThreadUnretained(this)));
- }
+ Heap().stats_collector(),
+ ThreadHeapStatsCollector::kConcurrentSweepingStep);
+
+ if (Heap().AdvanceConcurrentSweep(job))
+ has_unswept_pages_.store(false, std::memory_order_relaxed);
}
void ThreadState::StartIncrementalMarking(BlinkGC::GCReason reason) {
@@ -570,13 +580,21 @@ void ThreadState::ScheduleConcurrentAndLazySweep() {
return;
}
- static constexpr size_t kNumberOfSweepingTasks = 1u;
-
- for (size_t i = 0; i < kNumberOfSweepingTasks; ++i) {
- sweeper_scheduler_->ScheduleTask(
- WTF::CrossThreadBindOnce(&ThreadState::PerformConcurrentSweep,
- WTF::CrossThreadUnretained(this)));
- }
+ has_unswept_pages_ = true;
+ sweeper_handle_ = base::PostJob(
+ FROM_HERE,
+ {base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ ConvertToBaseRepeatingCallback(
+ WTF::CrossThreadBindRepeating(&ThreadState::PerformConcurrentSweep,
+ WTF::CrossThreadUnretained(this))),
+ ConvertToBaseRepeatingCallback(WTF::CrossThreadBindRepeating(
+ [](ThreadState* state) -> size_t {
+ return state->has_unswept_pages_.load(std::memory_order_relaxed)
+ ? 1
+ : 0;
+ },
+ WTF::CrossThreadUnretained(this))));
}
void ThreadState::SchedulePreciseGC() {
@@ -628,7 +646,8 @@ void ThreadState::SetGCState(GCState gc_state) {
DCHECK(CheckThread());
VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled ||
gc_state_ == kIncrementalMarkingStepScheduled ||
- gc_state_ == kIncrementalGCScheduled);
+ gc_state_ == kIncrementalGCScheduled ||
+ gc_state_ == kIncrementalMarkingStepPaused);
break;
case kIncrementalMarkingFinalizeScheduled:
DCHECK(CheckThread());
@@ -700,7 +719,8 @@ void ThreadState::RunScheduledGC(BlinkGC::StackState stack_state) {
CollectAllGarbageForTesting();
break;
case kPreciseGCScheduled:
- CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+ CollectGarbage(BlinkGC::CollectionType::kMajor,
+ BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kPreciseGC);
break;
@@ -709,9 +729,11 @@ void ThreadState::RunScheduledGC(BlinkGC::StackState stack_state) {
}
}
-void ThreadState::AtomicPauseMarkPrologue(BlinkGC::StackState stack_state,
- BlinkGC::MarkingType marking_type,
- BlinkGC::GCReason reason) {
+void ThreadState::AtomicPauseMarkPrologue(
+ BlinkGC::CollectionType collection_type,
+ BlinkGC::StackState stack_state,
+ BlinkGC::MarkingType marking_type,
+ BlinkGC::GCReason reason) {
ThreadHeapStatsCollector::EnabledScope mark_prologue_scope(
Heap().stats_collector(),
ThreadHeapStatsCollector::kAtomicPauseMarkPrologue, "epoch", gc_age_,
@@ -719,10 +741,10 @@ void ThreadState::AtomicPauseMarkPrologue(BlinkGC::StackState stack_state,
EnterAtomicPause();
EnterNoAllocationScope();
EnterGCForbiddenScope();
- // Compaction needs to be canceled when incremental marking ends with a
- // conservative GC.
- if (stack_state == BlinkGC::kHeapPointersOnStack)
- Heap().Compaction()->Cancel();
+
+ if (HeapPointersOnStackForced()) {
+ stack_state = BlinkGC::kHeapPointersOnStack;
+ }
if (IsMarkingInProgress()) {
// Incremental marking is already in progress. Only update the state
@@ -736,18 +758,26 @@ void ThreadState::AtomicPauseMarkPrologue(BlinkGC::StackState stack_state,
available_concurrent_marking_task_ids_.clear();
}
#if DCHECK_IS_ON()
- MarkingWorklist* worklist = Heap().GetMarkingWorklist();
+ MarkingWorklist* marking_worklist = Heap().GetMarkingWorklist();
+ WriteBarrierWorklist* write_barrier_worklist =
+ Heap().GetWriteBarrierWorklist();
for (int concurrent_task = WorklistTaskId::ConcurrentThreadBase;
- concurrent_task < worklist->num_tasks(); ++concurrent_task) {
- DCHECK(worklist->IsLocalEmpty(concurrent_task));
+ concurrent_task < MarkingWorklist::kNumTasks; ++concurrent_task) {
+ DCHECK(marking_worklist->IsLocalEmpty(concurrent_task));
+ DCHECK(write_barrier_worklist->IsLocalEmpty(concurrent_task));
}
#endif // DCHECK_IS_ON()
+ // Compaction needs to be canceled when incremental marking ends with a
+ // conservative GC.
+ if (stack_state == BlinkGC::kHeapPointersOnStack)
+ Heap().Compaction()->Cancel();
DisableIncrementalMarkingBarrier();
current_gc_data_.reason = reason;
current_gc_data_.stack_state = stack_state;
Heap().stats_collector()->UpdateReason(reason);
} else {
- MarkPhasePrologue(stack_state, marking_type, reason);
+ DCHECK(!Heap().Compaction()->IsCompacting());
+ MarkPhasePrologue(collection_type, stack_state, marking_type, reason);
}
if (stack_state == BlinkGC::kNoHeapPointersOnStack) {
@@ -776,7 +806,7 @@ void ThreadState::CompleteSweep() {
if (!IsSweepingInProgress())
return;
- // completeSweep() can be called recursively if finalizers can allocate
+ // CompleteSweep() can be called recursively if finalizers can allocate
// memory and the allocation triggers completeSweep(). This check prevents
// the sweeping from being executed recursively.
if (SweepForbidden())
@@ -794,6 +824,10 @@ void ThreadState::CompleteSweep() {
ThreadHeapStatsCollector::EnabledScope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kCompleteSweep,
"forced", IsForcedGC(current_gc_data_.reason));
+ // Boost priority of sweeping job to complete ASAP and avoid taking time on
+ // the main thread.
+ if (sweeper_handle_)
+ sweeper_handle_.UpdatePriority(base::TaskPriority::USER_BLOCKING);
Heap().CompleteSweep();
SynchronizeAndFinishConcurrentSweeping();
@@ -809,7 +843,8 @@ void ThreadState::SynchronizeAndFinishConcurrentSweeping() {
DCHECK(SweepForbidden());
// Wait for concurrent sweepers.
- sweeper_scheduler_->CancelAndWait();
+ if (sweeper_handle_)
+ sweeper_handle_.Cancel();
// Concurrent sweepers may perform some work at the last stage (e.g.
// sweeping the last page and preparing finalizers).
@@ -890,6 +925,8 @@ void UpdateHistograms(const ThreadHeapStatsCollector::Event& event) {
UMA_HISTOGRAM_TIMES("BlinkGC.TimeForAtomicPhaseMarking",
event.atomic_marking_time());
UMA_HISTOGRAM_TIMES("BlinkGC.TimeForGCCycle", event.gc_cycle_time());
+ UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarkingRoots",
+ event.roots_marking_time());
UMA_HISTOGRAM_TIMES("BlinkGC.TimeForIncrementalMarking",
event.incremental_marking_time());
UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarking.Foreground",
@@ -916,15 +953,14 @@ void UpdateHistograms(const ThreadHeapStatsCollector::Event& event) {
"BlinkGC.TimeForGlobalWeakProcessing",
event.scope_data[ThreadHeapStatsCollector::kMarkWeakProcessing]);
- base::TimeDelta marking_duration = event.marking_time();
- constexpr size_t kMinObjectSizeForReportingThroughput = 1024 * 1024;
+ base::TimeDelta marking_duration = event.foreground_marking_time();
+ constexpr size_t kMinMarkedBytesForReportingThroughput = 1024 * 1024;
if (base::TimeTicks::IsHighResolution() &&
- (event.object_size_in_bytes_before_sweeping >
- kMinObjectSizeForReportingThroughput) &&
+ (event.marked_bytes > kMinMarkedBytesForReportingThroughput) &&
!marking_duration.is_zero()) {
DCHECK_GT(marking_duration.InMillisecondsF(), 0.0);
const int main_thread_marking_throughput_mb_per_s = static_cast<int>(
- static_cast<double>(event.object_size_in_bytes_before_sweeping) /
+ static_cast<double>(event.marked_bytes) /
marking_duration.InMillisecondsF() * 1000 / 1024 / 1024);
UMA_HISTOGRAM_COUNTS_100000("BlinkGC.MainThreadMarkingThroughput",
main_thread_marking_throughput_mb_per_s);
@@ -933,8 +969,10 @@ void UpdateHistograms(const ThreadHeapStatsCollector::Event& event) {
DEFINE_STATIC_LOCAL(
CustomCountHistogram, object_size_freed_by_heap_compaction,
("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50));
- object_size_freed_by_heap_compaction.Count(
- CappedSizeInKB(event.compaction_freed_bytes));
+ if (event.compaction_recorded_events) {
+ object_size_freed_by_heap_compaction.Count(
+ CappedSizeInKB(event.compaction_freed_bytes));
+ }
DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_before_gc_histogram,
("BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50));
@@ -1024,7 +1062,10 @@ void ThreadState::PushRegistersAndVisitStack() {
DCHECK(CheckThread());
DCHECK(IsGCForbidden());
DCHECK_EQ(current_gc_data_.stack_state, BlinkGC::kHeapPointersOnStack);
+ // Visit registers, native stack, and asan fake stack.
PushAllRegisters(this, ThreadState::VisitStackAfterPushingRegisters);
+ // For builds that use safe stack, also visit the unsafe stack.
+ VisitUnsafeStack(static_cast<MarkingVisitor*>(CurrentVisitor()));
}
void ThreadState::AddObserver(BlinkGCObserver* observer) {
@@ -1077,21 +1118,6 @@ void ThreadState::FreePersistentNode(PersistentRegion* persistent_region,
DCHECK(!static_persistents_.Contains(persistent_node));
}
-void ThreadState::RegisterPreFinalizer(void* object,
- PreFinalizerCallback callback) {
-#if DCHECK_IS_ON()
- DCHECK(CheckThread());
-#endif
- DCHECK(!SweepForbidden());
-
- HeapObjectHeader* header = HeapObjectHeader::FromInnerAddress(object);
- DCHECK(ordered_pre_finalizers_.end() ==
- std::find(ordered_pre_finalizers_.begin(),
- ordered_pre_finalizers_.end(),
- PreFinalizer{header, object, callback}));
- ordered_pre_finalizers_.push_back(PreFinalizer{header, object, callback});
-}
-
void ThreadState::InvokePreFinalizers() {
DCHECK(CheckThread());
DCHECK(!SweepForbidden());
@@ -1099,22 +1125,23 @@ void ThreadState::InvokePreFinalizers() {
ThreadHeapStatsCollector::Scope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kInvokePreFinalizers);
SweepForbiddenScope sweep_forbidden(this);
- // Pre finalizers are forbidden from allocating objects.
+ // Pre finalizers are forbidden from allocating objects
NoAllocationScope no_allocation_scope(this);
// Call the prefinalizers in the opposite order to their registration.
+ //
+ // Deque does not support modification during iteration, so
+ // copy items first.
+ //
+ // The prefinalizer callback wrapper returns |true| when its associated
+ // object is unreachable garbage and the prefinalizer callback has run.
+ // The registered prefinalizer entry must then be removed and deleted.
Deque<PreFinalizer> remaining_ordered_pre_finalizers;
for (auto rit = ordered_pre_finalizers_.rbegin();
rit != ordered_pre_finalizers_.rend(); ++rit) {
const PreFinalizer& pre_finalizer = *rit;
- // Check if pre-finalizer should be executed.
- if (pre_finalizer.header->IsMarked()) {
- // Re-queue for checking in next garbage collection.
+ if (!(pre_finalizer.second)(pre_finalizer.first))
remaining_ordered_pre_finalizers.push_front(pre_finalizer);
- } else {
- // Execute pre-finalizer.
- pre_finalizer.callback(pre_finalizer.object);
- }
}
ordered_pre_finalizers_ = std::move(remaining_ordered_pre_finalizers);
@@ -1151,7 +1178,8 @@ void ThreadState::IncrementalMarkingStart(BlinkGC::GCReason reason) {
DCHECK(!IsMarkingInProgress());
// Sweeping is performed in driver functions.
DCHECK(!IsSweepingInProgress());
- Heap().stats_collector()->NotifyMarkingStarted(reason);
+ Heap().stats_collector()->NotifyMarkingStarted(
+ BlinkGC::CollectionType::kMajor, reason);
{
ThreadHeapStatsCollector::EnabledScope stats_scope(
Heap().stats_collector(),
@@ -1159,7 +1187,8 @@ void ThreadState::IncrementalMarkingStart(BlinkGC::GCReason reason) {
BlinkGC::ToString(reason));
AtomicPauseScope atomic_pause_scope(this);
ScriptForbiddenScope script_forbidden_scope;
- MarkPhasePrologue(BlinkGC::kNoHeapPointersOnStack,
+ MarkPhasePrologue(BlinkGC::CollectionType::kMajor,
+ BlinkGC::kNoHeapPointersOnStack,
BlinkGC::kIncrementalAndConcurrentMarking, reason);
{
MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
@@ -1172,14 +1201,19 @@ void ThreadState::IncrementalMarkingStart(BlinkGC::GCReason reason) {
// No active concurrent markers yet, so it is safe to write to
// concurrently_marked_bytes_ without a lock.
concurrently_marked_bytes_ = 0;
- current_gc_data_.visitor->FlushMarkingWorklist();
+ current_gc_data_.visitor->FlushMarkingWorklists();
// Check that the marking worklist has enough private segments for all
// concurrent marking tasks.
const uint8_t max_concurrent_task_id =
WorklistTaskId::ConcurrentThreadBase +
kNumberOfConcurrentMarkingTasks;
- DCHECK_LE(max_concurrent_task_id,
- Heap().GetMarkingWorklist()->num_tasks());
+ static_assert(
+ MarkingWorklist::kNumTasks == WriteBarrierWorklist::kNumTasks,
+ "Marking worklist and write-barrier worklist should be the "
+ "same size");
+ static_assert(max_concurrent_task_id <= MarkingWorklist::kNumTasks,
+ "Number of concurrent marking tasks should not exceed "
+ "number of tasks in worlkist");
// Initialize concurrent marking task ids.
for (uint8_t i = WorklistTaskId::ConcurrentThreadBase;
i < max_concurrent_task_id; ++i) {
@@ -1218,7 +1252,7 @@ void ThreadState::IncrementalMarkingStep(BlinkGC::StackState stack_state,
if (base::FeatureList::IsEnabled(
blink::features::kBlinkHeapConcurrentMarking)) {
- complete = complete && ConcurrentMarkingStep();
+ complete = ConcurrentMarkingStep() && complete;
}
if (complete) {
@@ -1239,8 +1273,8 @@ void ThreadState::IncrementalMarkingStep(BlinkGC::StackState stack_state,
}
bool ThreadState::ConcurrentMarkingStep() {
- current_gc_data_.visitor->FlushMarkingWorklist();
- if (!Heap().GetMarkingWorklist()->IsGlobalPoolEmpty()) {
+ current_gc_data_.visitor->FlushMarkingWorklists();
+ if (Heap().HasWorkForConcurrentMarking()) {
ScheduleConcurrentMarking();
return false;
}
@@ -1263,11 +1297,13 @@ void ThreadState::IncrementalMarkingFinalize() {
// UMA accounting and allow follow up GCs if necessary.
DCHECK_EQ(BlinkGC::kIncrementalAndConcurrentMarking,
current_gc_data_.marking_type);
- CollectGarbage(BlinkGC::kNoHeapPointersOnStack, current_gc_data_.marking_type,
+ CollectGarbage(current_gc_data_.collection_type,
+ BlinkGC::kNoHeapPointersOnStack, current_gc_data_.marking_type,
BlinkGC::kConcurrentAndLazySweeping, current_gc_data_.reason);
}
bool ThreadState::FinishIncrementalMarkingIfRunning(
+ BlinkGC::CollectionType collection_type,
BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::SweepingType sweeping_type,
@@ -1279,14 +1315,23 @@ bool ThreadState::FinishIncrementalMarkingIfRunning(
if (IsUnifiedGCMarkingInProgress()) {
unified_heap_controller()->FinalizeTracing();
} else {
- RunAtomicPause(stack_state, marking_type, sweeping_type, reason);
+ RunAtomicPause(collection_type, stack_state, marking_type, sweeping_type,
+ reason);
}
return true;
}
return false;
}
-void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
+void ThreadState::RestartIncrementalMarkingIfPaused() {
+ if (GetGCState() != ThreadState::kIncrementalMarkingStepPaused)
+ return;
+ SetGCState(ThreadState::kIncrementalMarkingStepScheduled);
+ incremental_marking_scheduler_->Restart();
+}
+
+void ThreadState::CollectGarbage(BlinkGC::CollectionType collection_type,
+ BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::SweepingType sweeping_type,
BlinkGC::GCReason reason) {
@@ -1302,7 +1347,7 @@ void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
GetIsolate(), RuntimeCallStats::CounterId::kCollectGarbage);
const bool was_incremental_marking = FinishIncrementalMarkingIfRunning(
- stack_state, marking_type, sweeping_type, reason);
+ collection_type, stack_state, marking_type, sweeping_type, reason);
// We don't want floating garbage for the specific garbage collection types
// mentioned below. In this case we will follow up with a regular full
@@ -1315,8 +1360,9 @@ void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
if (should_do_full_gc) {
CompleteSweep();
SetGCState(kNoGCScheduled);
- Heap().stats_collector()->NotifyMarkingStarted(reason);
- RunAtomicPause(stack_state, marking_type, sweeping_type, reason);
+ Heap().stats_collector()->NotifyMarkingStarted(collection_type, reason);
+ RunAtomicPause(collection_type, stack_state, marking_type, sweeping_type,
+ reason);
}
const base::TimeDelta total_collect_garbage_time =
@@ -1423,6 +1469,7 @@ class ClearReferencesInDeadObjectsVisitor final
} // namespace
void ThreadState::AtomicPauseSweepAndCompact(
+ BlinkGC::CollectionType collection_type,
BlinkGC::MarkingType marking_type,
BlinkGC::SweepingType sweeping_type) {
ThreadHeapStatsCollector::EnabledScope stats(
@@ -1434,7 +1481,7 @@ void ThreadState::AtomicPauseSweepAndCompact(
DCHECK(InAtomicMarkingPause());
DCHECK(CheckThread());
- Heap().PrepareForSweep();
+ Heap().PrepareForSweep(collection_type);
// We have to set the GCPhase to Sweeping before calling pre-finalizers
// to disallow a GC during the pre-finalizers.
@@ -1449,14 +1496,11 @@ void ThreadState::AtomicPauseSweepAndCompact(
unified_heap_controller()->IterateTracedGlobalHandles(&visitor);
}
- // Allocation is allowed during the pre-finalizers and destructors.
- // However, they must not mutate an object graph in a way in which
- // a dead object gets resurrected.
InvokePreFinalizers();
- // Slots filtering requires liveness information which is only present before
- // sweeping any arena.
- {
+ if (collection_type == BlinkGC::CollectionType::kMajor) {
+ // Slots filtering requires liveness information which is only present
+ // before sweeping any arena.
ThreadHeapStatsCollector::Scope stats_scope(
Heap().stats_collector(),
ThreadHeapStatsCollector::kAtomicPauseCompaction);
@@ -1467,14 +1511,14 @@ void ThreadState::AtomicPauseSweepAndCompact(
// Last point where all mark bits are present.
VerifyMarking(marking_type);
- // Any sweep compaction must happen after pre-finalizers, as it will
- // finalize dead objects in compactable arenas (e.g., backing stores
- // for container objects.)
- //
- // As per-contract for prefinalizers, those finalizable objects must
- // still be accessible when the prefinalizer runs, hence we cannot
- // schedule compaction until those have run.
- {
+ if (collection_type == BlinkGC::CollectionType::kMajor) {
+ // Any sweep compaction must happen after pre-finalizers, as it will
+ // finalize dead objects in compactable arenas (e.g., backing stores
+ // for container objects.)
+ //
+ // As per-contract for prefinalizers, those finalizable objects must
+ // still be accessible when the prefinalizer runs, hence we cannot
+ // schedule compaction until those have run.
SweepForbiddenScope scope(this);
NoAllocationScope no_allocation_scope(this);
Heap().Compact();
@@ -1573,7 +1617,8 @@ void ThreadState::PoisonUnmarkedObjects() {
}
#endif // ADDRESS_SANITIZER
-void ThreadState::RunAtomicPause(BlinkGC::StackState stack_state,
+void ThreadState::RunAtomicPause(BlinkGC::CollectionType collection_type,
+ BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::SweepingType sweeping_type,
BlinkGC::GCReason reason) {
@@ -1582,11 +1627,11 @@ void ThreadState::RunAtomicPause(BlinkGC::StackState stack_state,
TRACE_EVENT1("blink_gc,devtools.timeline", "BlinkGC.AtomicPhase", "forced",
IsForcedGC(reason));
- AtomicPauseMarkPrologue(stack_state, marking_type, reason);
+ AtomicPauseMarkPrologue(collection_type, stack_state, marking_type, reason);
AtomicPauseMarkRoots(stack_state, marking_type, reason);
AtomicPauseMarkTransitiveClosure();
AtomicPauseMarkEpilogue(marking_type);
- AtomicPauseSweepAndCompact(marking_type, sweeping_type);
+ AtomicPauseSweepAndCompact(collection_type, marking_type, sweeping_type);
AtomicPauseEpilogue();
}
@@ -1599,19 +1644,30 @@ MarkingVisitor::MarkingMode GetMarkingMode(bool should_compact) {
} // namespace
-void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
+void ThreadState::MarkPhasePrologue(BlinkGC::CollectionType collection_type,
+ BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::GCReason reason) {
SetGCPhase(GCPhase::kMarking);
- Heap().SetupWorklists();
const bool compaction_enabled =
Heap().Compaction()->ShouldCompact(stack_state, marking_type, reason);
+
+ Heap().SetupWorklists(compaction_enabled);
+
if (compaction_enabled) {
Heap().Compaction()->Initialize(this);
}
+#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION)
+ if (collection_type == BlinkGC::CollectionType::kMajor) {
+ // Unmark heap before doing major collection cycle.
+ Heap().Unmark();
+ }
+#endif
+
current_gc_data_.reason = reason;
+ current_gc_data_.collection_type = collection_type;
current_gc_data_.visitor =
IsUnifiedGCMarkingInProgress()
? std::make_unique<UnifiedHeapMarkingVisitor>(
@@ -1623,6 +1679,9 @@ void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
}
void ThreadState::MarkPhaseVisitRoots() {
+ ThreadHeapStatsCollector::EnabledScope stats_scope(
+ Heap().stats_collector(), ThreadHeapStatsCollector::kVisitRoots);
+
Visitor* visitor = current_gc_data_.visitor.get();
VisitPersistents(visitor);
@@ -1644,10 +1703,15 @@ void ThreadState::MarkPhaseVisitRoots() {
}
if (current_gc_data_.stack_state == BlinkGC::kHeapPointersOnStack) {
- ThreadHeapStatsCollector::Scope stats_scope(
+ ThreadHeapStatsCollector::Scope stack_stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kVisitStackRoots);
PushRegistersAndVisitStack();
}
+
+ // Visit remembered sets (card tables) for minor collections.
+ if (current_gc_data_.collection_type == BlinkGC::CollectionType::kMinor) {
+ VisitRememberedSets(static_cast<MarkingVisitor*>(visitor));
+ }
}
bool ThreadState::MarkPhaseAdvanceMarking(base::TimeTicks deadline) {
@@ -1710,8 +1774,8 @@ void ThreadState::CollectAllGarbageForTesting(BlinkGC::StackState stack_state) {
// We need to run multiple GCs to collect a chain of persistent handles.
size_t previous_live_objects = 0;
for (int i = 0; i < 5; ++i) {
- CollectGarbage(stack_state, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping,
+ CollectGarbage(BlinkGC::CollectionType::kMajor, stack_state,
+ BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
BlinkGC::GCReason::kForcedGCForTesting);
const size_t live_objects =
Heap().stats_collector()->previous().marked_bytes;
@@ -1743,7 +1807,8 @@ void ThreadState::PerformConcurrentMark() {
VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] "
<< "ConcurrentMark";
ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope(
- Heap().stats_collector(), ThreadHeapStatsCollector::kConcurrentMark);
+ Heap().stats_collector(),
+ ThreadHeapStatsCollector::kConcurrentMarkingStep);
uint8_t task_id;
{
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state.h b/chromium/third_party/blink/renderer/platform/heap/thread_state.h
index 42b55d95df5..f41cd050868 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state.h
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state.h
@@ -31,10 +31,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_
+#include <atomic>
#include <memory>
#include "base/macros.h"
#include "base/synchronization/lock.h"
+#include "base/task/post_job.h"
#include "third_party/blink/renderer/platform/heap/atomic_entry_flag.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
#include "third_party/blink/renderer/platform/heap/threading_traits.h"
@@ -62,7 +64,6 @@ class IncrementalMarkingScope;
} // namespace incremental_marking_test
class CancelableTaskScheduler;
-class HeapObjectHeader;
class MarkingVisitor;
class PersistentNode;
class PersistentRegion;
@@ -94,13 +95,17 @@ class Visitor;
// Member<Bar> bar_;
// };
#define USING_PRE_FINALIZER(Class, preFinalizer) \
- private: \
- static void PreFinalizerDispatch(void* object) { \
- reinterpret_cast<Class*>(object)->Class::preFinalizer(); \
+ public: \
+ static bool InvokePreFinalizer(void* object) { \
+ Class* self = reinterpret_cast<Class*>(object); \
+ if (ThreadHeap::IsHeapObjectAlive(self)) \
+ return false; \
+ self->Class::preFinalizer(); \
+ return true; \
} \
\
- friend class ThreadState::PreFinalizerRegistration<Class>; \
- ThreadState::PreFinalizerRegistration<Class> prefinalizer_dummy_{this}; \
+ private: \
+ ThreadState::PrefinalizerRegistration<Class> prefinalizer_dummy_{this}; \
using UsingPreFinalizerMacroNeedsTrailingSemiColon = char
class PLATFORM_EXPORT BlinkGCObserver {
@@ -130,16 +135,24 @@ class PLATFORM_EXPORT ThreadState final {
// Register the pre-finalizer for the |self| object. The class T be using
// USING_PRE_FINALIZER() macro.
template <typename T>
- class PreFinalizerRegistration final {
+ class PrefinalizerRegistration final {
DISALLOW_NEW();
public:
- PreFinalizerRegistration(T* self) {
- static_assert(sizeof(&T::PreFinalizerDispatch) > 0,
+ PrefinalizerRegistration(T* self) {
+ static_assert(sizeof(&T::InvokePreFinalizer) > 0,
"USING_PRE_FINALIZER(T) must be defined.");
ThreadState* state =
ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
- state->RegisterPreFinalizer(self, T::PreFinalizerDispatch);
+#if DCHECK_IS_ON()
+ DCHECK(state->CheckThread());
+#endif
+ DCHECK(!state->SweepForbidden());
+ DCHECK(std::find(state->ordered_pre_finalizers_.begin(),
+ state->ordered_pre_finalizers_.end(),
+ PreFinalizer(self, T::InvokePreFinalizer)) ==
+ state->ordered_pre_finalizers_.end());
+ state->ordered_pre_finalizers_.emplace_back(self, T::InvokePreFinalizer);
}
};
@@ -169,11 +182,11 @@ class PLATFORM_EXPORT ThreadState final {
class AtomicPauseScope;
class GCForbiddenScope;
class LsanDisabledScope;
- class MainThreadGCForbiddenScope;
class NoAllocationScope;
class StatisticsCollector;
struct Statistics;
class SweepForbiddenScope;
+ class HeapPointersOnStackScope;
using V8TraceRootsCallback = void (*)(v8::Isolate*, Visitor*);
using V8BuildEmbedderGraphCallback = void (*)(v8::Isolate*,
@@ -240,7 +253,7 @@ class PLATFORM_EXPORT ThreadState final {
}
void PerformIdleLazySweep(base::TimeTicks deadline);
- void PerformConcurrentSweep();
+ void PerformConcurrentSweep(base::JobDelegate*);
void SchedulePreciseGC();
void ScheduleForcedGCForTesting();
@@ -279,7 +292,8 @@ class PLATFORM_EXPORT ThreadState final {
void EnableCompactionForNextGCForTesting();
- bool FinishIncrementalMarkingIfRunning(BlinkGC::StackState,
+ bool FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType,
+ BlinkGC::StackState,
BlinkGC::MarkingType,
BlinkGC::SweepingType,
BlinkGC::GCReason);
@@ -287,6 +301,8 @@ class PLATFORM_EXPORT ThreadState final {
void EnableIncrementalMarkingBarrier();
void DisableIncrementalMarkingBarrier();
+ void RestartIncrementalMarkingIfPaused();
+
void CompleteSweep();
// Returns whether it is currently allowed to allocate an object. Mainly used
@@ -335,7 +351,8 @@ class PLATFORM_EXPORT ThreadState final {
v8::Isolate* GetIsolate() const { return isolate_; }
// Use CollectAllGarbageForTesting below for testing!
- void CollectGarbage(BlinkGC::StackState,
+ void CollectGarbage(BlinkGC::CollectionType,
+ BlinkGC::StackState,
BlinkGC::MarkingType,
BlinkGC::SweepingType,
BlinkGC::GCReason);
@@ -354,6 +371,12 @@ class PLATFORM_EXPORT ThreadState final {
return &FromObject(object)->Heap() == &Heap();
}
+ ALWAYS_INLINE bool IsOnStack(Address address) const {
+ return reinterpret_cast<Address>(start_of_stack_) >= address &&
+ address >= (reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(
+ WTF::GetCurrentStackPosition())));
+ }
+
int GcAge() const { return gc_age_; }
MarkingVisitor* CurrentVisitor() const {
@@ -366,17 +389,6 @@ class PLATFORM_EXPORT ThreadState final {
private:
class IncrementalMarkingScheduler;
- using PreFinalizerCallback = void (*)(void*);
- struct PreFinalizer {
- HeapObjectHeader* header;
- void* object;
- PreFinalizerCallback callback;
-
- bool operator==(const PreFinalizer& other) const {
- return object == other.object && callback == other.callback;
- }
- };
-
// Duration of one incremental marking step. Should be short enough that it
// doesn't cause jank even though it is scheduled as a normal task.
static constexpr base::TimeDelta kDefaultIncrementalMarkingStepDuration =
@@ -428,7 +440,8 @@ class PLATFORM_EXPORT ThreadState final {
// The following methods are used to compose RunAtomicPause. Public users
// should use the CollectGarbage entrypoint. Internal users should use these
// methods to compose a full garbage collection.
- void AtomicPauseMarkPrologue(BlinkGC::StackState,
+ void AtomicPauseMarkPrologue(BlinkGC::CollectionType,
+ BlinkGC::StackState,
BlinkGC::MarkingType,
BlinkGC::GCReason);
void AtomicPauseMarkRoots(BlinkGC::StackState,
@@ -436,20 +449,23 @@ class PLATFORM_EXPORT ThreadState final {
BlinkGC::GCReason);
void AtomicPauseMarkTransitiveClosure();
void AtomicPauseMarkEpilogue(BlinkGC::MarkingType);
- void AtomicPauseSweepAndCompact(BlinkGC::MarkingType marking_type,
+ void AtomicPauseSweepAndCompact(BlinkGC::CollectionType,
+ BlinkGC::MarkingType marking_type,
BlinkGC::SweepingType sweeping_type);
void AtomicPauseEpilogue();
// RunAtomicPause composes the final atomic pause that finishes a mark-compact
// phase of a garbage collection. Depending on SweepingType it may also finish
// sweeping or schedule lazy/concurrent sweeping.
- void RunAtomicPause(BlinkGC::StackState,
+ void RunAtomicPause(BlinkGC::CollectionType,
+ BlinkGC::StackState,
BlinkGC::MarkingType,
BlinkGC::SweepingType,
BlinkGC::GCReason);
// The version is needed to be able to start incremental marking.
- void MarkPhasePrologue(BlinkGC::StackState,
+ void MarkPhasePrologue(BlinkGC::CollectionType,
+ BlinkGC::StackState,
BlinkGC::MarkingType,
BlinkGC::GCReason);
void MarkPhaseEpilogue(BlinkGC::MarkingType);
@@ -463,7 +479,9 @@ class PLATFORM_EXPORT ThreadState final {
// Visit local thread stack and trace all pointers conservatively. Never call
// directly but always call through |PushRegistersAndVisitStack|.
+ void VisitStackImpl(MarkingVisitor*, Address*, Address*);
void VisitStack(MarkingVisitor*, Address*);
+ void VisitUnsafeStack(MarkingVisitor*);
// Visit the asan fake stack frame corresponding to a slot on the real machine
// stack if there is one. Never call directly but always call through
@@ -482,6 +500,9 @@ class PLATFORM_EXPORT ThreadState final {
// Visit all DOM wrappers allocatd on this thread.
void VisitDOMWrappers(Visitor*);
+ // Visit card tables (remembered sets) containing inter-generational pointers.
+ void VisitRememberedSets(MarkingVisitor*);
+
// Incremental marking implementation functions.
void IncrementalMarkingStartForTesting();
void IncrementalMarkingStart(BlinkGC::GCReason);
@@ -513,7 +534,6 @@ class PLATFORM_EXPORT ThreadState final {
void SynchronizeAndFinishConcurrentSweeping();
- void RegisterPreFinalizer(void*, PreFinalizerCallback);
void InvokePreFinalizers();
// Adds the given observer to the ThreadState's observer list. This doesn't
@@ -531,6 +551,13 @@ class PLATFORM_EXPORT ThreadState final {
reason == BlinkGC::GCReason::kForcedGCForTesting;
}
+ // Returns whether stack scanning is forced. This is currently only used in
+ // platform tests where non nested tasks can be run with heap pointers on
+ // stack.
+ bool HeapPointersOnStackForced() const {
+ return heap_pointers_on_stack_forced_;
+ }
+
#if defined(ADDRESS_SANITIZER)
// Poisons payload of unmarked objects.
//
@@ -551,6 +578,7 @@ class PLATFORM_EXPORT ThreadState final {
bool in_atomic_pause_ = false;
bool sweep_forbidden_ = false;
+ bool heap_pointers_on_stack_forced_ = false;
bool incremental_marking_ = false;
bool should_optimize_for_load_time_ = false;
size_t no_allocation_count_ = 0;
@@ -562,6 +590,9 @@ class PLATFORM_EXPORT ThreadState final {
BlinkGC::GCReason reason_for_scheduled_gc_ =
BlinkGC::GCReason::kForcedGCForTesting;
+ using PreFinalizerCallback = bool (*)(void*);
+ using PreFinalizer = std::pair<void*, PreFinalizerCallback>;
+
// Pre-finalizers are called in the reverse order in which they are
// registered by the constructors (including constructors of Mixin objects)
// for an object, by processing the ordered_pre_finalizers_ back-to-front.
@@ -587,6 +618,7 @@ class PLATFORM_EXPORT ThreadState final {
int gc_age_ = 0;
struct GCData {
+ BlinkGC::CollectionType collection_type;
BlinkGC::StackState stack_state;
BlinkGC::MarkingType marking_type;
BlinkGC::GCReason reason;
@@ -602,14 +634,15 @@ class PLATFORM_EXPORT ThreadState final {
base::Lock concurrent_marker_bootstrapping_lock_;
size_t concurrently_marked_bytes_ = 0;
- std::unique_ptr<CancelableTaskScheduler> sweeper_scheduler_;
+ base::JobHandle sweeper_handle_;
+ std::atomic_bool has_unswept_pages_{false};
friend class BlinkGCObserver;
friend class incremental_marking_test::IncrementalMarkingScope;
friend class IncrementalMarkingTestDriver;
friend class HeapAllocator;
template <typename T>
- friend class PreFinalizerRegistration;
+ friend class PrefinalizerRegistration;
friend class TestGCScope;
friend class TestSupportingGC;
friend class ThreadStateSchedulingTest;
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state_scopes.h b/chromium/third_party/blink/renderer/platform/heap/thread_state_scopes.h
index 0dea83fe654..bde958dc4ad 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state_scopes.h
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state_scopes.h
@@ -47,19 +47,6 @@ class ThreadState::SweepForbiddenScope final {
ThreadState* const state_;
};
-class ThreadState::MainThreadGCForbiddenScope final {
- STACK_ALLOCATED();
-
- public:
- MainThreadGCForbiddenScope() : thread_state_(ThreadState::MainThreadState()) {
- thread_state_->EnterGCForbiddenScope();
- }
- ~MainThreadGCForbiddenScope() { thread_state_->LeaveGCForbiddenScope(); }
-
- private:
- ThreadState* const thread_state_;
-};
-
class ThreadState::GCForbiddenScope final {
STACK_ALLOCATED();
@@ -90,6 +77,23 @@ class ThreadState::AtomicPauseScope final {
GCForbiddenScope gc_forbidden_scope;
};
+class ThreadState::HeapPointersOnStackScope final {
+ STACK_ALLOCATED();
+
+ public:
+ explicit HeapPointersOnStackScope(ThreadState* state) : state_(state) {
+ DCHECK(!state_->heap_pointers_on_stack_forced_);
+ state_->heap_pointers_on_stack_forced_ = true;
+ }
+ ~HeapPointersOnStackScope() {
+ DCHECK(state_->heap_pointers_on_stack_forced_);
+ state_->heap_pointers_on_stack_forced_ = false;
+ }
+
+ private:
+ ThreadState* const state_;
+};
+
#if defined(LEAK_SANITIZER)
class ThreadState::LsanDisabledScope final {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/platform/heap/threading_traits.h b/chromium/third_party/blink/renderer/platform/heap/threading_traits.h
index 3c5579ff1f7..95fa0c7e20a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/threading_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/threading_traits.h
@@ -32,7 +32,7 @@ enum ThreadAffinity {
// Remove them.
class Node;
class NodeList;
-class NodeRareDataBase;
+class NodeRareData;
template <
typename T,
@@ -40,7 +40,7 @@ template <
WTF::IsSubclass<typename std::remove_const<T>::type, Node>::value ||
WTF::IsSubclass<typename std::remove_const<T>::type, NodeList>::value ||
WTF::IsSubclass<typename std::remove_const<T>::type,
- NodeRareDataBase>::value>
+ NodeRareData>::value>
struct DefaultThreadingTrait;
template <typename T>
@@ -56,10 +56,6 @@ struct DefaultThreadingTrait<T, true> {
};
class HeapAllocator;
-template <typename Table>
-class HeapHashTableBacking;
-template <typename T, typename Traits>
-class HeapVectorBacking;
template <typename T>
class Member;
template <typename T>
@@ -118,12 +114,6 @@ struct ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator>> {
static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity;
};
-template <typename T, typename Traits>
-struct ThreadingTrait<HeapVectorBacking<T, Traits>> {
- STATIC_ONLY(ThreadingTrait);
- static const ThreadAffinity kAffinity = ThreadingTrait<T>::Affinity;
-};
-
template <typename T, size_t inlineCapacity>
struct ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator>> {
STATIC_ONLY(ThreadingTrait);
@@ -136,25 +126,13 @@ struct ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator>> {
static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity;
};
-template <typename Table>
-struct ThreadingTrait<HeapHashTableBacking<Table>> {
- STATIC_ONLY(ThreadingTrait);
- using Key = typename Table::KeyType;
- using Value = typename Table::ValueType;
- static const ThreadAffinity kAffinity =
- (ThreadingTrait<Key>::Affinity == kMainThreadOnly) &&
- (ThreadingTrait<Value>::Affinity == kMainThreadOnly)
- ? kMainThreadOnly
- : kAnyThread;
-};
-
template <typename T, typename U, typename V, typename W, typename X>
class HeapHashMap;
template <typename T, typename U, typename V>
class HeapHashSet;
template <typename T, wtf_size_t inlineCapacity>
class HeapVector;
-template <typename T, wtf_size_t inlineCapacity>
+template <typename T>
class HeapDeque;
template <typename T, typename U, typename V>
class HeapHashCountedSet;
@@ -174,9 +152,9 @@ struct ThreadingTrait<HeapVector<T, inlineCapacity>>
: public ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator>> {
STATIC_ONLY(ThreadingTrait);
};
-template <typename T, size_t inlineCapacity>
-struct ThreadingTrait<HeapDeque<T, inlineCapacity>>
- : public ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator>> {
+template <typename T>
+struct ThreadingTrait<HeapDeque<T>>
+ : public ThreadingTrait<Deque<T, 0, HeapAllocator>> {
STATIC_ONLY(ThreadingTrait);
};
template <typename T, typename U, typename V>
diff --git a/chromium/third_party/blink/renderer/platform/heap/trace_traits.h b/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
index 583aa7f78d3..4333dbf1edb 100644
--- a/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
@@ -21,6 +21,8 @@
namespace blink {
+template <typename Table>
+class HeapHashTableBacking;
template <typename ValueArg, wtf_size_t inlineCapacity>
class HeapListHashSetAllocator;
template <typename T>
@@ -35,11 +37,11 @@ template <typename T>
struct AdjustPointerTrait<T, false> {
STATIC_ONLY(AdjustPointerTrait);
- static TraceDescriptor GetTraceDescriptor(void* self) {
+ static TraceDescriptor GetTraceDescriptor(const void* self) {
return {self, TraceTrait<T>::Trace};
}
- static HeapObjectHeader* GetHeapObjectHeader(void* self) {
+ static HeapObjectHeader* GetHeapObjectHeader(const void* self) {
return HeapObjectHeader::FromPayload(self);
}
};
@@ -48,12 +50,12 @@ template <typename T>
struct AdjustPointerTrait<T, true> {
STATIC_ONLY(AdjustPointerTrait);
- static TraceDescriptor GetTraceDescriptor(void* self) {
- return static_cast<T*>(self)->GetTraceDescriptor();
+ static TraceDescriptor GetTraceDescriptor(const void* self) {
+ return static_cast<const T*>(self)->GetTraceDescriptor();
}
- static HeapObjectHeader* GetHeapObjectHeader(void* self) {
- return static_cast<T*>(self)->GetHeapObjectHeader();
+ static HeapObjectHeader* GetHeapObjectHeader(const void* self) {
+ return static_cast<const T*>(self)->GetHeapObjectHeader();
}
};
@@ -63,13 +65,13 @@ struct TraceIfNeeded;
template <typename T>
struct TraceIfNeeded<T, false> {
STATIC_ONLY(TraceIfNeeded);
- static void Trace(blink::Visitor*, T&) {}
+ static void Trace(Visitor*, const T&) {}
};
template <typename T>
struct TraceIfNeeded<T, true> {
STATIC_ONLY(TraceIfNeeded);
- static void Trace(blink::Visitor* visitor, T& t) { visitor->Trace(t); }
+ static void Trace(Visitor* visitor, const T& t) { visitor->Trace(t); }
};
template <WTF::WeakHandlingFlag weakness,
@@ -87,9 +89,9 @@ struct TraceCollectionIfEnabled<weakness,
WTF::kNoWeakHandling> {
STATIC_ONLY(TraceCollectionIfEnabled);
- static bool IsAlive(T&) { return true; }
+ static bool IsAlive(const T&) { return true; }
- static bool Trace(blink::Visitor*, void*) {
+ static bool Trace(Visitor*, const void*) {
static_assert(!WTF::IsTraceableInCollectionTrait<Traits>::value,
"T should not be traced");
return false;
@@ -104,9 +106,9 @@ struct TraceCollectionIfEnabled<WTF::kNoWeakHandling,
WTF::kWeakHandling> {
STATIC_ONLY(TraceCollectionIfEnabled);
- static bool Trace(blink::Visitor* visitor, void* t) {
+ static bool Trace(Visitor* visitor, const void* t) {
return WTF::TraceInCollectionTrait<WTF::kNoWeakHandling, T, Traits>::Trace(
- visitor, *reinterpret_cast<T*>(t));
+ visitor, *reinterpret_cast<const T*>(t));
}
};
@@ -118,16 +120,16 @@ template <WTF::WeakHandlingFlag weakness,
struct TraceCollectionIfEnabled {
STATIC_ONLY(TraceCollectionIfEnabled);
- static bool IsAlive(T& traceable) {
+ static bool IsAlive(const T& traceable) {
return WTF::TraceInCollectionTrait<weakness, T, Traits>::IsAlive(traceable);
}
- static bool Trace(blink::Visitor* visitor, void* t) {
+ static bool Trace(Visitor* visitor, const void* t) {
static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value ||
weakness == WTF::kWeakHandling,
"Traits should be traced");
return WTF::TraceInCollectionTrait<weakness, T, Traits>::Trace(
- visitor, *reinterpret_cast<T*>(t));
+ visitor, *reinterpret_cast<const T*>(t));
}
};
@@ -148,120 +150,32 @@ struct TraceTrait {
STATIC_ONLY(TraceTrait);
public:
- static TraceDescriptor GetTraceDescriptor(void* self) {
- return AdjustPointerTrait<T>::GetTraceDescriptor(static_cast<T*>(self));
+ static TraceDescriptor GetTraceDescriptor(const void* self) {
+ return AdjustPointerTrait<T>::GetTraceDescriptor(
+ static_cast<const T*>(self));
}
- static TraceDescriptor GetWeakTraceDescriptor(void* self) {
+ static TraceDescriptor GetWeakTraceDescriptor(const void* self) {
return {self, nullptr};
}
- static HeapObjectHeader* GetHeapObjectHeader(void* self) {
- return AdjustPointerTrait<T>::GetHeapObjectHeader(static_cast<T*>(self));
+ static HeapObjectHeader* GetHeapObjectHeader(const void* self) {
+ return AdjustPointerTrait<T>::GetHeapObjectHeader(
+ static_cast<const T*>(self));
}
- static void Trace(Visitor*, void* self);
+ static void Trace(Visitor*, const void* self);
};
template <typename T>
struct TraceTrait<const T> : public TraceTrait<T> {};
template <typename T>
-void TraceTrait<T>::Trace(Visitor* visitor, void* self) {
+void TraceTrait<T>::Trace(Visitor* visitor, const void* self) {
static_assert(WTF::IsTraceable<T>::value, "T should not be traced");
- static_cast<T*>(self)->Trace(visitor);
+ static_cast<T*>(const_cast<void*>(self))->Trace(visitor);
}
-template <typename T, typename Traits>
-struct TraceTrait<HeapVectorBacking<T, Traits>> {
- STATIC_ONLY(TraceTrait);
- using Backing = HeapVectorBacking<T, Traits>;
-
- public:
- static TraceDescriptor GetTraceDescriptor(void* self) {
- return {self, TraceTrait<Backing>::Trace};
- }
-
- static void Trace(blink::Visitor* visitor, void* self) {
- static_assert(!WTF::IsWeak<T>::value,
- "Weakness is not supported in HeapVector and HeapDeque");
- if (WTF::IsTraceableInCollectionTrait<Traits>::value) {
- WTF::TraceInCollectionTrait<WTF::kNoWeakHandling,
- HeapVectorBacking<T, Traits>,
- void>::Trace(visitor, self);
- }
- }
-};
-
-// The trace trait for the heap hashtable backing is used when we find a
-// direct pointer to the backing from the conservative stack scanner. This
-// normally indicates that there is an ongoing iteration over the table, and so
-// we disable weak processing of table entries. When the backing is found
-// through the owning hash table we mark differently, in order to do weak
-// processing.
-template <typename Table>
-struct TraceTrait<HeapHashTableBacking<Table>> {
- STATIC_ONLY(TraceTrait);
- using Backing = HeapHashTableBacking<Table>;
- using ValueType = typename Table::ValueTraits::TraitType;
- using Traits = typename Table::ValueTraits;
-
- public:
- static TraceDescriptor GetTraceDescriptor(void* self) {
- return {self, Trace<WTF::kNoWeakHandling>};
- }
-
- static TraceDescriptor GetWeakTraceDescriptor(void* self) {
- return GetWeakTraceDescriptorImpl<ValueType>::GetWeakTraceDescriptor(self);
- }
-
- template <WTF::WeakHandlingFlag WeakHandling = WTF::kNoWeakHandling>
- static void Trace(Visitor* visitor, void* self) {
- static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value ||
- WTF::IsWeak<ValueType>::value,
- "T should not be traced");
- WTF::TraceInCollectionTrait<WeakHandling, Backing, void>::Trace(visitor,
- self);
- }
-
- private:
- template <typename ValueType>
- struct GetWeakTraceDescriptorImpl {
- static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
- return {backing, nullptr};
- }
- };
-
- template <typename K, typename V>
- struct GetWeakTraceDescriptorImpl<WTF::KeyValuePair<K, V>> {
- static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
- return GetWeakTraceDescriptorKVPImpl<K, V>::GetWeakTraceDescriptor(
- backing);
- }
-
- template <typename KeyType,
- typename ValueType,
- bool ephemeron_semantics = (WTF::IsWeak<KeyType>::value &&
- !WTF::IsWeak<ValueType>::value &&
- WTF::IsTraceable<ValueType>::value) ||
- (WTF::IsWeak<ValueType>::value &&
- !WTF::IsWeak<KeyType>::value &&
- WTF::IsTraceable<KeyType>::value)>
- struct GetWeakTraceDescriptorKVPImpl {
- static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
- return {backing, nullptr};
- }
- };
-
- template <typename KeyType, typename ValueType>
- struct GetWeakTraceDescriptorKVPImpl<KeyType, ValueType, true> {
- static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
- return {backing, Trace<WTF::kWeakHandling>};
- }
- };
- };
-};
-
// This trace trait for std::pair will null weak members if their referent is
// collected. If you have a collection that contain weakness it does not remove
// entries from the collection that contain nulled weak members.
@@ -270,7 +184,7 @@ struct TraceTrait<std::pair<T, U>> {
STATIC_ONLY(TraceTrait);
public:
- static void Trace(blink::Visitor* visitor, std::pair<T, U>* pair) {
+ static void Trace(Visitor* visitor, const std::pair<T, U>* pair) {
TraceIfNeeded<T>::Trace(visitor, pair->first);
TraceIfNeeded<U>::Trace(visitor, pair->second);
}
@@ -285,7 +199,7 @@ struct TraceTrait<base::Optional<T>> {
STATIC_ONLY(TraceTrait);
public:
- static void Trace(blink::Visitor* visitor, base::Optional<T>* optional) {
+ static void Trace(Visitor* visitor, const base::Optional<T>* optional) {
if (*optional != base::nullopt) {
TraceIfNeeded<T>::Trace(visitor, optional->value());
}
@@ -304,9 +218,10 @@ struct EphemeronKeyValuePair {
using KeyTraits = _KeyTraits;
using ValueTraits = _ValueTraits;
- EphemeronKeyValuePair(KeyType* k, ValueType* v) : key(k), value(v) {}
- KeyType* key;
- ValueType* value;
+ EphemeronKeyValuePair(const KeyType* k, const ValueType* v)
+ : key(k), value(v) {}
+ const KeyType* key;
+ const ValueType* value;
};
template <typename _KeyType,
@@ -322,7 +237,7 @@ struct EphemeronKeyValuePair<_KeyType,
_ValueTraits,
_KeyTraits,
false> {
- EphemeronKeyValuePair(_KeyType* k, _ValueType* v)
+ EphemeronKeyValuePair(const _KeyType* k, const _ValueType* v)
: EphemeronKeyValuePair<_ValueType,
_KeyType,
_ValueTraits,
@@ -342,9 +257,9 @@ namespace WTF {
// weak elements.
template <typename T, typename Traits>
struct TraceInCollectionTrait<kNoWeakHandling, T, Traits> {
- static bool IsAlive(T& t) { return true; }
+ static bool IsAlive(const T& t) { return true; }
- static bool Trace(blink::Visitor* visitor, T& t) {
+ static bool Trace(blink::Visitor* visitor, const T& t) {
static_assert(IsTraceableInCollectionTrait<Traits>::value,
"T should not be traced");
visitor->Trace(t);
@@ -353,142 +268,45 @@ struct TraceInCollectionTrait<kNoWeakHandling, T, Traits> {
};
template <typename T, typename Traits>
-struct TraceInCollectionTrait<kNoWeakHandling, blink::WeakMember<T>, Traits> {
- static bool Trace(blink::Visitor* visitor, blink::WeakMember<T>& t) {
- // Extract raw pointer to avoid using the WeakMember<> overload in Visitor.
- visitor->Trace(t.Get());
+struct TraceInCollectionTrait<kNoWeakHandling, blink::Member<T>, Traits> {
+ static bool IsAlive(const blink::Member<T>& t) { return true; }
+ static bool Trace(blink::Visitor* visitor, const blink::Member<T>& t) {
+ visitor->TraceMaybeDeleted(t);
return false;
}
};
-// Catch-all for types that have HashTrait support for tracing with weakness.
-// Empty to enforce specialization.
-template <typename T, typename Traits>
-struct TraceInCollectionTrait<kWeakHandling, T, Traits> {};
-
template <typename T, typename Traits>
-struct TraceInCollectionTrait<kWeakHandling, blink::WeakMember<T>, Traits> {
- static bool IsAlive(blink::WeakMember<T>& value) {
- return blink::ThreadHeap::IsHeapObjectAlive(value);
- }
-
- static bool Trace(blink::Visitor* visitor, blink::WeakMember<T>& value) {
- return !blink::ThreadHeap::IsHeapObjectAlive(value);
+struct TraceInCollectionTrait<kWeakHandling, blink::Member<T>, Traits> {
+ static bool IsAlive(const blink::Member<T>& t) { return true; }
+ static bool Trace(blink::Visitor* visitor, const blink::Member<T>& t) {
+ visitor->TraceMaybeDeleted(t);
+ return false;
}
};
-// This trace method is used only for on-stack HeapVectors found in
-// conservative scanning. On-heap HeapVectors are traced by Vector::trace.
template <typename T, typename Traits>
-struct TraceInCollectionTrait<kNoWeakHandling,
- blink::HeapVectorBacking<T, Traits>,
- void> {
- static bool Trace(blink::Visitor* visitor, void* self) {
- // HeapVectorBacking does not know the exact size of the vector
- // and just knows the capacity of the vector. Due to the constraint,
- // HeapVectorBacking can support only the following objects:
- //
- // - An object that has a vtable. In this case, HeapVectorBacking
- // traces only slots that are not zeroed out. This is because if
- // the object has a vtable, the zeroed slot means that it is
- // an unused slot (Remember that the unused slots are guaranteed
- // to be zeroed out by VectorUnusedSlotClearer).
- //
- // - An object that can be initialized with memset. In this case,
- // HeapVectorBacking traces all slots including unused slots.
- // This is fine because the fact that the object can be initialized
- // with memset indicates that it is safe to treat the zerod slot
- // as a valid object.
- static_assert(!IsTraceableInCollectionTrait<Traits>::value ||
- Traits::kCanClearUnusedSlotsWithMemset ||
- std::is_polymorphic<T>::value,
- "HeapVectorBacking doesn't support objects that cannot be "
- "cleared as unused with memset.");
-
- // This trace method is instantiated for vectors where
- // IsTraceableInCollectionTrait<Traits>::value is false, but the trace
- // method should not be called. Thus we cannot static-assert
- // IsTraceableInCollectionTrait<Traits>::value but should runtime-assert it.
- DCHECK(IsTraceableInCollectionTrait<Traits>::value);
-
- T* array = reinterpret_cast<T*>(self);
- blink::HeapObjectHeader* header =
- blink::HeapObjectHeader::FromPayload(self);
- // Use the payload size as recorded by the heap to determine how many
- // elements to trace.
- size_t length = header->PayloadSize() / sizeof(T);
-#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
- // As commented above, HeapVectorBacking can trace unused slots
- // (which are already zeroed out).
- ANNOTATE_CHANGE_SIZE(array, length, 0, length);
-#endif
- if (std::is_polymorphic<T>::value) {
- char* pointer = reinterpret_cast<char*>(array);
- for (unsigned i = 0; i < length; ++i) {
- char* element = pointer + i * sizeof(T);
- if (blink::VTableInitialized(element))
- blink::TraceIfNeeded<
- T, IsTraceableInCollectionTrait<Traits>::value>::Trace(visitor,
- array[i]);
- }
- } else {
- for (size_t i = 0; i < length; ++i)
- blink::TraceIfNeeded<
- T, IsTraceableInCollectionTrait<Traits>::value>::Trace(visitor,
- array[i]);
- }
+struct TraceInCollectionTrait<kNoWeakHandling, blink::WeakMember<T>, Traits> {
+ static bool Trace(blink::Visitor* visitor, const blink::WeakMember<T>& t) {
+ visitor->TraceMaybeDeleted(t);
return false;
}
};
-// This trace method is for tracing a HashTableBacking either through regular
-// tracing (via the relevant TraceTraits) or when finding a HashTableBacking
-// through conservative stack scanning (which will treat all references in the
-// backing strongly).
-template <WTF::WeakHandlingFlag WeakHandling, typename Table>
-struct TraceHashTableBackingInCollectionTrait {
- using Value = typename Table::ValueType;
- using Traits = typename Table::ValueTraits;
-
- static bool Trace(blink::Visitor* visitor, void* self) {
- static_assert(IsTraceableInCollectionTrait<Traits>::value ||
- WTF::IsWeak<Value>::value,
- "Table should not be traced");
- Value* array = reinterpret_cast<Value*>(self);
- blink::HeapObjectHeader* header =
- blink::HeapObjectHeader::FromPayload(self);
- // Use the payload size as recorded by the heap to determine how many
- // elements to trace.
- size_t length = header->PayloadSize() / sizeof(Value);
- for (size_t i = 0; i < length; ++i) {
- if (!HashTableHelper<Value, typename Table::ExtractorType,
- typename Table::KeyTraitsType>::
- IsEmptyOrDeletedBucket(array[i])) {
- blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
- visitor, &array[i]);
- }
- }
- return false;
- }
-};
+// Catch-all for types that have HashTrait support for tracing with weakness.
+// Empty to enforce specialization.
+template <typename T, typename Traits>
+struct TraceInCollectionTrait<kWeakHandling, T, Traits> {};
-template <typename Table>
-struct TraceInCollectionTrait<kNoWeakHandling,
- blink::HeapHashTableBacking<Table>,
- void> {
- static bool Trace(blink::Visitor* visitor, void* self) {
- return TraceHashTableBackingInCollectionTrait<kNoWeakHandling,
- Table>::Trace(visitor, self);
+template <typename T, typename Traits>
+struct TraceInCollectionTrait<kWeakHandling, blink::WeakMember<T>, Traits> {
+ static bool IsAlive(const blink::WeakMember<T>& value) {
+ return blink::ThreadHeap::IsHeapObjectAlive(value);
}
-};
-template <typename Table>
-struct TraceInCollectionTrait<kWeakHandling,
- blink::HeapHashTableBacking<Table>,
- void> {
- static bool Trace(blink::Visitor* visitor, void* self) {
- return TraceHashTableBackingInCollectionTrait<kWeakHandling, Table>::Trace(
- visitor, self);
+ static bool Trace(blink::Visitor* visitor,
+ const blink::WeakMember<T>& value) {
+ return !blink::ThreadHeap::IsHeapObjectAlive(value);
}
};
@@ -522,109 +340,46 @@ struct TraceInCollectionTrait<
blink::HeapListHashSetAllocator<T, inlineCapacity>>;
using Table = HashTable<Node*, U, V, W, X, Y, blink::HeapAllocator>;
- static bool Trace(blink::Visitor* visitor, void* self) {
- Node** array = reinterpret_cast<Node**>(self);
+ static bool Trace(blink::Visitor* visitor, const void* self) {
+ const Node* const* array = reinterpret_cast<const Node* const*>(self);
blink::HeapObjectHeader* header =
blink::HeapObjectHeader::FromPayload(self);
size_t length = header->PayloadSize() / sizeof(Node*);
+ const bool is_concurrent = visitor->IsConcurrent();
for (size_t i = 0; i < length; ++i) {
- if (!HashTableHelper<Node*, typename Table::ExtractorType,
- typename Table::KeyTraitsType>::
- IsEmptyOrDeletedBucket(array[i])) {
- visitor->Trace(array[i]);
+ const Node* node;
+ if (is_concurrent) {
+ // If tracing concurrently, IsEmptyOrDeletedBucket can cause data
+ // races. Loading array[i] atomically prevents possible data races.
+ // array[i] is of type Node* so can directly loaded atomically.
+ node = AsAtomicPtr(&array[i])->load(std::memory_order_relaxed);
+ } else {
+ node = array[i];
+ }
+ if (!HashTableHelper<
+ const Node*, typename Table::ExtractorType,
+ typename Table::KeyTraitsType>::IsEmptyOrDeletedBucket(node)) {
+ visitor->Trace(node);
}
}
return false;
}
};
-// Key value pairs, as used in HashMap. To disambiguate template choice we have
-// to have two versions, first the one with no special weak handling, then the
-// one with weak handling.
-template <typename Key, typename Value, typename Traits>
-struct TraceInCollectionTrait<kNoWeakHandling,
- KeyValuePair<Key, Value>,
- Traits> {
- using EphemeronHelper =
- blink::EphemeronKeyValuePair<Key,
- Value,
- typename Traits::KeyTraits,
- typename Traits::ValueTraits>;
-
- static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) {
- if (WTF::IsWeak<Key>::value != WTF::IsWeak<Value>::value) {
- // Strongification of Weak/Strong and Strong/Weak.
- EphemeronHelper helper(&self.key, &self.value);
- visitor->VisitEphemeronKeyValuePair(
- helper.key, helper.value,
- blink::TraceCollectionIfEnabled<
- kNoWeakHandling, typename EphemeronHelper::KeyType,
- typename EphemeronHelper::KeyTraits>::Trace,
- blink::TraceCollectionIfEnabled<
- kNoWeakHandling, typename EphemeronHelper::ValueType,
- typename EphemeronHelper::ValueTraits>::Trace);
- } else {
- // Strongification of Strong/Strong or Weak/Weak. Order does not matter
- // here.
- blink::TraceCollectionIfEnabled<
- kNoWeakHandling, Key, typename Traits::KeyTraits>::Trace(visitor,
- &self.key);
- blink::TraceCollectionIfEnabled<
- kNoWeakHandling, Value,
- typename Traits::ValueTraits>::Trace(visitor, &self.value);
- }
- return false;
- }
-};
-
-template <typename Key, typename Value, typename Traits>
-struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> {
- using EphemeronHelper =
- blink::EphemeronKeyValuePair<Key,
- Value,
- typename Traits::KeyTraits,
- typename Traits::ValueTraits>;
-
- static bool IsAlive(KeyValuePair<Key, Value>& self) {
- // Needed for Weak/Weak, Strong/Weak (reverse ephemeron), and Weak/Strong
- // (ephemeron). Order of invocation does not matter as tracing weak key or
- // value does not have any side effects.
- return blink::TraceCollectionIfEnabled<
- WeakHandlingTrait<Key>::value, Key,
- typename Traits::KeyTraits>::IsAlive(self.key) &&
- blink::TraceCollectionIfEnabled<
- WeakHandlingTrait<Value>::value, Value,
- typename Traits::ValueTraits>::IsAlive(self.value);
- }
-
- static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) {
- EphemeronHelper helper(&self.key, &self.value);
- return visitor->VisitEphemeronKeyValuePair(
- helper.key, helper.value,
- blink::TraceCollectionIfEnabled<
- WeakHandlingTrait<typename EphemeronHelper::KeyType>::value,
- typename EphemeronHelper::KeyType,
- typename EphemeronHelper::KeyTraits>::Trace,
- blink::TraceCollectionIfEnabled<
- WeakHandlingTrait<typename EphemeronHelper::ValueType>::value,
- typename EphemeronHelper::ValueType,
- typename EphemeronHelper::ValueTraits>::Trace);
- }
-};
-
// Nodes used by LinkedHashSet. Again we need two versions to disambiguate the
// template.
template <typename Value, typename Traits>
struct TraceInCollectionTrait<kNoWeakHandling,
LinkedHashSetNode<Value>,
Traits> {
- static bool IsAlive(LinkedHashSetNode<Value>& self) {
+ static bool IsAlive(const LinkedHashSetNode<Value>& self) {
return TraceInCollectionTrait<
kNoWeakHandling, Value,
typename Traits::ValueTraits>::IsAlive(self.value_);
}
- static bool Trace(blink::Visitor* visitor, LinkedHashSetNode<Value>& self) {
+ static bool Trace(blink::Visitor* visitor,
+ const LinkedHashSetNode<Value>& self) {
static_assert(
IsTraceableInCollectionTrait<Traits>::value || IsWeak<Value>::value,
"T should not be traced");
@@ -636,13 +391,14 @@ struct TraceInCollectionTrait<kNoWeakHandling,
template <typename Value, typename Traits>
struct TraceInCollectionTrait<kWeakHandling, LinkedHashSetNode<Value>, Traits> {
- static bool IsAlive(LinkedHashSetNode<Value>& self) {
+ static bool IsAlive(const LinkedHashSetNode<Value>& self) {
return TraceInCollectionTrait<
kWeakHandling, Value,
typename Traits::ValueTraits>::IsAlive(self.value_);
}
- static bool Trace(blink::Visitor* visitor, LinkedHashSetNode<Value>& self) {
+ static bool Trace(blink::Visitor* visitor,
+ const LinkedHashSetNode<Value>& self) {
return TraceInCollectionTrait<
kWeakHandling, Value, typename Traits::ValueTraits>::Trace(visitor,
self.value_);
@@ -661,7 +417,7 @@ struct TraceInCollectionTrait<
ListHashSetNode<Value,
blink::HeapListHashSetAllocator<Value, inlineCapacity>>;
- static bool Trace(blink::Visitor* visitor, Node* node) {
+ static bool Trace(blink::Visitor* visitor, const Node* node) {
static_assert(!IsWeak<Node>::value,
"ListHashSet does not support weakness");
static_assert(IsTraceableInCollectionTrait<Traits>::value,
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc b/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
index d618263c29e..a607b88200a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
@@ -46,7 +46,8 @@ void UnifiedHeapController::TracePrologue(
// Be conservative here as a new garbage collection gets started right away.
thread_state_->FinishIncrementalMarkingIfRunning(
- BlinkGC::kHeapPointersOnStack, BlinkGC::kIncrementalAndConcurrentMarking,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+ BlinkGC::kIncrementalAndConcurrentMarking,
BlinkGC::kConcurrentAndLazySweeping,
thread_state_->current_gc_data_.reason);
@@ -65,7 +66,7 @@ void UnifiedHeapController::EnterFinalPause(EmbedderStackState stack_state) {
ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope(
thread_state_->Heap().stats_collector());
thread_state_->AtomicPauseMarkPrologue(
- ToBlinkGCStackState(stack_state),
+ BlinkGC::CollectionType::kMajor, ToBlinkGCStackState(stack_state),
BlinkGC::kIncrementalAndConcurrentMarking,
thread_state_->current_gc_data_.reason);
thread_state_->AtomicPauseMarkRoots(ToBlinkGCStackState(stack_state),
@@ -82,6 +83,7 @@ void UnifiedHeapController::TraceEpilogue(
thread_state_->AtomicPauseMarkEpilogue(
BlinkGC::kIncrementalAndConcurrentMarking);
thread_state_->AtomicPauseSweepAndCompact(
+ BlinkGC::CollectionType::kMajor,
BlinkGC::kIncrementalAndConcurrentMarking,
BlinkGC::kConcurrentAndLazySweeping);
@@ -104,9 +106,9 @@ void UnifiedHeapController::RegisterV8References(
const bool was_in_atomic_pause = thread_state()->in_atomic_pause();
if (!was_in_atomic_pause)
ThreadState::Current()->EnterAtomicPause();
- for (auto& internal_fields : internal_fields_of_potential_wrappers) {
- WrapperTypeInfo* wrapper_type_info =
- reinterpret_cast<WrapperTypeInfo*>(internal_fields.first);
+ for (const auto& internal_fields : internal_fields_of_potential_wrappers) {
+ const WrapperTypeInfo* wrapper_type_info =
+ reinterpret_cast<const WrapperTypeInfo*>(internal_fields.first);
if (wrapper_type_info->gin_embedder != gin::GinEmbedder::kEmbedderBlink) {
continue;
}
@@ -123,7 +125,7 @@ bool UnifiedHeapController::AdvanceTracing(double deadline_in_ms) {
ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope(
thread_state_->Heap().stats_collector());
if (!thread_state_->in_atomic_pause()) {
- ThreadHeapStatsCollector::Scope advance_tracing_scope(
+ ThreadHeapStatsCollector::EnabledScope advance_tracing_scope(
thread_state_->Heap().stats_collector(),
ThreadHeapStatsCollector::kUnifiedMarkingStep);
// V8 calls into embedder tracing from its own marking to ensure
@@ -133,6 +135,14 @@ bool UnifiedHeapController::AdvanceTracing(double deadline_in_ms) {
base::TimeTicks deadline =
base::TimeTicks() + base::TimeDelta::FromMillisecondsD(deadline_in_ms);
is_tracing_done_ = thread_state_->MarkPhaseAdvanceMarking(deadline);
+ if (!is_tracing_done_) {
+ thread_state_->RestartIncrementalMarkingIfPaused();
+ }
+ if (base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking)) {
+ is_tracing_done_ =
+ thread_state_->ConcurrentMarkingStep() && is_tracing_done_;
+ }
return is_tracing_done_;
}
thread_state_->AtomicPauseMarkTransitiveClosure();
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc
index ce94f8becfd..62f9340f754 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc
@@ -28,8 +28,6 @@ UnifiedHeapMarkingVisitorBase::UnifiedHeapMarkingVisitorBase(
void UnifiedHeapMarkingVisitorBase::VisitImpl(
const TraceWrapperV8Reference<v8::Value>& v8_reference) {
- if (v8_reference.Get().IsEmpty())
- return;
DCHECK(isolate_);
if (task_id_ != WorklistTaskId::MutatorThread) {
// This is a temporary solution. Pushing directly from concurrent threads
@@ -40,6 +38,8 @@ void UnifiedHeapMarkingVisitorBase::VisitImpl(
v8_references_worklist_.Push(&v8_reference);
return;
}
+ if (v8_reference.Get().IsEmpty())
+ return;
controller_->RegisterEmbedderReference(
v8_reference.template Cast<v8::Data>().Get());
}
@@ -69,7 +69,7 @@ void UnifiedHeapMarkingVisitor::WriteBarrier(
void UnifiedHeapMarkingVisitor::WriteBarrier(
v8::Isolate* isolate,
const WrapperTypeInfo* wrapper_type_info,
- void* object) {
+ const void* object) {
// |object| here is either ScriptWrappable or CustomWrappable.
if (!ThreadState::IsAnyIncrementalMarking())
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
index b396d3c59c1..d2e663116cc 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
@@ -49,7 +49,7 @@ class PLATFORM_EXPORT UnifiedHeapMarkingVisitor
public:
// Write barriers for annotating a write during incremental marking.
static void WriteBarrier(const TraceWrapperV8Reference<v8::Value>&);
- static void WriteBarrier(v8::Isolate*, const WrapperTypeInfo*, void*);
+ static void WriteBarrier(v8::Isolate*, const WrapperTypeInfo*, const void*);
UnifiedHeapMarkingVisitor(ThreadState*, MarkingMode, v8::Isolate*);
~UnifiedHeapMarkingVisitor() override = default;
diff --git a/chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.cc b/chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.cc
new file mode 100644
index 00000000000..a33e2b21ee0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.cc
@@ -0,0 +1,63 @@
+// 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 "third_party/blink/renderer/platform/heap/unsanitized_atomic.h"
+
+#include "cstdint"
+
+#include "base/compiler_specific.h"
+
+#if HAS_FEATURE(address_sanitizer)
+#error "Must be built without asan."
+#endif
+
+namespace blink {
+namespace internal {
+
+template <typename T>
+void UnsanitizedAtomic<T>::store(T value, std::memory_order order) {
+ Base::store(value, order);
+}
+
+template <typename T>
+T UnsanitizedAtomic<T>::load(std::memory_order order) const {
+ return Base::load(order);
+}
+
+template <typename T>
+bool UnsanitizedAtomic<T>::compare_exchange_strong(T& expected,
+ T desired,
+ std::memory_order order) {
+ return Base::compare_exchange_strong(expected, desired, order);
+}
+
+template <typename T>
+bool UnsanitizedAtomic<T>::compare_exchange_strong(
+ T& expected,
+ T desired,
+ std::memory_order succ_order,
+ std::memory_order fail_order) {
+ return Base::compare_exchange_strong(expected, desired, succ_order,
+ fail_order);
+}
+
+template <typename T>
+bool UnsanitizedAtomic<T>::compare_exchange_weak(T& expected,
+ T desired,
+ std::memory_order order) {
+ return Base::compare_exchange_weak(expected, desired, order);
+}
+
+template <typename T>
+bool UnsanitizedAtomic<T>::compare_exchange_weak(T& expected,
+ T desired,
+ std::memory_order succ_order,
+ std::memory_order fail_order) {
+ return Base::compare_exchange_weak(expected, desired, succ_order, fail_order);
+}
+
+template class PLATFORM_EXPORT UnsanitizedAtomic<uint16_t>;
+
+} // namespace internal
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.h b/chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.h
new file mode 100644
index 00000000000..fc93c9b4dd8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/unsanitized_atomic.h
@@ -0,0 +1,61 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNSANITIZED_ATOMIC_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNSANITIZED_ATOMIC_H_
+
+#include <atomic>
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+namespace internal {
+
+// Simple wrapper for std::atomic<> that makes sure that accesses to underlying
+// data are not sanitized. This is needed because the no_sanitize_address
+// attribute doesn't propagate down to callees. Must be used with care.
+// Currently is only used to access poisoned HeapObjectHeader. For derived or
+// user types an explicit instantiation must be added to unsanitized_atomic.cc.
+template <typename T>
+class PLATFORM_EXPORT UnsanitizedAtomic final : private std::atomic<T> {
+ using Base = std::atomic<T>;
+
+ public:
+ void store(T, std::memory_order = std::memory_order_seq_cst);
+ T load(std::memory_order = std::memory_order_seq_cst) const;
+
+ bool compare_exchange_strong(T&,
+ T,
+ std::memory_order = std::memory_order_seq_cst);
+ bool compare_exchange_strong(T&, T, std::memory_order, std::memory_order);
+
+ bool compare_exchange_weak(T&,
+ T,
+ std::memory_order = std::memory_order_seq_cst);
+ bool compare_exchange_weak(T&, T, std::memory_order, std::memory_order);
+};
+
+template <typename T>
+auto* AsUnsanitizedAtomic(T* ptr) {
+#if defined(ADDRESS_SANITIZER)
+ return reinterpret_cast<UnsanitizedAtomic<T>*>(ptr);
+#else
+ return WTF::AsAtomicPtr(ptr);
+#endif
+}
+
+template <typename T>
+const auto* AsUnsanitizedAtomic(const T* ptr) {
+#if defined(ADDRESS_SANITIZER)
+ return reinterpret_cast<const UnsanitizedAtomic<T>*>(ptr);
+#else
+ return WTF::AsAtomicPtr(ptr);
+#endif
+}
+
+} // namespace internal
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNSANITIZED_ATOMIC_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/visitor.h b/chromium/third_party/blink/renderer/platform/heap/visitor.h
index 67e195fe821..d0d6e096441 100644
--- a/chromium/third_party/blink/renderer/platform/heap/visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/visitor.h
@@ -69,19 +69,19 @@ class TraceWrapperV8Reference;
//
// This interface is safe to use on concurrent threads. All accesses (reads)
// from member are done atomically.
-template <typename T, void (T::*method)(Visitor*)>
+template <typename T, void (T::*method)(Visitor*) const>
struct TraceMethodDelegate {
STATIC_ONLY(TraceMethodDelegate);
- static void Trampoline(Visitor* visitor, void* self) {
- (reinterpret_cast<T*>(self)->*method)(visitor);
+ static void Trampoline(Visitor* visitor, const void* self) {
+ (reinterpret_cast<T*>(const_cast<void*>(self))->*method)(visitor);
}
};
template <typename T, void (T::*method)(const WeakCallbackInfo&)>
struct WeakCallbackMethodDelegate {
STATIC_ONLY(WeakCallbackMethodDelegate);
- static void Trampoline(const WeakCallbackInfo& info, void* self) {
- (reinterpret_cast<T*>(self)->*method)(info);
+ static void Trampoline(const WeakCallbackInfo& info, const void* self) {
+ (reinterpret_cast<T*>(const_cast<void*>(self))->*method)(info);
}
};
@@ -105,24 +105,47 @@ class PLATFORM_EXPORT Visitor {
"T needs to be a garbage collected object");
if (!t)
return;
- VisitRoot(const_cast<T*>(t), TraceDescriptorFor(t), location);
+ VisitRoot(t, TraceDescriptorFor(t), location);
}
template <typename T>
void Trace(const Member<T>& t) {
- DCHECK(!t.IsHashTableDeletedValueSafe());
- Trace(t.GetSafe());
+ const T* value = t.GetSafe();
+
+ DCHECK(!Member<T>::IsMemberHashTableDeletedValue(value));
+
+ Trace(value);
}
- // Fallback methods used only when we need to trace raw pointers of T. This is
- // the case when a member is a union where we do not support members.
template <typename T>
- void Trace(const T* t) {
- Trace(const_cast<T*>(t));
+ ALWAYS_INLINE void TraceMaybeDeleted(const Member<T>& t) {
+ const T* value = t.GetSafe();
+
+ if (Member<T>::IsMemberHashTableDeletedValue(value))
+ return;
+
+ Trace<T>(value);
}
+ // TraceMayBeDeleted strongifies WeakMembers.
+ template <typename T>
+ ALWAYS_INLINE void TraceMaybeDeleted(const WeakMember<T>& t) {
+ const T* value = t.GetSafe();
+
+ if (WeakMember<T>::IsMemberHashTableDeletedValue(value))
+ return;
+
+ Trace<T>(value);
+ }
+
+ // Fallback methods used only when we need to trace raw pointers of T. This is
+ // the case when a member is a union where we do not support members.
template <typename T>
void Trace(T* t) {
+ Trace(const_cast<const T*>(t));
+ }
+ template <typename T>
+ void Trace(const T* t) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
@@ -132,40 +155,42 @@ class PLATFORM_EXPORT Visitor {
}
template <typename T>
- void TraceBackingStoreStrongly(T* backing_store, T** backing_store_slot) {
+ void TraceBackingStoreStrongly(const T* backing_store,
+ const T* const* backing_store_slot) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
- VisitBackingStoreStrongly(backing_store,
- reinterpret_cast<void**>(backing_store_slot),
- TraceDescriptorFor(backing_store));
+ VisitBackingStoreStrongly(
+ backing_store, reinterpret_cast<const void* const*>(backing_store_slot),
+ TraceDescriptorFor(backing_store));
}
template <typename HashTable, typename T>
- void TraceBackingStoreWeakly(T* backing_store,
- T** backing_store_slot,
+ void TraceBackingStoreWeakly(const T* backing_store,
+ const T* const* backing_store_slot,
WeakCallback weak_callback,
- void* weak_callback_parameter) {
+ const void* weak_callback_parameter) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
- VisitBackingStoreWeakly(backing_store,
- reinterpret_cast<void**>(backing_store_slot),
- TraceDescriptorFor(backing_store),
- WeakTraceDescriptorFor(backing_store),
- weak_callback, weak_callback_parameter);
+ VisitBackingStoreWeakly(
+ backing_store, reinterpret_cast<const void* const*>(backing_store_slot),
+ TraceDescriptorFor(backing_store),
+ WeakTraceDescriptorFor(backing_store), weak_callback,
+ weak_callback_parameter);
}
template <typename T>
- void TraceBackingStoreOnly(T* backing_store, T** backing_store_slot) {
+ void TraceBackingStoreOnly(const T* backing_store,
+ const T* const* backing_store_slot) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
- VisitBackingStoreOnly(backing_store,
- reinterpret_cast<void**>(backing_store_slot));
+ VisitBackingStoreOnly(backing_store, reinterpret_cast<const void* const*>(
+ backing_store_slot));
}
// WeakMember version of the templated trace method. It doesn't keep
@@ -175,19 +200,17 @@ class PLATFORM_EXPORT Visitor {
// picking the correct overload, so all these trace methods have to have
// the same constness on their argument to allow the type to decide.
template <typename T>
- void Trace(const WeakMember<T>& const_weak_member) {
+ void Trace(const WeakMember<T>& weak_member) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
- WeakMember<T>& weak_member = const_cast<WeakMember<T>&>(const_weak_member);
- std::remove_const_t<T>* value =
- const_cast<std::remove_const_t<T>*>(weak_member.GetSafe());
+ const T* value = weak_member.GetSafe();
if (!value)
return;
- DCHECK(!weak_member.IsHashTableDeletedValueSafe());
+ DCHECK(!WeakMember<T>::IsMemberHashTableDeletedValue(value));
VisitWeak(value, &weak_member, TraceDescriptorFor(value),
&HandleWeakCell<T>);
}
@@ -204,11 +227,11 @@ class PLATFORM_EXPORT Visitor {
void Trace(const T& t) {
static_assert(sizeof(T), "T must be fully defined");
if (std::is_polymorphic<T>::value) {
- intptr_t vtable = *reinterpret_cast<const intptr_t*>(&t);
+ const intptr_t vtable = *reinterpret_cast<const intptr_t*>(&t);
if (!vtable)
return;
}
- TraceTrait<T>::Trace(this, &const_cast<T&>(t));
+ TraceTrait<T>::Trace(this, &t);
}
// Registers an instance method using |RegisterWeakCallback|. See description
@@ -216,7 +239,7 @@ class PLATFORM_EXPORT Visitor {
template <typename T, void (T::*method)(const WeakCallbackInfo&)>
void RegisterWeakCallbackMethod(const T* obj) {
RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>::Trampoline,
- const_cast<T*>(obj));
+ obj);
}
// Cross-component tracing interface.
@@ -228,32 +251,39 @@ class PLATFORM_EXPORT Visitor {
// Dynamic visitor interface.
- virtual void VisitRoot(void* t, TraceDescriptor desc, const base::Location&) {
+ virtual void VisitRoot(const void* t,
+ TraceDescriptor desc,
+ const base::Location&) {
Visit(t, desc);
}
// Visits an object through a strong reference.
- virtual void Visit(void*, TraceDescriptor) = 0;
+ virtual void Visit(const void*, TraceDescriptor) = 0;
// Visits an object through a weak reference.
- virtual void VisitWeak(void*, void*, TraceDescriptor, WeakCallback) = 0;
+ virtual void VisitWeak(const void*,
+ const void*,
+ TraceDescriptor,
+ WeakCallback) = 0;
// Visitors for collection backing stores.
- virtual void VisitBackingStoreStrongly(void*, void**, TraceDescriptor) = 0;
- virtual void VisitBackingStoreWeakly(void*,
- void**,
+ virtual void VisitBackingStoreStrongly(const void*,
+ const void* const*,
+ TraceDescriptor) = 0;
+ virtual void VisitBackingStoreWeakly(const void*,
+ const void* const*,
TraceDescriptor,
TraceDescriptor,
WeakCallback,
- void*) = 0;
- virtual void VisitBackingStoreOnly(void*, void**) = 0;
+ const void*) = 0;
+ virtual void VisitBackingStoreOnly(const void*, const void* const*) = 0;
// Visits ephemeron pairs which are a combination of weak and strong keys and
// values.
- using EphemeronTracingCallback = bool (*)(Visitor*, void*);
+ using EphemeronTracingCallback = bool (*)(Visitor*, const void*);
virtual bool VisitEphemeronKeyValuePair(
- void* key,
- void* value,
+ const void* key,
+ const void* value,
EphemeronTracingCallback key_trace_callback,
EphemeronTracingCallback value_trace_callback) {
return true;
@@ -265,7 +295,7 @@ class PLATFORM_EXPORT Visitor {
// Registers backing store pointers so that they can be moved and properly
// updated.
- virtual void RegisterBackingStoreCallback(void* backing,
+ virtual void RegisterBackingStoreCallback(const void* backing,
MovingObjectCallback) = 0;
// Adds a |callback| that is invoked with |parameter| after liveness has been
@@ -280,22 +310,32 @@ class PLATFORM_EXPORT Visitor {
// - Clearing out pointers is allowed.
// - Removing elements from heap collections is allowed as these collections
// are aware of custom weakness and won't resize their backings.
- virtual void RegisterWeakCallback(WeakCallback callback, void* parameter) = 0;
+ virtual void RegisterWeakCallback(WeakCallback callback,
+ const void* parameter) = 0;
+
+ virtual bool IsConcurrent() const { return false; }
+
+ // TODO(crbug/986235): ConcurrentTracingBailOut is part of a temporary
+ // bailout mechanism to avoid tracing collections on concurrent threads.
+ // This method and any usage of it will be removed as soon as making all
+ // collections cuncurrent-safe is finished.
+ // The same also applies to NotSafeToConcurrentlyTraceWorklist in heap.h.
+ virtual bool ConcurrentTracingBailOut(TraceDescriptor desc) { return false; }
protected:
template <typename T>
static inline TraceDescriptor TraceDescriptorFor(const T* traceable) {
- return TraceTrait<T>::GetTraceDescriptor(const_cast<T*>(traceable));
+ return TraceTrait<T>::GetTraceDescriptor(traceable);
}
template <typename T>
static inline TraceDescriptor WeakTraceDescriptorFor(const T* traceable) {
- return TraceTrait<T>::GetWeakTraceDescriptor(const_cast<T*>(traceable));
+ return TraceTrait<T>::GetWeakTraceDescriptor(traceable);
}
private:
template <typename T>
- static void HandleWeakCell(const WeakCallbackInfo&, void*);
+ static void HandleWeakCell(const WeakCallbackInfo&, const void*);
ThreadState* const state_;
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/weakness_marking_test.cc b/chromium/third_party/blink/renderer/platform/heap/weakness_marking_test.cc
index 2a8869b664c..86408b94779 100644
--- a/chromium/third_party/blink/renderer/platform/heap/weakness_marking_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/weakness_marking_test.cc
@@ -198,6 +198,50 @@ TEST_F(WeaknessMarkingTest, TracableEphemeronIsRegsitered) {
EXPECT_NE(old_ephemeron_count, ephemeron_count);
}
+// TODO(keinakashima): add tests for NewLinkedHashSet after supporting
+// WeakMember
+TEST_F(WeaknessMarkingTest, SwapIntoAlreadyProcessedWeakSet) {
+ // Regression test: https://crbug.com/1038623
+ //
+ // Test ensures that an empty weak set that has already been marked sets up
+ // weakness callbacks. This is important as another backing may be swapped in
+ // at some point after marking it initially.
+ using WeakLinkedSet = HeapLinkedHashSet<WeakMember<IntegerObject>>;
+ Persistent<WeakLinkedSet> holder1(MakeGarbageCollected<WeakLinkedSet>());
+ Persistent<WeakLinkedSet> holder2(MakeGarbageCollected<WeakLinkedSet>());
+ holder1->insert(MakeGarbageCollected<IntegerObject>(1));
+ IncrementalMarkingTestDriver driver(ThreadState::Current());
+ driver.Start();
+ driver.FinishSteps();
+ holder1->Swap(*holder2.Get());
+ driver.FinishGC();
+}
+
+TEST_F(WeaknessMarkingTest, EmptyEphemeronCollection) {
+ // Tests that an empty ephemeron collection does not crash in the GC when
+ // processing a non-existent backing store.
+ using Map = HeapHashMap<Member<IntegerObject>, WeakMember<IntegerObject>>;
+ Persistent<Map> map = MakeGarbageCollected<Map>();
+ TestSupportingGC::PreciselyCollectGarbage();
+}
+
+TEST_F(WeaknessMarkingTest, ClearWeakHashTableAfterMarking) {
+ // Regression test: https://crbug.com/1054363
+ //
+ // Test ensures that no marked backing with weak pointers to dead object is
+ // left behind after marking. The test creates a backing that is floating
+ // garbage. The marking verifier ensures that all buckets are properly
+ // deleted.
+ using Set = HeapHashSet<WeakMember<IntegerObject>>;
+ Persistent<Set> holder(MakeGarbageCollected<Set>());
+ holder->insert(MakeGarbageCollected<IntegerObject>(1));
+ IncrementalMarkingTestDriver driver(ThreadState::Current());
+ driver.Start();
+ driver.FinishSteps();
+ holder->clear();
+ driver.FinishGC();
+}
+
} // namespace weakness_marking_test
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/worklist.h b/chromium/third_party/blink/renderer/platform/heap/worklist.h
index 7664cacf6be..b3f341077ae 100644
--- a/chromium/third_party/blink/renderer/platform/heap/worklist.h
+++ b/chromium/third_party/blink/renderer/platform/heap/worklist.h
@@ -11,6 +11,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_WORKLIST_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_WORKLIST_H_
+#include <atomic>
#include <cstddef>
#include <utility>
@@ -30,14 +31,16 @@ namespace blink {
//
// Work stealing is best effort, i.e., there is no way to inform other tasks
// of the need of items.
-template <typename _EntryType, int segment_size, int max_tasks = 2>
+template <typename _EntryType, int segment_size, int num_tasks = 4>
class Worklist {
USING_FAST_MALLOC(Worklist);
- using WorklistType = Worklist<_EntryType, segment_size, max_tasks>;
+ using WorklistType = Worklist<_EntryType, segment_size, num_tasks>;
public:
using EntryType = _EntryType;
+ static constexpr int kNumTasks = num_tasks;
+
class View {
DISALLOW_NEW();
@@ -79,11 +82,8 @@ class Worklist {
static constexpr size_t kSegmentCapacity = segment_size;
- Worklist() : Worklist(max_tasks) {}
-
- explicit Worklist(int num_tasks) : num_tasks_(num_tasks) {
- CHECK_LE(num_tasks, max_tasks);
- for (int i = 0; i < num_tasks_; i++) {
+ Worklist() {
+ for (int i = 0; i < kNumTasks; i++) {
private_push_segment(i) = NewSegment();
private_pop_segment(i) = NewSegment();
}
@@ -91,7 +91,7 @@ class Worklist {
~Worklist() {
CHECK(IsGlobalEmpty());
- for (int i = 0; i < num_tasks_; i++) {
+ for (int i = 0; i < kNumTasks; i++) {
DCHECK(private_push_segment(i));
DCHECK(private_pop_segment(i));
delete private_push_segment(i);
@@ -100,7 +100,7 @@ class Worklist {
}
bool Push(int task_id, EntryType entry) {
- DCHECK_LT(task_id, num_tasks_);
+ DCHECK_LT(task_id, kNumTasks);
DCHECK(private_push_segment(task_id));
if (!private_push_segment(task_id)->Push(entry)) {
PublishPushSegmentToGlobal(task_id);
@@ -112,7 +112,7 @@ class Worklist {
}
bool Pop(int task_id, EntryType* entry) {
- DCHECK_LT(task_id, num_tasks_);
+ DCHECK_LT(task_id, kNumTasks);
DCHECK(private_pop_segment(task_id));
if (!private_pop_segment(task_id)->Pop(entry)) {
if (!private_push_segment(task_id)->IsEmpty()) {
@@ -137,7 +137,7 @@ class Worklist {
bool IsGlobalPoolEmpty() const { return global_pool_.IsEmpty(); }
bool IsGlobalEmpty() const {
- for (int i = 0; i < num_tasks_; i++) {
+ for (int i = 0; i < kNumTasks; i++) {
if (!IsLocalEmpty(i))
return false;
}
@@ -153,6 +153,9 @@ class Worklist {
private_push_segment(task_id)->Size();
}
+ // Thread-safe but may return an outdated result.
+ size_t GlobalPoolSize() const { return global_pool_.Size(); }
+
size_t LocalPushSegmentSize(int task_id) const {
return private_push_segment(task_id)->Size();
}
@@ -161,7 +164,7 @@ class Worklist {
//
// Assumes that no other tasks are running.
void Clear() {
- for (int i = 0; i < num_tasks_; i++) {
+ for (int i = 0; i < kNumTasks; i++) {
private_pop_segment(i)->Clear();
private_push_segment(i)->Clear();
}
@@ -178,7 +181,7 @@ class Worklist {
// Assumes that no other tasks are running.
template <typename Callback>
void Update(Callback callback) {
- for (int i = 0; i < num_tasks_; i++) {
+ for (int i = 0; i < kNumTasks; i++) {
private_pop_segment(i)->Update(callback);
private_push_segment(i)->Update(callback);
}
@@ -196,12 +199,9 @@ class Worklist {
}
void MergeGlobalPool(Worklist* other) {
- auto pair = other->global_pool_.Extract();
- global_pool_.MergeList(pair.first, pair.second);
+ global_pool_.Merge(&other->global_pool_);
}
- int num_tasks() const { return num_tasks_; }
-
private:
FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentCreate);
FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentPush);
@@ -284,11 +284,14 @@ class Worklist {
base::AutoLock guard(lock_);
segment->set_next(top_);
set_top(segment);
+ size_.fetch_add(1, std::memory_order_relaxed);
}
inline bool Pop(Segment** segment) {
base::AutoLock guard(lock_);
if (top_) {
+ DCHECK_LT(0U, size_);
+ size_.fetch_sub(1, std::memory_order_relaxed);
*segment = top_;
set_top(top_->next());
return true;
@@ -301,8 +304,16 @@ class Worklist {
reinterpret_cast<const base::subtle::AtomicWord*>(&top_)) == 0;
}
+ inline size_t Size() const {
+ // It is safe to read |size_| without a lock since this variable is
+ // atomic, keeping in mind that threads may not immediately see the new
+ // value when it is updated.
+ return TS_UNCHECKED_READ(size_).load(std::memory_order_relaxed);
+ }
+
void Clear() {
base::AutoLock guard(lock_);
+ size_.store(0, std::memory_order_relaxed);
Segment* current = top_;
while (current) {
Segment* tmp = current;
@@ -321,6 +332,8 @@ class Worklist {
while (current) {
current->Update(callback);
if (current->IsEmpty()) {
+ DCHECK_LT(0U, size_);
+ size_.fetch_sub(1, std::memory_order_relaxed);
if (!prev) {
top_ = current->next();
} else {
@@ -345,28 +358,28 @@ class Worklist {
}
}
- std::pair<Segment*, Segment*> Extract() {
+ void Merge(GlobalPool* other) {
Segment* top = nullptr;
+ size_t other_size = 0;
{
- base::AutoLock guard(lock_);
- if (!top_)
- return std::make_pair(nullptr, nullptr);
- top = top_;
- set_top(nullptr);
+ base::AutoLock guard(other->lock_);
+ if (!other->top_)
+ return;
+ top = other->top_;
+ other_size = other->size_.load(std::memory_order_relaxed);
+ other->size_.store(0, std::memory_order_relaxed);
+ other->set_top(nullptr);
}
+
Segment* end = top;
while (end->next())
end = end->next();
- return std::make_pair(top, end);
- }
- void MergeList(Segment* start, Segment* end) {
- if (!start)
- return;
{
base::AutoLock guard(lock_);
+ size_.fetch_add(other_size, std::memory_order_relaxed);
end->set_next(top_);
- set_top(start);
+ set_top(top);
}
}
@@ -378,7 +391,8 @@ class Worklist {
}
mutable base::Lock lock_;
- Segment* top_;
+ Segment* top_ GUARDED_BY(lock_);
+ std::atomic<size_t> size_ GUARDED_BY(lock_){0};
};
ALWAYS_INLINE Segment*& private_push_segment(int task_id) {
@@ -430,9 +444,8 @@ class Worklist {
return new Segment();
}
- PrivateSegmentHolder private_segments_[max_tasks];
+ PrivateSegmentHolder private_segments_[kNumTasks];
GlobalPool global_pool_;
- int num_tasks_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/worklist_test.cc b/chromium/third_party/blink/renderer/platform/heap/worklist_test.cc
index f563a75c199..1030cbab9ac 100644
--- a/chromium/third_party/blink/renderer/platform/heap/worklist_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/worklist_test.cc
@@ -155,13 +155,16 @@ TEST(WorklistTest, LocalPushStaysPrivate) {
SomeObject dummy;
SomeObject* retrieved = nullptr;
EXPECT_TRUE(worklist.IsGlobalEmpty());
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
EXPECT_TRUE(worklist_view1.Push(&dummy));
EXPECT_FALSE(worklist.IsGlobalEmpty());
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
EXPECT_FALSE(worklist_view2.Pop(&retrieved));
EXPECT_EQ(nullptr, retrieved);
EXPECT_TRUE(worklist_view1.Pop(&retrieved));
EXPECT_EQ(&dummy, retrieved);
EXPECT_TRUE(worklist.IsGlobalEmpty());
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
}
TEST(WorklistTest, GlobalUpdateNull) {
@@ -175,6 +178,7 @@ TEST(WorklistTest, GlobalUpdateNull) {
EXPECT_TRUE(worklist_view.Push(object));
worklist.Update([](SomeObject* object, SomeObject** out) { return false; });
EXPECT_TRUE(worklist.IsGlobalEmpty());
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
}
TEST(WorklistTest, GlobalUpdate) {
@@ -216,6 +220,7 @@ TEST(WorklistTest, FlushToGlobalPushSegment) {
objectA = reinterpret_cast<SomeObject*>(&objectA);
EXPECT_TRUE(worklist_view0.Push(objectA));
worklist.FlushToGlobal(0);
+ EXPECT_EQ(1U, worklist.GlobalPoolSize());
EXPECT_TRUE(worklist_view1.Pop(&object));
}
@@ -230,6 +235,7 @@ TEST(WorklistTest, FlushToGlobalPopSegment) {
EXPECT_TRUE(worklist_view0.Push(objectA));
EXPECT_TRUE(worklist_view0.Pop(&object));
worklist.FlushToGlobal(0);
+ EXPECT_EQ(1U, worklist.GlobalPoolSize());
EXPECT_TRUE(worklist_view1.Pop(&object));
}
@@ -242,8 +248,10 @@ TEST(WorklistTest, Clear) {
EXPECT_TRUE(worklist_view.Push(object));
}
EXPECT_TRUE(worklist_view.Push(object));
+ EXPECT_EQ(1U, worklist.GlobalPoolSize());
worklist.Clear();
EXPECT_TRUE(worklist.IsGlobalEmpty());
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
}
TEST(WorklistTest, SingleSegmentSteal) {
@@ -259,6 +267,7 @@ TEST(WorklistTest, SingleSegmentSteal) {
EXPECT_TRUE(worklist_view1.Push(nullptr));
EXPECT_TRUE(worklist_view1.Pop(&retrieved));
EXPECT_EQ(nullptr, retrieved);
+ EXPECT_EQ(1U, worklist.GlobalPoolSize());
// Stealing.
for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) {
EXPECT_TRUE(worklist_view2.Pop(&retrieved));
@@ -266,6 +275,7 @@ TEST(WorklistTest, SingleSegmentSteal) {
EXPECT_FALSE(worklist_view1.Pop(&retrieved));
}
EXPECT_TRUE(worklist.IsGlobalEmpty());
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
}
TEST(WorklistTest, MultipleSegmentsStolen) {
@@ -287,11 +297,13 @@ TEST(WorklistTest, MultipleSegmentsStolen) {
EXPECT_TRUE(worklist_view1.Push(&dummy3));
EXPECT_TRUE(worklist_view1.Pop(&retrieved));
EXPECT_EQ(&dummy3, retrieved);
+ EXPECT_EQ(2U, worklist.GlobalPoolSize());
// Stealing.
EXPECT_TRUE(worklist_view2.Pop(&retrieved));
SomeObject* const expect_bag2 = retrieved;
EXPECT_TRUE(worklist_view3.Pop(&retrieved));
SomeObject* const expect_bag3 = retrieved;
+ EXPECT_EQ(0U, worklist.GlobalPoolSize());
EXPECT_NE(expect_bag2, expect_bag3);
EXPECT_TRUE(expect_bag2 == &dummy1 || expect_bag2 == &dummy2);
EXPECT_TRUE(expect_bag3 == &dummy1 || expect_bag3 == &dummy2);
@@ -320,10 +332,13 @@ TEST(WorklistTest, MergeGlobalPool) {
EXPECT_TRUE(worklist_view1.Push(nullptr));
EXPECT_TRUE(worklist_view1.Pop(&retrieved));
EXPECT_EQ(nullptr, retrieved);
+ EXPECT_EQ(1U, worklist1.GlobalPoolSize());
// Merging global pool into a new Worklist.
TestWorklist worklist2;
TestWorklist::View worklist_view2(&worklist2, 0);
+ EXPECT_EQ(0U, worklist2.GlobalPoolSize());
worklist2.MergeGlobalPool(&worklist1);
+ EXPECT_EQ(1U, worklist2.GlobalPoolSize());
EXPECT_FALSE(worklist2.IsGlobalEmpty());
for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) {
EXPECT_TRUE(worklist_view2.Pop(&retrieved));
diff --git a/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc b/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc
index 2cc9848ddbd..92bf0523d47 100644
--- a/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc
@@ -4,7 +4,7 @@
#include "base/callback.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
+#include "testing/perf/perf_result_reporter.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
@@ -14,6 +14,21 @@ class WriteBarrierPerfTest : public TestSupportingGC {};
namespace {
+constexpr char kMetricPrefixWriteBarrier[] = "WriteBarrier.";
+constexpr char kMetricWritesDuringGcRunsPerS[] = "writes_during_gc";
+constexpr char kMetricWritesOutsideGcRunsPerS[] = "writes_outside_gc";
+constexpr char kMetricRelativeSpeedDifferenceUnitless[] =
+ "relative_speed_difference";
+
+perf_test::PerfResultReporter SetUpReporter(const std::string& story_name) {
+ perf_test::PerfResultReporter reporter(kMetricPrefixWriteBarrier, story_name);
+ reporter.RegisterImportantMetric(kMetricWritesDuringGcRunsPerS, "runs/s");
+ reporter.RegisterImportantMetric(kMetricWritesOutsideGcRunsPerS, "runs/s");
+ reporter.RegisterImportantMetric(kMetricRelativeSpeedDifferenceUnitless,
+ "unitless");
+ return reporter;
+}
+
class PerfDummyObject : public GarbageCollected<PerfDummyObject> {
public:
PerfDummyObject() = default;
@@ -61,19 +76,16 @@ TEST_F(WriteBarrierPerfTest, MemberWritePerformance) {
PreciselyCollectGarbage();
// Reporting.
- perf_test::PrintResult(
- "WriteBarrierPerfTest", " writes during GC", "",
- static_cast<double>(kNumElements) / during_gc_duration.InMillisecondsF(),
- "writes/ms", true);
- perf_test::PrintResult(
- "WriteBarrierPerfTest", " writes outside GC", "",
- static_cast<double>(kNumElements) / outside_gc_duration.InMillisecondsF(),
- "writes/ms", true);
- perf_test::PrintResult("WriteBarrierPerfTest", " relative speed difference",
- "",
- during_gc_duration.InMillisecondsF() /
- outside_gc_duration.InMillisecondsF(),
- "times", true);
+ auto reporter = SetUpReporter("member_write_performance");
+ reporter.AddResult(
+ kMetricWritesDuringGcRunsPerS,
+ static_cast<double>(kNumElements) / during_gc_duration.InSecondsF());
+ reporter.AddResult(
+ kMetricWritesOutsideGcRunsPerS,
+ static_cast<double>(kNumElements) / outside_gc_duration.InSecondsF());
+ reporter.AddResult(
+ kMetricRelativeSpeedDifferenceUnitless,
+ during_gc_duration.InSecondsF() / outside_gc_duration.InSecondsF());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap_observer_list.h b/chromium/third_party/blink/renderer/platform/heap_observer_list.h
new file mode 100644
index 00000000000..1c439a68ae8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap_observer_list.h
@@ -0,0 +1,91 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_OBSERVER_LIST_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_OBSERVER_LIST_H_
+
+#include "base/auto_reset.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+// A list of observers. Ensures list is not mutated while iterating. Observers
+// are not retained.
+template <class ObserverType>
+class PLATFORM_EXPORT HeapObserverList {
+ DISALLOW_NEW();
+
+ public:
+ // Add an observer to this list. An observer should not be added to the same
+ // list more than once.
+ void AddObserver(ObserverType* observer) {
+ CHECK(iteration_state_ & kAllowingAddition);
+ DCHECK(!HasObserver(observer));
+ observers_.insert(observer);
+ }
+
+ // Removes the given observer from this list. Does nothing if this observer is
+ // not in this list.
+ void RemoveObserver(ObserverType* observer) {
+ CHECK(iteration_state_ & kAllowingRemoval);
+ observers_.erase(observer);
+ }
+
+ // Determine whether a particular observer is in the list.
+ bool HasObserver(ObserverType* observer) const {
+ DCHECK(!IsIteratingOverObservers());
+ return observers_.Contains(observer);
+ }
+
+ // Returns true if the list is being iterated over.
+ bool IsIteratingOverObservers() const {
+ return iteration_state_ != kNotIterating;
+ }
+
+ // Removes all the observers from this list.
+ void Clear() {
+ CHECK(iteration_state_ & kAllowingRemoval);
+ observers_.clear();
+ }
+
+ // Safely iterate over the registered lifecycle observers.
+ //
+ // Adding or removing observers is not allowed during iteration. The callable
+ // will only be called synchronously inside ForEachObserver().
+ //
+ // Sample usage:
+ // ForEachObserver([](ObserverType* observer) {
+ // observer->SomeMethod();
+ // });
+ template <typename ForEachCallable>
+ void ForEachObserver(const ForEachCallable& callable) const {
+ base::AutoReset<IterationState> scope(&iteration_state_, kAllowingNone);
+ for (ObserverType* observer : observers_) {
+ callable(observer);
+ }
+ }
+
+ void Trace(Visitor* visitor) { visitor->Trace(observers_); }
+
+ private:
+ using ObserverSet = HeapLinkedHashSet<WeakMember<ObserverType>>;
+
+ // TODO(keishi): Clean up iteration state once transition from
+ // LifecycleObserver is complete.
+ enum IterationState {
+ kAllowingNone = 0,
+ kAllowingAddition = 1,
+ kAllowingRemoval = 1 << 1,
+ kNotIterating = kAllowingAddition | kAllowingRemoval,
+ };
+
+ // Iteration state is recorded while iterating the observer set,
+ // optionally barring add or remove mutations.
+ mutable IterationState iteration_state_ = kNotIterating;
+ ObserverSet observers_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_OBSERVER_LIST_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap_observer_list_test.cc b/chromium/third_party/blink/renderer/platform/heap_observer_list_test.cc
new file mode 100644
index 00000000000..1797cf0482f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap_observer_list_test.cc
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2013 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "third_party/blink/renderer/platform/heap_observer_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
+
+namespace blink {
+
+class TestingObserver;
+
+class TestingNotifier final : public GarbageCollected<TestingNotifier> {
+ public:
+ TestingNotifier() = default;
+
+ HeapObserverList<TestingObserver>& ObserverList() { return observer_list_; }
+
+ void Trace(Visitor* visitor) { visitor->Trace(observer_list_); }
+
+ private:
+ HeapObserverList<TestingObserver> observer_list_;
+};
+
+class TestingObserver final : public GarbageCollected<TestingObserver> {
+ public:
+ TestingObserver() = default;
+ void OnNotification() { count_++; }
+ int Count() { return count_; }
+ void Trace(Visitor* visitor) {}
+
+ private:
+ int count_ = 0;
+};
+
+void Notify(HeapObserverList<TestingObserver>& observer_list) {
+ observer_list.ForEachObserver(
+ [](TestingObserver* observer) { observer->OnNotification(); });
+}
+
+TEST(HeapObserverListTest, AddRemove) {
+ Persistent<TestingNotifier> notifier =
+ MakeGarbageCollected<TestingNotifier>();
+ Persistent<TestingObserver> observer =
+ MakeGarbageCollected<TestingObserver>();
+
+ notifier->ObserverList().AddObserver(observer);
+
+ EXPECT_EQ(observer->Count(), 0);
+ Notify(notifier->ObserverList());
+ EXPECT_EQ(observer->Count(), 1);
+
+ notifier->ObserverList().RemoveObserver(observer);
+
+ Notify(notifier->ObserverList());
+ EXPECT_EQ(observer->Count(), 1);
+}
+
+TEST(HeapObserverListTest, HasObserver) {
+ Persistent<TestingNotifier> notifier =
+ MakeGarbageCollected<TestingNotifier>();
+ Persistent<TestingObserver> observer =
+ MakeGarbageCollected<TestingObserver>();
+
+ EXPECT_FALSE(notifier->ObserverList().HasObserver(observer));
+
+ notifier->ObserverList().AddObserver(observer);
+ EXPECT_TRUE(notifier->ObserverList().HasObserver(observer.Get()));
+
+ notifier->ObserverList().RemoveObserver(observer);
+ EXPECT_FALSE(notifier->ObserverList().HasObserver(observer.Get()));
+}
+
+TEST(HeapObserverListTest, GarbageCollect) {
+ Persistent<TestingNotifier> notifier =
+ MakeGarbageCollected<TestingNotifier>();
+ Persistent<TestingObserver> observer =
+ MakeGarbageCollected<TestingObserver>();
+ notifier->ObserverList().AddObserver(observer);
+
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ Notify(notifier->ObserverList());
+ EXPECT_EQ(observer->Count(), 1);
+
+ WeakPersistent<TestingObserver> weak_ref = observer.Get();
+ observer = nullptr;
+ ThreadState::Current()->CollectAllGarbageForTesting();
+ EXPECT_EQ(weak_ref.Get(), nullptr);
+}
+
+TEST(HeapObserverListTest, IsIteratingOverObservers) {
+ Persistent<TestingNotifier> notifier =
+ MakeGarbageCollected<TestingNotifier>();
+ Persistent<TestingObserver> observer =
+ MakeGarbageCollected<TestingObserver>();
+ notifier->ObserverList().AddObserver(observer);
+
+ EXPECT_FALSE(notifier->ObserverList().IsIteratingOverObservers());
+ notifier->ObserverList().ForEachObserver([&](TestingObserver* observer) {
+ EXPECT_TRUE(notifier->ObserverList().IsIteratingOverObservers());
+ });
+}
+
+TEST(HeapObserverListTest, ForEachObserverOrder) {
+ Persistent<TestingNotifier> notifier =
+ MakeGarbageCollected<TestingNotifier>();
+ Persistent<TestingObserver> observer1 =
+ MakeGarbageCollected<TestingObserver>();
+ Persistent<TestingObserver> observer2 =
+ MakeGarbageCollected<TestingObserver>();
+
+ HeapVector<Member<TestingObserver>> seen_observers;
+
+ notifier->ObserverList().AddObserver(observer1);
+ notifier->ObserverList().AddObserver(observer2);
+ notifier->ObserverList().ForEachObserver(
+ [&](TestingObserver* observer) { seen_observers.push_back(observer); });
+
+ ASSERT_EQ(2u, seen_observers.size());
+ EXPECT_EQ(observer1.Get(), seen_observers[0].Get());
+ EXPECT_EQ(observer2.Get(), seen_observers[1].Get());
+
+ seen_observers.clear();
+
+ notifier->ObserverList().RemoveObserver(observer1);
+ notifier->ObserverList().AddObserver(observer1);
+ notifier->ObserverList().ForEachObserver(
+ [&](TestingObserver* observer) { seen_observers.push_back(observer); });
+
+ ASSERT_EQ(2u, seen_observers.size());
+ EXPECT_EQ(observer2.Get(), seen_observers[0].Get());
+ EXPECT_EQ(observer1.Get(), seen_observers[1].Get());
+
+ seen_observers.clear();
+
+ notifier->ObserverList().Clear();
+ notifier->ObserverList().ForEachObserver(
+ [&](TestingObserver* observer) { seen_observers.push_back(observer); });
+ ASSERT_EQ(0u, seen_observers.size());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/OWNERS b/chromium/third_party/blink/renderer/platform/image-decoders/OWNERS
index 9cf2710a1d5..f6310a37e22 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/OWNERS
@@ -1,6 +1,6 @@
urvang@chromium.org
pkasting@chromium.org
noel@chromium.org
-scroggo@chromium.org
+scroggo@google.com
# COMPONENT: Internals>Images>Codecs
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h
index f99b89349df..b5e12645ec5 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h
@@ -261,9 +261,9 @@ class PLATFORM_EXPORT ImageDecoder {
// method, i.e., IsDecodedSizeAvailable() must return true.
virtual cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const;
- // This will only differ from size() for ICO (where each frame is a
+ // This will only differ from Size() for ICO (where each frame is a
// different icon) or other formats where different frames are different
- // sizes. This does NOT differ from size() for GIF or WebP, since
+ // sizes. This does NOT differ from Size() for GIF or WebP, since
// decoding GIF or WebP composites any smaller frames against previous
// frames to create full-size frames.
virtual IntSize FrameSizeAtIndex(size_t) const { return Size(); }
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
index 37abdaf7376..ba51a4ba05b 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
@@ -26,9 +26,11 @@ class ImageFrameTest : public testing::Test {
src_8888 = SkPackARGB32(src_8888_a, src_8888_r, src_8888_g, src_8888_b);
dst_8888 = SkPackARGB32(0xA0, 0x60, 0x70, 0x80);
+#if SK_PMCOLOR_BYTE_ORDER(B, G, R, A)
+ pixel_format_n32 = skcms_PixelFormat_BGRA_8888;
+#else
pixel_format_n32 = skcms_PixelFormat_RGBA_8888;
- if (kN32_SkColorType == kRGBA_8888_SkColorType)
- pixel_format_n32 = skcms_PixelFormat_BGRA_8888;
+#endif
skcms_Transform(&src_8888, pixel_format_n32, skcms_AlphaFormat_Unpremul,
nullptr, &src_f16, skcms_PixelFormat_RGBA_hhhh,
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
index 7c01efc1273..1a7ed7d26d2 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
@@ -892,6 +892,8 @@ bool JPEGImageDecoder::SetSize(unsigned width, unsigned height) {
}
void JPEGImageDecoder::OnSetData(SegmentReader* data) {
+ if (reader_)
+ reader_->SetData(data);
// TODO(crbug.com/943519): Incremental YUV decoding is not currently
// supported.
if (IsAllDataReceived()) {
@@ -903,8 +905,6 @@ void JPEGImageDecoder::OnSetData(SegmentReader* data) {
allow_decode_to_yuv_ &=
IsSizeAvailable() && reader_->Info()->out_color_space == JCS_YCbCr;
}
- if (reader_)
- reader_->SetData(data);
}
void JPEGImageDecoder::SetDecodedSize(unsigned width, unsigned height) {
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
index a82cb44e183..a25603243b9 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
@@ -49,10 +49,13 @@ static const size_t kLargeEnoughSize = 1000 * 1000;
namespace {
-std::unique_ptr<JPEGImageDecoder> CreateJPEGDecoder(size_t max_decoded_bytes) {
+std::unique_ptr<JPEGImageDecoder> CreateJPEGDecoder(
+ size_t max_decoded_bytes,
+ ImageDecoder::OverrideAllowDecodeToYuv decodeToYUV =
+ ImageDecoder::OverrideAllowDecodeToYuv::kDeny) {
return std::make_unique<JPEGImageDecoder>(
ImageDecoder::kAlphaNotPremultiplied, ColorBehavior::TransformToSRGB(),
- max_decoded_bytes, ImageDecoder::OverrideAllowDecodeToYuv::kDefault);
+ max_decoded_bytes, decodeToYUV);
}
std::unique_ptr<ImageDecoder> CreateJPEGDecoder() {
@@ -87,8 +90,8 @@ void ReadYUV(size_t max_decoded_bytes,
scoped_refptr<SharedBuffer> data = ReadFile(image_file_path);
ASSERT_TRUE(data);
- std::unique_ptr<JPEGImageDecoder> decoder =
- CreateJPEGDecoder(max_decoded_bytes);
+ std::unique_ptr<JPEGImageDecoder> decoder = CreateJPEGDecoder(
+ max_decoded_bytes, ImageDecoder::OverrideAllowDecodeToYuv::kDefault);
decoder->SetDecodeToYuvForTesting(true);
decoder->SetData(data.get(), true);
@@ -274,7 +277,8 @@ TEST(JPEGImageDecoderTest, yuv) {
scoped_refptr<SharedBuffer> data = ReadFile(jpeg_file);
ASSERT_TRUE(data);
- std::unique_ptr<JPEGImageDecoder> decoder = CreateJPEGDecoder(230 * 230 * 4);
+ std::unique_ptr<JPEGImageDecoder> decoder = CreateJPEGDecoder(
+ 230 * 230 * 4, ImageDecoder::OverrideAllowDecodeToYuv::kDefault);
decoder->SetDecodeToYuvForTesting(true);
decoder->SetData(data.get(), true);
@@ -552,4 +556,23 @@ INSTANTIATE_TEST_SUITE_P(JPEGImageDecoderTest,
ColorSpaceUMATest,
::testing::ValuesIn(kColorSpaceUMATestParams));
+TEST(JPEGImageDecoderTest, PartialDataWithoutSize) {
+ const char* jpeg_file = "/images/resources/lenna.jpg";
+ scoped_refptr<SharedBuffer> full_data = ReadFile(jpeg_file);
+ ASSERT_TRUE(full_data);
+
+ constexpr size_t kDataLengthWithoutSize = 4;
+ ASSERT_LT(kDataLengthWithoutSize, full_data->size());
+ scoped_refptr<SharedBuffer> partial_data =
+ SharedBuffer::Create(full_data->Data(), kDataLengthWithoutSize);
+
+ std::unique_ptr<ImageDecoder> decoder = CreateJPEGDecoder();
+ decoder->SetData(partial_data.get(), false);
+ EXPECT_FALSE(decoder->IsSizeAvailable());
+ EXPECT_FALSE(decoder->Failed());
+ decoder->SetData(full_data.get(), true);
+ EXPECT_TRUE(decoder->IsSizeAvailable());
+ EXPECT_FALSE(decoder->Failed());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder_utils.cc b/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder_utils.cc
index 7ecb3436e48..97cf9c92a25 100644
--- a/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder_utils.cc
@@ -33,7 +33,7 @@ enum RequestedImageMimeType {
ImageEncodingMimeType ImageEncoderUtils::ToEncodingMimeType(
const String& mime_type_name,
const EncodeReason encode_reason) {
- String lowercase_mime_type = mime_type_name.DeprecatedLower();
+ String lowercase_mime_type = mime_type_name.LowerASCII();
RequestedImageMimeType requested_mime_type;
if (mime_type_name.IsNull())
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h b/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h
index 7ccf114c838..6a3443121a5 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h
@@ -38,33 +38,24 @@
namespace blink {
-#define INSTANCE_COUNTERS_LIST(V) \
- V(AudioHandler) \
- V(Document) \
- V(Frame) \
- V(JSEventListener) \
- V(LayoutObject) \
- V(MediaKeySession) \
- V(MediaKeys) \
- V(Node) \
- V(Resource) \
- V(ContextLifecycleStateObserver) \
- V(V8PerContextData) \
- V(WorkerGlobalScope) \
- V(UACSSResource) \
- V(RTCPeerConnection) \
- V(ResourceFetcher) \
- V(AdSubframe) \
- V(DetachedScriptState) \
- V(V8CallInDetachedWindowByNavigation) \
- V(V8CallInDetachedWindowByNavigationAfter10s) \
- V(V8CallInDetachedWindowByNavigationAfter1min) \
- V(V8CallInDetachedWindowByClosing) \
- V(V8CallInDetachedWindowByClosingAfter10s) \
- V(V8CallInDetachedWindowByClosingAfter1min) \
- V(V8CallInDetachedWindowByOtherReason) \
- V(V8CallInDetachedWindowByOtherReasonAfter10s) \
- V(V8CallInDetachedWindowByOtherReasonAfter1min)
+#define INSTANCE_COUNTERS_LIST(V) \
+ V(AudioHandler) \
+ V(Document) \
+ V(Frame) \
+ V(JSEventListener) \
+ V(LayoutObject) \
+ V(MediaKeySession) \
+ V(MediaKeys) \
+ V(Node) \
+ V(Resource) \
+ V(ContextLifecycleStateObserver) \
+ V(V8PerContextData) \
+ V(WorkerGlobalScope) \
+ V(UACSSResource) \
+ V(RTCPeerConnection) \
+ V(ResourceFetcher) \
+ V(AdSubframe) \
+ V(DetachedScriptState)
// Atomic counters of the number of instances of objects that exist.
//
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.cc b/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.cc
index 074c7272786..8db183664dc 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.cc
@@ -7,6 +7,7 @@
#include "base/allocator/partition_allocator/memory_reclaimer.h"
#include "base/feature_list.h"
#include "base/system/sys_info.h"
+#include "base/trace_event/common/trace_event_common.h"
#include "build/build_config.h"
#include "third_party/blink/public/common/device_memory/approximated_device_memory.h"
#include "third_party/blink/public/common/features.h"
@@ -100,7 +101,8 @@ void MemoryPressureListenerRegistry::UnregisterClient(
void MemoryPressureListenerRegistry::OnMemoryPressure(
WebMemoryPressureLevel level) {
- TRACE_EVENT0("blink", "MemoryPressureListenerRegistry::onMemoryPressure");
+ TRACE_EVENT1("blink", "MemoryPressureListenerRegistry::onMemoryPressure",
+ "level", level);
CHECK(IsMainThread());
for (auto& client : clients_)
client->OnMemoryPressure(level);
@@ -131,7 +133,7 @@ void MemoryPressureListenerRegistry::ClearThreadSpecificMemory() {
FontGlobalContext::ClearMemory();
}
-void MemoryPressureListenerRegistry::Trace(blink::Visitor* visitor) {
+void MemoryPressureListenerRegistry::Trace(Visitor* visitor) {
visitor->Trace(clients_);
}
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h b/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h
index 9bab204ceeb..cc24601b37a 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h
@@ -31,7 +31,9 @@ class PLATFORM_EXPORT MemoryPressureListenerRegistry final
public:
static MemoryPressureListenerRegistry& Instance();
- // Whether the device Blink runs on is a low-end device.
+ // See: SysUtils::IsLowEndDevice for the full details of what "low-end" means.
+ // This returns true for devices that can use more extreme tradeoffs for
+ // performance. Many low memory devices (<=1GB) are not considered low-end.
// Can be overridden in web tests via internals.
static bool IsLowEndDevice();
@@ -57,7 +59,7 @@ class PLATFORM_EXPORT MemoryPressureListenerRegistry final
void OnPurgeMemory();
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
private:
friend class Internals;
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
index 93e6ae85dba..9991d6abb44 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
@@ -63,4 +63,13 @@ void DocumentResourceCoordinator::OnNonPersistentNotificationCreated() {
service_->OnNonPersistentNotificationCreated();
}
+void DocumentResourceCoordinator::SetHadFormInteraction() {
+ // Only send this signal for the first interaction as it doesn't get cleared
+ // for the lifetime of the frame and it's inefficient to send this message
+ // for every keystroke.
+ if (!had_form_interaction_)
+ service_->SetHadFormInteraction();
+ had_form_interaction_ = true;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
index 5d0ee9e07fd..73797f732ca 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
@@ -34,6 +34,7 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
// A one way switch that marks a frame as being an adframe.
void SetIsAdFrame();
void OnNonPersistentNotificationCreated();
+ void SetHadFormInteraction();
private:
explicit DocumentResourceCoordinator(const BrowserInterfaceBrokerProxy&);
@@ -41,6 +42,8 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
mojo::Remote<performance_manager::mojom::blink::DocumentCoordinationUnit>
service_;
+ bool had_form_interaction_ = false;
+
DISALLOW_COPY_AND_ASSIGN(DocumentResourceCoordinator);
};
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.cc
index f94bc634a74..37ca752b695 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.cc
@@ -6,7 +6,7 @@
namespace blink {
-void MemoryCacheDumpClient::Trace(blink::Visitor* visitor) {}
+void MemoryCacheDumpClient::Trace(Visitor* visitor) {}
MemoryCacheDumpProvider* MemoryCacheDumpProvider::Instance() {
DEFINE_STATIC_LOCAL(MemoryCacheDumpProvider, instance, ());
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h
index c99c5dc3e6d..e996a368083 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h
@@ -22,7 +22,7 @@ class PLATFORM_EXPORT MemoryCacheDumpClient : public GarbageCollectedMixin {
virtual bool OnMemoryDump(WebMemoryDumpLevelOfDetail,
WebProcessMemoryDump*) = 0;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
};
// This class is wrapper around MemoryCache to take memory snapshots. It dumps
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
index 6d75c7dfc91..c36eafdad5d 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
@@ -12,113 +12,128 @@
namespace blink {
-TracedValue::TracedValue() = default;
+TracedValue::TracedValue()
+ : TracedValue(std::make_unique<base::trace_event::TracedValue>()) {}
TracedValue::~TracedValue() = default;
void TracedValue::SetInteger(const char* name, int value) {
- traced_value_.SetInteger(name, value);
+ traced_value_->SetInteger(name, value);
}
void TracedValue::SetIntegerWithCopiedName(const char* name, int value) {
- traced_value_.SetIntegerWithCopiedName(name, value);
+ traced_value_->SetIntegerWithCopiedName(name, value);
}
void TracedValue::SetDouble(const char* name, double value) {
- traced_value_.SetDouble(name, value);
+ traced_value_->SetDouble(name, value);
}
void TracedValue::SetDoubleWithCopiedName(const char* name, double value) {
- traced_value_.SetDoubleWithCopiedName(name, value);
+ traced_value_->SetDoubleWithCopiedName(name, value);
}
void TracedValue::SetBoolean(const char* name, bool value) {
- traced_value_.SetBoolean(name, value);
+ traced_value_->SetBoolean(name, value);
}
void TracedValue::SetBooleanWithCopiedName(const char* name, bool value) {
- traced_value_.SetBooleanWithCopiedName(name, value);
+ traced_value_->SetBooleanWithCopiedName(name, value);
}
void TracedValue::SetString(const char* name, const String& value) {
StringUTF8Adaptor adaptor(value);
- traced_value_.SetString(name, adaptor.AsStringPiece());
+ traced_value_->SetString(name, adaptor.AsStringPiece());
}
void TracedValue::SetValue(const char* name, TracedValue* value) {
- traced_value_.SetValue(name, &value->traced_value_);
+ traced_value_->SetValue(name, value->traced_value_.get());
}
void TracedValue::SetStringWithCopiedName(const char* name,
const String& value) {
StringUTF8Adaptor adaptor(value);
- traced_value_.SetStringWithCopiedName(name, adaptor.AsStringPiece());
+ traced_value_->SetStringWithCopiedName(name, adaptor.AsStringPiece());
}
void TracedValue::BeginDictionary(const char* name) {
- traced_value_.BeginDictionary(name);
+ traced_value_->BeginDictionary(name);
}
void TracedValue::BeginDictionaryWithCopiedName(const char* name) {
- traced_value_.BeginDictionaryWithCopiedName(name);
+ traced_value_->BeginDictionaryWithCopiedName(name);
}
void TracedValue::BeginArray(const char* name) {
- traced_value_.BeginArray(name);
+ traced_value_->BeginArray(name);
}
void TracedValue::BeginArrayWithCopiedName(const char* name) {
- traced_value_.BeginArrayWithCopiedName(name);
+ traced_value_->BeginArrayWithCopiedName(name);
}
void TracedValue::EndDictionary() {
- traced_value_.EndDictionary();
+ traced_value_->EndDictionary();
}
void TracedValue::PushInteger(int value) {
- traced_value_.AppendInteger(value);
+ traced_value_->AppendInteger(value);
}
void TracedValue::PushDouble(double value) {
- traced_value_.AppendDouble(value);
+ traced_value_->AppendDouble(value);
}
void TracedValue::PushBoolean(bool value) {
- traced_value_.AppendBoolean(value);
+ traced_value_->AppendBoolean(value);
}
void TracedValue::PushString(const String& value) {
StringUTF8Adaptor adaptor(value);
- traced_value_.AppendString(adaptor.AsStringPiece());
+ traced_value_->AppendString(adaptor.AsStringPiece());
}
void TracedValue::BeginArray() {
- traced_value_.BeginArray();
+ traced_value_->BeginArray();
}
void TracedValue::BeginDictionary() {
- traced_value_.BeginDictionary();
+ traced_value_->BeginDictionary();
}
void TracedValue::EndArray() {
- traced_value_.EndArray();
-}
-
-String TracedValue::ToString() const {
- return String(traced_value_.ToString().c_str());
+ traced_value_->EndArray();
}
void TracedValue::AppendAsTraceFormat(std::string* out) const {
- traced_value_.AppendAsTraceFormat(out);
+ traced_value_->AppendAsTraceFormat(out);
}
bool TracedValue::AppendToProto(ProtoAppender* appender) {
- return traced_value_.AppendToProto(appender);
+ return traced_value_->AppendToProto(appender);
}
void TracedValue::EstimateTraceMemoryOverhead(
base::trace_event::TraceEventMemoryOverhead* overhead) {
- traced_value_.EstimateTraceMemoryOverhead(overhead);
+ traced_value_->EstimateTraceMemoryOverhead(overhead);
+}
+
+TracedValueJSON::TracedValueJSON()
+ : TracedValue(std::make_unique<base::trace_event::TracedValueJSON>()) {}
+TracedValueJSON::~TracedValueJSON() = default;
+
+String TracedValueJSON::ToJSON() const {
+ return String(
+ static_cast<base::trace_event::TracedValueJSON*>(traced_value_.get())
+ ->ToJSON()
+ .c_str());
+}
+
+String TracedValueJSON::ToFormattedJSON() const {
+ return String(
+ static_cast<base::trace_event::TracedValueJSON*>(traced_value_.get())
+ ->ToFormattedJSON()
+ .c_str());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
index d496bf52855..effbd5f6857 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
@@ -5,6 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_TRACING_TRACED_VALUE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_TRACING_TRACED_VALUE_H_
+#include <memory>
+#include <string>
+
#include "base/macros.h"
#include "base/trace_event/traced_value.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -13,7 +16,7 @@
namespace blink {
// Thin wrapper around base::trace_event::TracedValue.
-class PLATFORM_EXPORT TracedValue final
+class PLATFORM_EXPORT TracedValue
: public base::trace_event::ConvertableToTraceFormat {
public:
TracedValue();
@@ -44,21 +47,32 @@ class PLATFORM_EXPORT TracedValue final
void BeginArray();
void BeginDictionary();
- String ToString() const;
+ protected:
+ explicit TracedValue(
+ std::unique_ptr<base::trace_event::TracedValue> traced_value)
+ : traced_value_(std::move(traced_value)) {}
+ std::unique_ptr<base::trace_event::TracedValue> traced_value_;
private:
// ConvertableToTraceFormat
-
void AppendAsTraceFormat(std::string*) const final;
bool AppendToProto(ProtoAppender* appender) final;
void EstimateTraceMemoryOverhead(
base::trace_event::TraceEventMemoryOverhead*) final;
- base::trace_event::TracedValue traced_value_;
-
DISALLOW_COPY_AND_ASSIGN(TracedValue);
};
+// Thin wrapper around base::trace_event::TracedValueJSON.
+class PLATFORM_EXPORT TracedValueJSON final : public TracedValue {
+ public:
+ TracedValueJSON();
+ ~TracedValueJSON() final;
+
+ String ToJSON() const;
+ String ToFormattedJSON() const;
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_TRACING_TRACED_VALUE_H_
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc
index ee380f810b6..3544b8cf0e6 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/traced_value_test.cc
@@ -4,27 +4,27 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
+#include <utility>
+
#include "base/json/json_reader.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include <memory>
namespace blink {
-std::unique_ptr<base::Value> ParseTracedValue(
- std::unique_ptr<TracedValue> value) {
- base::JSONReader reader;
- return reader.ReadDeprecated(value->ToString().Utf8());
+base::Optional<base::Value> ParseTracedValue(
+ std::unique_ptr<TracedValueJSON> value) {
+ return base::JSONReader::Read(value->ToJSON().Utf8());
}
TEST(TracedValueTest, FlatDictionary) {
- auto value = std::make_unique<TracedValue>();
+ auto value = std::make_unique<TracedValueJSON>();
value->SetIntegerWithCopiedName("int", 2014);
value->SetDoubleWithCopiedName("double", 0.0);
value->SetBooleanWithCopiedName("bool", true);
value->SetStringWithCopiedName("string", "string");
- std::unique_ptr<base::Value> parsed = ParseTracedValue(std::move(value));
+ base::Optional<base::Value> parsed = ParseTracedValue(std::move(value));
base::DictionaryValue* dictionary;
ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
int int_value;
@@ -39,7 +39,7 @@ TEST(TracedValueTest, FlatDictionary) {
}
TEST(TracedValueTest, Hierarchy) {
- auto value = std::make_unique<TracedValue>();
+ auto value = std::make_unique<TracedValueJSON>();
value->SetIntegerWithCopiedName("i0", 2014);
value->BeginDictionaryWithCopiedName("dict1");
value->SetIntegerWithCopiedName("i1", 2014);
@@ -59,7 +59,7 @@ TEST(TracedValueTest, Hierarchy) {
value->EndArray();
value->SetStringWithCopiedName("s0", "foo");
- std::unique_ptr<base::Value> parsed = ParseTracedValue(std::move(value));
+ base::Optional<base::Value> parsed = ParseTracedValue(std::move(value));
base::DictionaryValue* dictionary;
ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
int i0;
@@ -99,14 +99,14 @@ TEST(TracedValueTest, Hierarchy) {
}
TEST(TracedValueTest, Escape) {
- auto value = std::make_unique<TracedValue>();
+ auto value = std::make_unique<TracedValueJSON>();
value->SetStringWithCopiedName("s0", "value0\\");
value->SetStringWithCopiedName("s1", "value\n1");
value->SetStringWithCopiedName("s2", "\"value2\"");
value->SetStringWithCopiedName("s3\\", "value3");
value->SetStringWithCopiedName("\"s4\"", "value4");
- std::unique_ptr<base::Value> parsed = ParseTracedValue(std::move(value));
+ base::Optional<base::Value> parsed = ParseTracedValue(std::move(value));
base::DictionaryValue* dictionary;
ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
std::string s0;
@@ -127,7 +127,7 @@ TEST(TracedValueTest, Escape) {
}
TEST(TracedValueTest, NonCopiedNames) {
- auto value = std::make_unique<TracedValue>();
+ auto value = std::make_unique<TracedValueJSON>();
const char* int_str = "int";
const char* double_str = "double";
const char* bool_str = "bool";
@@ -142,7 +142,7 @@ TEST(TracedValueTest, NonCopiedNames) {
value->PushInteger(2);
value->EndArray();
- std::unique_ptr<base::Value> parsed = ParseTracedValue(std::move(value));
+ base::Optional<base::Value> parsed = ParseTracedValue(std::move(value));
base::DictionaryValue* dictionary;
ASSERT_TRUE(parsed->GetAsDictionary(&dictionary));
int int_value;
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc
index e1e24170879..54c702cb6e2 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc
@@ -14,8 +14,6 @@ WebMemoryAllocatorDump::WebMemoryAllocatorDump(
: memory_allocator_dump_(memory_allocator_dump),
guid_(memory_allocator_dump->guid().ToUint64()) {}
-WebMemoryAllocatorDump::~WebMemoryAllocatorDump() = default;
-
void WebMemoryAllocatorDump::AddScalar(const char* name,
const char* units,
uint64_t value) {
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h
index a9af22ee206..75180ada990 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h
@@ -30,7 +30,6 @@ class PLATFORM_EXPORT WebMemoryAllocatorDump final {
public:
explicit WebMemoryAllocatorDump(
base::trace_event::MemoryAllocatorDump* memory_allocator_dump);
- ~WebMemoryAllocatorDump();
// Adds a scalar attribute to the dump.
// Arguments:
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc b/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
deleted file mode 100644
index 94a9886d12b..00000000000
--- a/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "base/test/scoped_feature_list.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
-#include "third_party/blink/renderer/platform/heap/persistent.h"
-#include "third_party/blink/renderer/platform/heap/thread_state.h"
-#include "third_party/blink/renderer/platform/lifecycle_notifier.h"
-#include "third_party/blink/renderer/platform/lifecycle_observer.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-
-namespace blink {
-
-class TestingObserver;
-
-class DummyContext final
- : public GarbageCollected<DummyContext>,
- public LifecycleNotifier<DummyContext, TestingObserver> {
- USING_GARBAGE_COLLECTED_MIXIN(DummyContext);
-
- public:
- void Trace(blink::Visitor* visitor) override {
- LifecycleNotifier<DummyContext, TestingObserver>::Trace(visitor);
- }
-
- // Make the protected method public for testing.
- using LifecycleNotifier<DummyContext, TestingObserver>::ForEachObserver;
-};
-
-class TestingObserver final
- : public GarbageCollected<TestingObserver>,
- public LifecycleObserver<DummyContext, TestingObserver> {
- USING_GARBAGE_COLLECTED_MIXIN(TestingObserver);
-
- public:
- explicit TestingObserver(DummyContext* context)
- : LifecycleObserver(context), context_destroyed_called_(false) {}
-
- void ContextDestroyed(DummyContext* destroyed_context) {
- if (observer_to_remove_on_destruct_) {
- destroyed_context->RemoveObserver(observer_to_remove_on_destruct_);
- observer_to_remove_on_destruct_.Clear();
- }
- context_destroyed_called_ = true;
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(observer_to_remove_on_destruct_);
- LifecycleObserver::Trace(visitor);
- }
-
- void Unobserve() { SetContext(nullptr); }
-
- void SetObserverToRemoveAndDestroy(
- TestingObserver* observer_to_remove_on_destruct) {
- DCHECK(!observer_to_remove_on_destruct_);
- observer_to_remove_on_destruct_ = observer_to_remove_on_destruct;
- }
-
- TestingObserver* InnerObserver() const {
- return observer_to_remove_on_destruct_;
- }
- bool ContextDestroyedCalled() const { return context_destroyed_called_; }
-
- private:
- Member<TestingObserver> observer_to_remove_on_destruct_;
- bool context_destroyed_called_;
-};
-
-TEST(LifecycleContextTest, ShouldObserveContextDestroyed) {
- auto* context = MakeGarbageCollected<DummyContext>();
- Persistent<TestingObserver> observer =
- MakeGarbageCollected<TestingObserver>(context);
-
- EXPECT_EQ(observer->LifecycleContext(), context);
- EXPECT_FALSE(observer->ContextDestroyedCalled());
- context->NotifyContextDestroyed();
- context = nullptr;
- ThreadState::Current()->CollectAllGarbageForTesting();
- EXPECT_EQ(observer->LifecycleContext(), static_cast<DummyContext*>(nullptr));
- EXPECT_TRUE(observer->ContextDestroyedCalled());
-}
-
-TEST(LifecycleContextTest, ShouldNotObserveContextDestroyedIfUnobserve) {
- auto* context = MakeGarbageCollected<DummyContext>();
- Persistent<TestingObserver> observer =
- MakeGarbageCollected<TestingObserver>(context);
- observer->Unobserve();
- context->NotifyContextDestroyed();
- context = nullptr;
- ThreadState::Current()->CollectAllGarbageForTesting();
- EXPECT_EQ(observer->LifecycleContext(), static_cast<DummyContext*>(nullptr));
- EXPECT_FALSE(observer->ContextDestroyedCalled());
-}
-
-TEST(LifecycleContextTest, ObserverRemovedDuringNotifyDestroyed) {
- auto* context = MakeGarbageCollected<DummyContext>();
- Persistent<TestingObserver> observer =
- MakeGarbageCollected<TestingObserver>(context);
- auto* inner_observer = MakeGarbageCollected<TestingObserver>(context);
- // Attach the observer to the other. When 'observer' is notified
- // of destruction, it will remove & destroy 'innerObserver'.
- observer->SetObserverToRemoveAndDestroy(inner_observer);
-
- EXPECT_EQ(observer->LifecycleContext(), context);
- EXPECT_EQ(observer->InnerObserver()->LifecycleContext(), context);
- EXPECT_FALSE(observer->ContextDestroyedCalled());
- EXPECT_FALSE(observer->InnerObserver()->ContextDestroyedCalled());
-
- context->NotifyContextDestroyed();
- EXPECT_EQ(observer->InnerObserver(), nullptr);
- context = nullptr;
- ThreadState::Current()->CollectAllGarbageForTesting();
- EXPECT_EQ(observer->LifecycleContext(), static_cast<DummyContext*>(nullptr));
- EXPECT_TRUE(observer->ContextDestroyedCalled());
-}
-
-// This is a regression test for http://crbug.com/854639.
-TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) {
- base::test::ScopedFeatureList scoped_feature_list;
- // Disable concurrent marking and concurrent sweeping as worker_pool task
- // environment is not set.
- scoped_feature_list.InitWithFeatures(
- {blink::features::kBlinkHeapIncrementalMarking},
- {blink::features::kBlinkHeapConcurrentMarking,
- blink::features::kBlinkHeapConcurrentSweeping});
- IncrementalMarkingTestDriver driver(ThreadState::Current());
- driver.Start();
-
- auto* context = MakeGarbageCollected<DummyContext>();
-
- // This should not cause a CFI check failure.
- Persistent<TestingObserver> observer =
- MakeGarbageCollected<TestingObserver>(context);
-
- EXPECT_FALSE(observer->ContextDestroyedCalled());
- context->NotifyContextDestroyed();
- EXPECT_TRUE(observer->ContextDestroyedCalled());
- context = nullptr;
-
- driver.FinishGC();
-}
-
-TEST(LifecycleContextTest, ForEachObserver) {
- Persistent<DummyContext> context = MakeGarbageCollected<DummyContext>();
- Persistent<TestingObserver> observer =
- MakeGarbageCollected<TestingObserver>(context);
-
- HeapVector<Member<TestingObserver>> seen_observers;
- context->ForEachObserver(
- [&](TestingObserver* observer) { seen_observers.push_back(observer); });
-
- ASSERT_EQ(1u, seen_observers.size());
- EXPECT_EQ(observer.Get(), seen_observers[0].Get());
-
- seen_observers.clear();
- observer.Clear();
- ThreadState::Current()->CollectAllGarbageForTesting();
-
- context->ForEachObserver(
- [&](TestingObserver* observer) { seen_observers.push_back(observer); });
- ASSERT_EQ(0u, seen_observers.size());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h b/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
deleted file mode 100644
index d105761b4b8..00000000000
--- a/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- * Copyright (C) 2013 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LIFECYCLE_NOTIFIER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LIFECYCLE_NOTIFIER_H_
-
-#include "base/auto_reset.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
-
-namespace blink {
-
-class LifecycleObserverBase;
-
-template <typename T, typename Observer>
-class LifecycleNotifier : public GarbageCollectedMixin {
- public:
- virtual ~LifecycleNotifier();
-
- void AddObserver(LifecycleObserverBase*);
- void RemoveObserver(LifecycleObserverBase*);
-
- // NotifyContextDestroyed() should be explicitly dispatched from an
- // observed context to detach its observers and, if the observer kind
- // requires it, notify each observer by invoking ContextDestroyed().
- //
- // When ContextDestroyed() is called, it is supplied the context as
- // an argument, but the observer's LifecycleContext() is still valid
- // and safe to use while handling the notification.
- virtual void NotifyContextDestroyed();
-
- void Trace(blink::Visitor* visitor) override { visitor->Trace(observers_); }
-
- bool IsIteratingOverObservers() const {
- return iteration_state_ != kNotIterating;
- }
-
- protected:
- LifecycleNotifier() : iteration_state_(kNotIterating) {}
-
- T* Context() { return static_cast<T*>(this); }
-
- // Safely iterate over the registered lifecycle observers.
- //
- // Adding or removing observers is not allowed during iteration. The callable
- // will only be called synchronously inside ForEachObserver().
- //
- // Sample usage:
- // ForEachObserver([](ObserverType* observer) {
- // observer->SomeMethod();
- // });
- template <typename ForEachCallable>
- void ForEachObserver(const ForEachCallable& callable) const {
- base::AutoReset<IterationState> scope(&iteration_state_, kAllowingNone);
- for (LifecycleObserverBase* observer_base : observers_) {
- Observer* observer = static_cast<Observer*>(observer_base);
- callable(observer);
- }
- }
-
- private:
- using ObserverSet = HeapLinkedHashSet<WeakMember<LifecycleObserverBase>>;
-
- enum IterationState {
- kAllowingNone = 0,
- kAllowingAddition = 1,
- kAllowingRemoval = 2,
- kNotIterating = kAllowingAddition | kAllowingRemoval,
- };
-
- // Iteration state is recorded while iterating the observer set,
- // optionally barring add or remove mutations.
- mutable IterationState iteration_state_;
- ObserverSet observers_;
-};
-
-template <typename T, typename Observer>
-inline LifecycleNotifier<T, Observer>::~LifecycleNotifier() {
- // FIXME: Enable the following ASSERT. Also see a FIXME in
- // Document::detachLayoutTree().
- // DCHECK(!m_observers.size());
-}
-
-// Determine if |contextDestroyed(Observer*) is a public method on
-// class type |Observer|, or any of the class types it derives from.
-template <typename Observer, typename T>
-class HasContextDestroyed {
- using YesType = char;
- using NoType = int;
-
- template <typename V>
- static YesType CheckHasContextDestroyedMethod(
- V* observer,
- T* context = nullptr,
- typename std::enable_if<
- std::is_same<decltype(observer->ContextDestroyed(context)),
- void>::value>::type* g = nullptr);
- template <typename V>
- static NoType CheckHasContextDestroyedMethod(...);
-
- public:
- static_assert(sizeof(Observer), "Observer's class declaration not in scope");
- static const bool value =
- sizeof(YesType) ==
- sizeof(CheckHasContextDestroyedMethod<Observer>(nullptr));
-};
-
-// If |Observer::contextDestroyed()| is present, invoke it.
-template <typename Observer,
- typename T,
- bool = HasContextDestroyed<Observer, T>::value>
-class ContextDestroyedNotifier {
- STATIC_ONLY(ContextDestroyedNotifier);
-
- public:
- static void Call(Observer* observer, T* context) {
- observer->ContextDestroyed(context);
- }
-};
-
-template <typename Observer, typename T>
-class ContextDestroyedNotifier<Observer, T, false> {
- STATIC_ONLY(ContextDestroyedNotifier);
-
- public:
- static void Call(Observer*, T*) {}
-};
-
-template <typename T, typename Observer>
-inline void LifecycleNotifier<T, Observer>::NotifyContextDestroyed() {
- // Observer unregistration is allowed, but effectively a no-op.
- base::AutoReset<IterationState> scope(&iteration_state_, kAllowingRemoval);
- ObserverSet observers;
- observers_.Swap(observers);
- for (LifecycleObserverBase* observer_base : observers) {
- Observer* observer = static_cast<Observer*>(observer_base);
- DCHECK(observer->LifecycleContext() == Context());
- ContextDestroyedNotifier<Observer, T>::Call(observer, Context());
- observer->ClearContext();
- }
- // Explicitly free the backing store to avoid memory regressions.
- // TODO(bikineev): Revisit after young generation is done.
- observers.clear();
-}
-
-template <typename T, typename Observer>
-inline void LifecycleNotifier<T, Observer>::AddObserver(
- LifecycleObserverBase* observer) {
- CHECK(iteration_state_ & kAllowingAddition);
- observers_.insert(observer);
-}
-
-template <typename T, typename Observer>
-inline void LifecycleNotifier<T, Observer>::RemoveObserver(
- LifecycleObserverBase* observer) {
- CHECK(iteration_state_ & kAllowingRemoval);
- observers_.erase(observer);
-}
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LIFECYCLE_NOTIFIER_H_
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_observer.h b/chromium/third_party/blink/renderer/platform/lifecycle_observer.h
deleted file mode 100644
index 491550573f6..00000000000
--- a/chromium/third_party/blink/renderer/platform/lifecycle_observer.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LIFECYCLE_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LIFECYCLE_OBSERVER_H_
-
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-template <typename Context, typename Observer>
-class LifecycleNotifier;
-
-class LifecycleObserverBase : public GarbageCollectedMixin {};
-
-template <typename Context, typename Observer>
-class LifecycleObserver : public LifecycleObserverBase {
- public:
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(lifecycle_context_);
- }
-
- Context* LifecycleContext() const { return lifecycle_context_; }
-
- void ClearContext() { SetContext(nullptr); }
-
- protected:
- explicit LifecycleObserver(Context* context) : lifecycle_context_(nullptr) {
- SetContext(context);
- }
-
- void SetContext(Context*);
-
- private:
- WeakMember<Context> lifecycle_context_;
-};
-
-template <typename Context, typename Observer>
-inline void LifecycleObserver<Context, Observer>::SetContext(Context* context) {
- using Notifier = LifecycleNotifier<Context, Observer>;
-
- if (lifecycle_context_ == context)
- return;
-
- if (lifecycle_context_) {
- static_cast<Notifier*>(lifecycle_context_)->RemoveObserver(this);
- }
-
- lifecycle_context_ = context;
-
- if (lifecycle_context_) {
- static_cast<Notifier*>(lifecycle_context_)->AddObserver(this);
- }
-}
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LIFECYCLE_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
index 731514c2914..c050053f89d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -103,8 +103,12 @@ blink_platform_sources("loader") {
"fetch/stale_revalidation_resource_client.h",
"fetch/text_resource_decoder_options.cc",
"fetch/text_resource_decoder_options.h",
+ "fetch/trust_token_params_conversion.cc",
+ "fetch/trust_token_params_conversion.h",
"fetch/unique_identifier.cc",
"fetch/unique_identifier.h",
+ "fetch/url_loader/request_conversion.cc",
+ "fetch/url_loader/request_conversion.h",
"fetch/worker_resource_timing_notifier.h",
"ftp_directory_listing.cc",
"ftp_directory_listing.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/DEPS b/chromium/third_party/blink/renderer/platform/loader/DEPS
index bea7ce0ccd6..e99fddc126d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/DEPS
@@ -63,4 +63,13 @@ specific_include_rules = {
"replaying_web_data_consumer_handle.h": [
"+third_party/blink/renderer/platform/waitable_event.h",
],
+ "request_conversion.cc": [
+ # This file consists of conversion functions and hence needs to access
+ # both the blink and chromium mojom variants.
+ "+net/base/request_priority.h",
+ "+net/http/http_request_headers.h",
+ "+net/http/http_util.h",
+ "+third_party/blink/public/mojom/blob/blob.mojom.h",
+ "+services/network/public/mojom/data_pipe_getter.mojom.h",
+ ]
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
index 42c442fb1d9..4b4c2cc6c9d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace blink {
@@ -89,7 +90,7 @@ class HTTPHeaderNameListParser {
// in |output| when successful. Otherwise, returns with |output| kept empty.
//
// |output| must be empty.
- void Parse(WebHTTPHeaderSet& output) {
+ void Parse(HTTPHeaderSet& output) {
DCHECK(output.empty());
while (true) {
@@ -160,12 +161,11 @@ namespace cors {
base::Optional<network::CorsErrorStatus> CheckAccess(
const KURL& response_url,
- const int response_status_code,
const HTTPHeaderMap& response_header,
network::mojom::CredentialsMode credentials_mode,
const SecurityOrigin& origin) {
return network::cors::CheckAccess(
- response_url, response_status_code,
+ response_url,
GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
GetHeaderValue(response_header,
http_names::kAccessControlAllowCredentials),
@@ -201,11 +201,6 @@ base::Optional<network::CorsErrorStatus> CheckRedirectLocation(
url, request_mode, origin_to_pass, cors_flag == CorsFlag::Set, false);
}
-base::Optional<network::mojom::CorsError> CheckPreflight(
- const int preflight_response_status_code) {
- return network::cors::CheckPreflight(preflight_response_status_code);
-}
-
base::Optional<network::CorsErrorStatus> CheckExternalPreflight(
const HTTPHeaderMap& response_header) {
return network::cors::CheckExternalPreflight(
@@ -253,8 +248,9 @@ base::Optional<network::CorsErrorStatus> EnsurePreflightResultAndCacheOnSuccess(
if (status)
return status;
- GetPerThreadPreflightCache().AppendEntry(origin.Ascii(), request_url,
- std::move(result));
+ GetPerThreadPreflightCache().AppendEntry(
+ url::Origin::Create(GURL(origin.Ascii())), request_url,
+ net::NetworkIsolationKey(), std::move(result));
return base::nullopt;
}
@@ -270,7 +266,8 @@ bool CheckIfRequestCanSkipPreflight(
// |is_revalidating| is not needed for blink-side CORS.
constexpr bool is_revalidating = false;
return GetPerThreadPreflightCache().CheckIfRequestCanSkipPreflight(
- origin.Ascii(), url, credentials_mode, method.Ascii(),
+ url::Origin::Create(GURL(origin.Ascii())), url,
+ net::NetworkIsolationKey(), credentials_mode, method.Ascii(),
*CreateNetHttpRequestHeaders(request_header_map), is_revalidating);
}
@@ -392,7 +389,7 @@ bool CalculateCorsFlag(const KURL& url,
const SecurityOrigin* initiator_origin,
const SecurityOrigin* isolated_world_origin,
network::mojom::RequestMode request_mode) {
- if (network::IsNavigationRequestMode(request_mode) ||
+ if (request_mode == network::mojom::RequestMode::kNavigate ||
request_mode == network::mojom::RequestMode::kNoCors) {
return false;
}
@@ -410,7 +407,7 @@ bool CalculateCorsFlag(const KURL& url,
return true;
}
-WebHTTPHeaderSet ExtractCorsExposedHeaderNamesList(
+HTTPHeaderSet ExtractCorsExposedHeaderNamesList(
network::mojom::CredentialsMode credentials_mode,
const ResourceResponse& response) {
// If a response was fetched via a service worker, it will always have
@@ -418,13 +415,13 @@ WebHTTPHeaderSet ExtractCorsExposedHeaderNamesList(
// For requests that didn't come from a service worker, just parse the CORS
// header.
if (response.WasFetchedViaServiceWorker()) {
- WebHTTPHeaderSet header_set;
+ HTTPHeaderSet header_set;
for (const auto& header : response.CorsExposedHeaderNames())
header_set.insert(header.Ascii());
return header_set;
}
- WebHTTPHeaderSet header_set;
+ HTTPHeaderSet header_set;
HTTPHeaderNameListParser parser(
response.HttpHeaderField(http_names::kAccessControlExposeHeaders));
parser.Parse(header_set);
@@ -441,7 +438,7 @@ WebHTTPHeaderSet ExtractCorsExposedHeaderNamesList(
bool IsCorsSafelistedResponseHeader(const String& name) {
// https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
// TODO(dcheng): Consider using a flat_set here with a transparent comparator.
- DEFINE_THREAD_SAFE_STATIC_LOCAL(WebHTTPHeaderSet,
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(HTTPHeaderSet,
allowed_cross_origin_response_headers,
({
"cache-control",
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
index 84998f9c4b2..610c2c75c3f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
@@ -10,7 +10,7 @@
#include "services/network/public/mojom/cors.mojom-blink-forward.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
-#include "third_party/blink/public/platform/web_http_header_set.h"
+#include "third_party/blink/renderer/platform/network/http_header_set.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -35,7 +35,6 @@ namespace cors {
// be removed.
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckAccess(
const KURL&,
- const int response_status_code,
const HTTPHeaderMap&,
network::mojom::CredentialsMode,
const SecurityOrigin&);
@@ -53,9 +52,6 @@ PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckRedirectLocation(
const SecurityOrigin*,
CorsFlag);
-PLATFORM_EXPORT base::Optional<network::mojom::CorsError> CheckPreflight(
- const int preflight_response_status_code);
-
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckExternalPreflight(
const HTTPHeaderMap&);
@@ -124,7 +120,7 @@ PLATFORM_EXPORT bool CalculateCorsFlag(
const SecurityOrigin* isolated_world_origin,
network::mojom::RequestMode request_mode);
-PLATFORM_EXPORT WebHTTPHeaderSet
+PLATFORM_EXPORT HTTPHeaderSet
ExtractCorsExposedHeaderNamesList(network::mojom::CredentialsMode,
const ResourceResponse&);
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
index e68e93c56b7..173f852a577 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
@@ -17,8 +17,8 @@ class CorsExposedHeadersTest : public testing::Test {
public:
using CredentialsMode = network::mojom::CredentialsMode;
- WebHTTPHeaderSet Parse(CredentialsMode credentials_mode,
- const AtomicString& header) const {
+ HTTPHeaderSet Parse(CredentialsMode credentials_mode,
+ const AtomicString& header) const {
ResourceResponse response;
response.AddHttpHeaderField("access-control-expose-headers", header);
@@ -27,25 +27,24 @@ class CorsExposedHeadersTest : public testing::Test {
};
TEST_F(CorsExposedHeadersTest, ValidInput) {
- EXPECT_EQ(Parse(CredentialsMode::kOmit, "valid"),
- WebHTTPHeaderSet({"valid"}));
+ EXPECT_EQ(Parse(CredentialsMode::kOmit, "valid"), HTTPHeaderSet({"valid"}));
- EXPECT_EQ(Parse(CredentialsMode::kOmit, "a,b"), WebHTTPHeaderSet({"a", "b"}));
+ EXPECT_EQ(Parse(CredentialsMode::kOmit, "a,b"), HTTPHeaderSet({"a", "b"}));
EXPECT_EQ(Parse(CredentialsMode::kOmit, " a , b "),
- WebHTTPHeaderSet({"a", "b"}));
+ HTTPHeaderSet({"a", "b"}));
EXPECT_EQ(Parse(CredentialsMode::kOmit, " \t \t\t a"),
- WebHTTPHeaderSet({"a"}));
+ HTTPHeaderSet({"a"}));
- EXPECT_EQ(Parse(CredentialsMode::kOmit, "a , "), WebHTTPHeaderSet({"a", ""}));
+ EXPECT_EQ(Parse(CredentialsMode::kOmit, "a , "), HTTPHeaderSet({"a", ""}));
}
TEST_F(CorsExposedHeadersTest, DuplicatedEntries) {
- EXPECT_EQ(Parse(CredentialsMode::kOmit, "a, a"), WebHTTPHeaderSet{"a"});
+ EXPECT_EQ(Parse(CredentialsMode::kOmit, "a, a"), HTTPHeaderSet{"a"});
EXPECT_EQ(Parse(CredentialsMode::kOmit, "a, a, b"),
- WebHTTPHeaderSet({"a", "b"}));
+ HTTPHeaderSet({"a", "b"}));
}
TEST_F(CorsExposedHeadersTest, InvalidInput) {
@@ -81,12 +80,12 @@ TEST_F(CorsExposedHeadersTest, Wildcard) {
EXPECT_EQ(
cors::ExtractCorsExposedHeaderNamesList(CredentialsMode::kOmit, response),
- WebHTTPHeaderSet({"access-control-expose-headers", "b", "c", "d", "*"}));
+ HTTPHeaderSet({"access-control-expose-headers", "b", "c", "d", "*"}));
EXPECT_EQ(
cors::ExtractCorsExposedHeaderNamesList(CredentialsMode::kSameOrigin,
response),
- WebHTTPHeaderSet({"access-control-expose-headers", "b", "c", "d", "*"}));
+ HTTPHeaderSet({"access-control-expose-headers", "b", "c", "d", "*"}));
}
TEST_F(CorsExposedHeadersTest, Asterisk) {
@@ -99,7 +98,7 @@ TEST_F(CorsExposedHeadersTest, Asterisk) {
EXPECT_EQ(cors::ExtractCorsExposedHeaderNamesList(CredentialsMode::kInclude,
response),
- WebHTTPHeaderSet({"a", "b", "*"}));
+ HTTPHeaderSet({"a", "b", "*"}));
}
// Keep this in sync with the CalculateResponseTainting test in
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS b/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS
index d430e11a2d9..35694fdca61 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS
@@ -1,3 +1,5 @@
include_rules = [
+ "+net/dns/public",
"+services/network/public/cpp/fetch_api_utils.h",
+ "+services/network/public/cpp/optional_trust_token_params.h",
]
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
index 923c1903f67..e8411eddd6c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
@@ -6,23 +6,22 @@
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
-#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
+namespace {
+constexpr int32_t kDelayMilliseconds = 50;
+} // namespace
+
// static
BufferingBytesConsumer* BufferingBytesConsumer::CreateWithDelay(
BytesConsumer* bytes_consumer,
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner) {
- if (!base::FeatureList::IsEnabled(features::kBufferingBytesConsumerDelay))
- return Create(bytes_consumer);
-
return MakeGarbageCollected<BufferingBytesConsumer>(
util::PassKey<BufferingBytesConsumer>(), bytes_consumer,
std::move(timer_task_runner),
- base::TimeDelta::FromMilliseconds(
- features::kBufferingBytesConsumerDelayMilliseconds.Get()));
+ base::TimeDelta::FromMilliseconds(kDelayMilliseconds));
}
// static
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h
index 194590efe87..49155275231 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h
@@ -79,7 +79,7 @@ class PLATFORM_EXPORT BufferingBytesConsumer final
Error GetError() const override;
String DebugName() const override { return "BufferingBytesConsumer"; }
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
void OnTimerFired(TimerBase*);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
index 1f17f0aadfc..8c298b58301 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
@@ -7,7 +7,6 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
#include "third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h"
@@ -74,10 +73,6 @@ TEST_F(BufferingBytesConsumerTest, ReadWithDelay) {
auto* replaying_bytes_consumer =
MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- features::kBufferingBytesConsumerDelay, {{"milliseconds", "10"}});
-
replaying_bytes_consumer->Add(Command(Command::kWait));
replaying_bytes_consumer->Add(Command(Command::kData, "1"));
replaying_bytes_consumer->Add(Command(Command::kWait));
@@ -143,10 +138,6 @@ TEST_F(BufferingBytesConsumerTest, Buffering) {
}
TEST_F(BufferingBytesConsumerTest, BufferingWithDelay) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- features::kBufferingBytesConsumerDelay, {{"milliseconds", "10"}});
-
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
auto* replaying_bytes_consumer =
MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
@@ -175,7 +166,7 @@ TEST_F(BufferingBytesConsumerTest, BufferingWithDelay) {
EXPECT_EQ(PublicState::kReadableOrWaiting,
replaying_bytes_consumer->GetPublicState());
- task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(11));
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(51));
task_runner->RunUntilIdle();
// After the delay expires the underlying consumer should be completely read.
@@ -242,10 +233,6 @@ TEST_F(BufferingBytesConsumerTest, DrainAsDataPipeFailsWithoutDelay) {
}
TEST_F(BufferingBytesConsumerTest, DrainAsDataPipeSucceedsWithDelay) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- features::kBufferingBytesConsumerDelay, {{"milliseconds", "10"}});
-
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
@@ -262,10 +249,6 @@ TEST_F(BufferingBytesConsumerTest, DrainAsDataPipeSucceedsWithDelay) {
}
TEST_F(BufferingBytesConsumerTest, DrainAsDataPipeFailsWithExpiredDelay) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- features::kBufferingBytesConsumerDelay, {{"milliseconds", "10"}});
-
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
@@ -276,7 +259,7 @@ TEST_F(BufferingBytesConsumerTest, DrainAsDataPipeFailsWithExpiredDelay) {
auto* bytes_consumer = BufferingBytesConsumer::CreateWithDelay(
data_pipe_consumer, scheduler::GetSingleThreadTaskRunnerForTesting());
- task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(11));
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(51));
EXPECT_EQ(PublicState::kReadableOrWaiting, bytes_consumer->GetPublicState());
auto drained_consumer_handle = bytes_consumer->DrainAsDataPipe();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
index c557ed1495d..5ec8bba5dd9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
@@ -177,7 +177,7 @@ class PLATFORM_EXPORT BytesConsumer : public GarbageCollected<BytesConsumer> {
// Returns a BytesConsumer whose state is Errored.
static BytesConsumer* CreateErrored(const Error&);
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
protected:
// This InternalState directly corresponds to the states in the class
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
index 3aea5dc8784..c0a819c63b0 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
@@ -20,8 +20,9 @@ class CachedMetadata;
class ResourceResponse;
class WebProcessMemoryDump;
-// A callback for sending the serialized data of cached metadata back to the
-// platform.
+// A callback for sending the serialized data of cached metadata to the
+// persistent storage.
+// TODO(pasko): rename this class to CachedMetadataPersister.
class PLATFORM_EXPORT CachedMetadataSender {
USING_FAST_MALLOC(CachedMetadataSender);
@@ -46,9 +47,19 @@ PLATFORM_EXPORT bool ShouldUseIsolatedCodeCache(mojom::RequestContextType,
// Handler class for caching operations.
class CachedMetadataHandler : public GarbageCollected<CachedMetadataHandler> {
public:
- enum CacheType {
- kSendToPlatform, // send cache data to blink::Platform::cacheMetadata
- kCacheLocally // cache only in Resource's member variables
+ enum ClearCacheType {
+ // Clears the in-memory cache, but doesn't update persistent storage. The
+ // old cached metadata is considered invalid.
+ kClearLocally,
+
+ // Discards the in-memory cache for memory reduction, preventing any further
+ // uses or updates. The cached metadata will no longer be available, but
+ // should not be considered invalid.
+ kDiscardLocally,
+
+ // Clears the metadata in both memory and persistent storage via
+ // blink::Platform::CacheMetadata.
+ kClearPersistentStorage
};
// Enum for marking serialized cached metadatas so that the deserializers
@@ -60,10 +71,11 @@ class CachedMetadataHandler : public GarbageCollected<CachedMetadataHandler> {
};
virtual ~CachedMetadataHandler() = default;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
- // Reset existing metadata, to allow setting new data.
- virtual void ClearCachedMetadata(CacheType = kCacheLocally) = 0;
+ // Reset existing metadata. Subclasses can ignore setting new metadata after
+ // clearing with |kDiscardLocally| to save memory.
+ virtual void ClearCachedMetadata(ClearCacheType) = 0;
// Returns the encoding to which the cache is specific.
virtual String Encoding() const = 0;
@@ -88,8 +100,13 @@ class SingleCachedMetadataHandler : public CachedMetadataHandler {
// identifier that is used to distinguish data generated by the caller.
virtual void SetCachedMetadata(uint32_t data_type_id,
const uint8_t*,
- size_t,
- CacheType = kSendToPlatform) = 0;
+ size_t) = 0;
+
+ // Permanently disable persisting CachedMetadata in the platform only when it
+ // is set.
+ void DisableSendToPlatformForTesting() {
+ disable_send_to_platform_for_testing_ = true;
+ }
// Returns cached metadata of the given type associated with this resource.
// This cached metadata can be pruned at any time.
@@ -98,6 +115,7 @@ class SingleCachedMetadataHandler : public CachedMetadataHandler {
protected:
SingleCachedMetadataHandler() = default;
+ bool disable_send_to_platform_for_testing_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
index 3af7c4975b2..b49dc9e74a1 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
@@ -14,64 +14,6 @@
namespace blink {
-namespace {
-
-void ParseAcceptChHeader(const String& header_value,
- WebEnabledClientHints& enabled_hints) {
- CommaDelimitedHeaderSet accept_client_hints_header;
- ParseCommaDelimitedHeader(header_value, accept_client_hints_header);
-
- for (size_t i = 0;
- i < static_cast<int>(mojom::WebClientHintsType::kMaxValue) + 1; ++i) {
- enabled_hints.SetIsEnabled(
- static_cast<mojom::WebClientHintsType>(i),
- accept_client_hints_header.Contains(kClientHintsNameMapping[i]));
- }
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kDeviceMemory,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kDeviceMemory));
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kRtt,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kRtt));
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kDownlink,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kDownlink));
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kEct,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kEct));
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kLang,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kLang) &&
- RuntimeEnabledFeatures::LangClientHintHeaderEnabled());
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kUA,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kUA) &&
- RuntimeEnabledFeatures::UserAgentClientHintEnabled());
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kUAArch,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kUAArch) &&
- RuntimeEnabledFeatures::UserAgentClientHintEnabled());
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kUAPlatform,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kUAPlatform) &&
- RuntimeEnabledFeatures::UserAgentClientHintEnabled());
-
- enabled_hints.SetIsEnabled(
- mojom::WebClientHintsType::kUAModel,
- enabled_hints.IsEnabled(mojom::WebClientHintsType::kUAModel) &&
- RuntimeEnabledFeatures::UserAgentClientHintEnabled());
-}
-
-} // namespace
-
ClientHintsPreferences::ClientHintsPreferences() {
DCHECK_EQ(static_cast<size_t>(mojom::WebClientHintsType::kMaxValue) + 1,
kClientHintsMappingsCount);
@@ -97,16 +39,24 @@ void ClientHintsPreferences::UpdateFromAcceptClientHintsHeader(
if (!IsClientHintsAllowed(url))
return;
- WebEnabledClientHints new_enabled_types;
+ // 8-bit conversions from String can turn non-ASCII characters into ?,
+ // turning syntax errors into "correct" syntax, so reject those first.
+ // (.Utf8() doesn't have this problem, but it does a lot of expensive
+ // work that would be wasted feeding to an ASCII-only syntax).
+ if (!header_value.ContainsOnlyASCIIOrEmpty())
+ return;
- ParseAcceptChHeader(header_value, new_enabled_types);
+ // Note: .Ascii() would convert tab to ?, which is undesirable.
+ base::Optional<std::vector<blink::mojom::WebClientHintsType>> parsed_ch =
+ ParseAcceptCH(header_value.Latin1(),
+ RuntimeEnabledFeatures::LangClientHintHeaderEnabled(),
+ RuntimeEnabledFeatures::UserAgentClientHintEnabled());
+ if (!parsed_ch.has_value())
+ return;
- for (size_t i = 0;
- i < static_cast<int>(mojom::WebClientHintsType::kMaxValue) + 1; ++i) {
- mojom::WebClientHintsType type = static_cast<mojom::WebClientHintsType>(i);
- enabled_hints_.SetIsEnabled(type, enabled_hints_.IsEnabled(type) ||
- new_enabled_types.IsEnabled(type));
- }
+ // Note: this keeps previously enabled hints.
+ for (blink::mojom::WebClientHintsType newly_enabled : parsed_ch.value())
+ enabled_hints_.SetIsEnabled(newly_enabled, true);
if (context) {
for (size_t i = 0;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
index e3e328e565d..1b6afccf66a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
@@ -28,31 +28,33 @@ TEST_F(ClientHintsPreferencesTest, BasicSecure) {
bool expectation_ua_arch;
bool expectation_ua_platform;
bool expectation_ua_model;
+ bool expectation_ua_full_version;
} cases[] = {
{"width, dpr, viewportWidth", true, true, false, false, false, false,
- false, false, false, false, false},
+ false, false, false, false, false, false},
{"WiDtH, dPr, viewport-width, rtt, downlink, ect, lang", true, true, true,
- true, true, true, true, false, false, false, false},
+ true, true, true, true, false, false, false, false, false},
{"WiDtH, dPr, viewport-width, rtt, downlink, effective-connection-type",
- true, true, true, true, true, false, false, false, false, false, false},
+ true, true, true, true, true, false, false, false, false, false, false,
+ false},
{"WIDTH, DPR, VIWEPROT-Width", true, true, false, false, false, false,
- false, false, false, false, false},
+ false, false, false, false, false, false},
{"VIewporT-Width, wutwut, width", true, false, true, false, false, false,
- false, false, false, false, false},
+ false, false, false, false, false, false},
{"dprw", false, false, false, false, false, false, false, false, false,
- false, false},
+ false, false, false},
{"DPRW", false, false, false, false, false, false, false, false, false,
- false, false},
+ false, false, false},
{"ua", false, false, false, false, false, false, false, true, false,
- false, false},
- {"arch", false, false, false, false, false, false, false, false, true,
- false, false},
- {"platform", false, false, false, false, false, false, false, false,
- false, true, false},
- {"model", false, false, false, false, false, false, false, false, false,
- false, true},
- {"ua, arch, platform, model", false, false, false, false, false, false,
- false, true, true, true, true},
+ false, false, false},
+ {"ua-arch", false, false, false, false, false, false, false, false, true,
+ false, false, false},
+ {"ua-platform", false, false, false, false, false, false, false, false,
+ false, true, false, false},
+ {"ua-model", false, false, false, false, false, false, false, false,
+ false, false, true, false},
+ {"ua, ua-arch, ua-platform, ua-model, ua-full-version", false, false,
+ false, false, false, false, false, true, true, true, true, true},
};
for (const auto& test_case : cases) {
@@ -214,23 +216,25 @@ TEST_F(ClientHintsPreferencesTest, ParseHeaders) {
bool expect_ua_arch;
bool expect_ua_platform;
bool expect_ua_model;
+ bool expect_ua_full_version;
} test_cases[] = {
{"width, dpr, viewportWidth, lang", "", 0, false, true, true, false,
- false, false, false, true, false, false, false, false},
+ false, false, false, true, false, false, false, false, false},
{"width, dpr, viewportWidth", "-1000", 0, false, true, true, false, false,
- false, false, false, false, false, false, false},
+ false, false, false, false, false, false, false, false},
{"width, dpr, viewportWidth", "1000s", 0, false, true, true, false, false,
- false, false, false, false, false, false, false},
- {"width, dpr, viewportWidth", "1000.5", 0, false, true, true, false,
false, false, false, false, false, false, false, false},
+ {"width, dpr, viewportWidth", "1000.5", 0, false, true, true, false,
+ false, false, false, false, false, false, false, false, false},
{"width, dpr, rtt, downlink, ect", "1000", 1000, false, true, true, false,
- true, true, true, false, false, false, false, false},
+ true, true, true, false, false, false, false, false, false},
{"device-memory", "-1000", 0, true, false, false, false, false, false,
- false, false, false, false, false, false},
+ false, false, false, false, false, false, false},
{"dpr rtt", "1000", 1000, false, false, false, false, false, false, false,
- false, false, false, false, false},
- {"ua, arch, platform, model", "1000", 1000, false, false, false, false,
- false, false, false, false, true, true, true, true},
+ false, false, false, false, false, false},
+ {"ua, ua-arch, ua-platform, ua-model, ua-full-version", "1000", 1000,
+ false, false, false, false, false, false, false, false, true, true, true,
+ true, true},
};
for (const auto& test : test_cases) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc
index 42054403a7b..c36b32b18fc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc
@@ -153,7 +153,7 @@ BytesConsumer::PublicState DataPipeBytesConsumer::GetPublicState() const {
return GetPublicStateFromInternalState(state_);
}
-void DataPipeBytesConsumer::Trace(blink::Visitor* visitor) {
+void DataPipeBytesConsumer::Trace(Visitor* visitor) {
visitor->Trace(client_);
BytesConsumer::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h
index 4d84e2b8205..9bfc9775f21 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h
@@ -40,7 +40,7 @@ class PLATFORM_EXPORT DataPipeBytesConsumer final : public BytesConsumer {
// written into the pipe.
void SignalComplete();
void SignalError(const BytesConsumer::Error& error);
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
private:
const WeakMember<DataPipeBytesConsumer> bytes_consumer_;
@@ -65,7 +65,7 @@ class PLATFORM_EXPORT DataPipeBytesConsumer final : public BytesConsumer {
}
String DebugName() const override { return "DataPipeBytesConsumer"; }
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
bool IsReadableOrWaiting() const;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
index 3ffd87b8aba..9f5f505218e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
@@ -8,7 +8,7 @@
#include "base/optional.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
-#include "third_party/blink/public/platform/web_insecure_request_policy.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
@@ -81,7 +81,8 @@ class PLATFORM_EXPORT FetchClientSettingsObject
virtual network::mojom::IPAddressSpace GetAddressSpace() const = 0;
// https://w3c.github.io/webappsec-upgrade-insecure-requests/#insecure-requests-policy
- virtual WebInsecureRequestPolicy GetInsecureRequestsPolicy() const = 0;
+ virtual mojom::blink::InsecureRequestPolicy GetInsecureRequestsPolicy()
+ const = 0;
// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-insecure-navigations-set
using InsecureNavigationsSet = HashSet<unsigned, WTF::AlreadyHashed>;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc
index ad064d1dba4..e11f91fc064 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/heap/trace_traits.h"
namespace blink {
@@ -45,7 +46,7 @@ FetchClientSettingsObjectSnapshot::FetchClientSettingsObjectSnapshot(
HttpsState https_state,
AllowedByNosniff::MimeTypeCheck mime_type_check_for_classic_worker_script,
network::mojom::IPAddressSpace address_space,
- WebInsecureRequestPolicy insecure_requests_policy,
+ mojom::blink::InsecureRequestPolicy insecure_requests_policy,
InsecureNavigationsSet insecure_navigations_set)
: global_object_url_(global_object_url),
base_url_(base_url),
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
index 84a9a1b9cc1..b4ae59e5550 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_CLIENT_SETTINGS_OBJECT_SNAPSHOT_H_
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -37,7 +38,7 @@ struct CrossThreadFetchClientSettingsObjectData {
HttpsState https_state,
AllowedByNosniff::MimeTypeCheck mime_type_check_for_classic_worker_script,
network::mojom::IPAddressSpace address_space,
- WebInsecureRequestPolicy insecure_requests_policy,
+ mojom::blink::InsecureRequestPolicy insecure_requests_policy,
FetchClientSettingsObject::InsecureNavigationsSet
insecure_navigations_set)
: global_object_url(std::move(global_object_url)),
@@ -61,7 +62,7 @@ struct CrossThreadFetchClientSettingsObjectData {
const AllowedByNosniff::MimeTypeCheck
mime_type_check_for_classic_worker_script;
const network::mojom::IPAddressSpace address_space;
- const WebInsecureRequestPolicy insecure_requests_policy;
+ const mojom::blink::InsecureRequestPolicy insecure_requests_policy;
const FetchClientSettingsObject::InsecureNavigationsSet
insecure_navigations_set;
@@ -94,7 +95,7 @@ class PLATFORM_EXPORT FetchClientSettingsObjectSnapshot final
HttpsState https_state,
AllowedByNosniff::MimeTypeCheck,
network::mojom::IPAddressSpace,
- WebInsecureRequestPolicy,
+ mojom::blink::InsecureRequestPolicy,
InsecureNavigationsSet);
~FetchClientSettingsObjectSnapshot() override = default;
@@ -116,7 +117,8 @@ class PLATFORM_EXPORT FetchClientSettingsObjectSnapshot final
return address_space_;
}
- WebInsecureRequestPolicy GetInsecureRequestsPolicy() const override {
+ mojom::blink::InsecureRequestPolicy GetInsecureRequestsPolicy()
+ const override {
return insecure_requests_policy_;
}
@@ -151,7 +153,7 @@ class PLATFORM_EXPORT FetchClientSettingsObjectSnapshot final
mime_type_check_for_classic_worker_script_;
const network::mojom::IPAddressSpace address_space_;
- const WebInsecureRequestPolicy insecure_requests_policy_;
+ const mojom::blink::InsecureRequestPolicy insecure_requests_policy_;
const InsecureNavigationsSet insecure_navigations_set_;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index cb44fc15e85..916041c76e1 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -47,7 +47,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h"
+#include "third_party/blink/renderer/platform/weborigin/reporting_disposition.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
@@ -75,7 +75,7 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
virtual ~FetchContext() = default;
- virtual void Trace(blink::Visitor*) {}
+ virtual void Trace(Visitor*) {}
virtual void AddAdditionalRequestHeaders(ResourceRequest&);
@@ -112,7 +112,7 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
const ResourceRequest&,
const KURL&,
const ResourceLoaderOptions&,
- SecurityViolationReportingPolicy,
+ ReportingDisposition,
ResourceRequest::RedirectStatus) const {
return ResourceRequestBlockedReason::kOther;
}
@@ -120,7 +120,7 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
mojom::RequestContextType,
const KURL&,
const ResourceLoaderOptions&,
- SecurityViolationReportingPolicy,
+ ReportingDisposition,
ResourceRequest::RedirectStatus) const {
return ResourceRequestBlockedReason::kOther;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
index eea543633a1..c57dfd3b668 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -33,16 +33,16 @@
namespace blink {
-FetchParameters::FetchParameters(const ResourceRequest& resource_request)
- : resource_request_(resource_request),
+FetchParameters::FetchParameters(ResourceRequest resource_request)
+ : resource_request_(std::move(resource_request)),
decoder_options_(TextResourceDecoderOptions::kPlainTextContent),
speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
defer_(kNoDefer),
image_request_optimization_(kNone) {}
-FetchParameters::FetchParameters(const ResourceRequest& resource_request,
+FetchParameters::FetchParameters(ResourceRequest resource_request,
const ResourceLoaderOptions& options)
- : resource_request_(resource_request),
+ : resource_request_(std::move(resource_request)),
decoder_options_(TextResourceDecoderOptions::kPlainTextContent),
options_(options),
speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index de0d27f225b..a1e29fbe9b6 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -71,8 +71,8 @@ class PLATFORM_EXPORT FetchParameters {
ResourceWidth() : width(0), is_set(false) {}
};
- explicit FetchParameters(const ResourceRequest&);
- FetchParameters(const ResourceRequest&, const ResourceLoaderOptions&);
+ explicit FetchParameters(ResourceRequest);
+ FetchParameters(ResourceRequest, const ResourceLoaderOptions&);
FetchParameters(const FetchParameters&) = delete;
FetchParameters& operator=(const FetchParameters&) = delete;
FetchParameters(FetchParameters&&);
@@ -88,6 +88,10 @@ class PLATFORM_EXPORT FetchParameters {
resource_request_.SetRequestContext(context);
}
+ void SetRequestDestination(network::mojom::RequestDestination destination) {
+ resource_request_.SetRequestDestination(destination);
+ }
+
void SetFetchImportanceMode(mojom::FetchImportanceMode importance_mode) {
resource_request_.SetFetchImportanceMode(importance_mode);
}
@@ -139,7 +143,7 @@ class PLATFORM_EXPORT FetchParameters {
}
void SetContentSecurityCheck(
- ContentSecurityPolicyDisposition content_security_policy_option) {
+ network::mojom::CSPDisposition content_security_policy_option) {
options_.content_security_policy_option = content_security_policy_option;
}
// Configures the request to use the "cors" mode and the credentials mode
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
index 216c0f02ba1..f43766d2fcd 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
@@ -66,7 +66,7 @@ MemoryCache* ReplaceMemoryCacheForTesting(MemoryCache* cache) {
return old_cache;
}
-void MemoryCacheEntry::Trace(blink::Visitor* visitor) {
+void MemoryCacheEntry::Trace(Visitor* visitor) {
visitor->template RegisterWeakCallbackMethod<
MemoryCacheEntry, &MemoryCacheEntry::ClearResourceWeak>(this);
}
@@ -93,7 +93,7 @@ MemoryCache::MemoryCache(
MemoryCache::~MemoryCache() = default;
-void MemoryCache::Trace(blink::Visitor* visitor) {
+void MemoryCache::Trace(Visitor* visitor) {
visitor->Trace(resource_maps_);
MemoryCacheDumpClient::Trace(visitor);
MemoryPressureListener::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
index bc8e09b6442..d797ba16873 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
@@ -51,7 +51,7 @@ class MemoryCacheEntry final : public GarbageCollected<MemoryCacheEntry> {
public:
explicit MemoryCacheEntry(Resource* resource) : resource_(resource) {}
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
Resource* GetResource() const { return resource_; }
private:
@@ -71,7 +71,7 @@ class PLATFORM_EXPORT MemoryCache final : public GarbageCollected<MemoryCache>,
explicit MemoryCache(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~MemoryCache() override;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
struct TypeStatistic {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
index 814e5c4b38f..96a01d2843c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
@@ -95,13 +95,13 @@ class MemoryCacheCorrectnessTest : public testing::Test {
ResourceRequest resource_request{KURL(kResourceURL)};
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
resource_request.SetRequestorOrigin(GetSecurityOrigin());
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
return RawResource::Fetch(fetch_params, Fetcher(), nullptr);
}
MockResource* FetchMockResource() {
ResourceRequest resource_request{KURL(kResourceURL)};
resource_request.SetRequestorOrigin(GetSecurityOrigin());
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
return MockResource::Fetch(fetch_params, Fetcher(), nullptr);
}
ResourceFetcher* Fetcher() const { return fetcher_.Get(); }
@@ -318,7 +318,7 @@ TEST_F(MemoryCacheCorrectnessTest, RequestWithNoCache) {
no_cache_request.SetHttpHeaderField(http_names::kCacheControl, "no-cache");
no_cache_request.SetRequestorOrigin(GetSecurityOrigin());
MockResource* no_cache_resource =
- ResourceFromResourceRequest(no_cache_request);
+ ResourceFromResourceRequest(std::move(no_cache_request));
MockResource* fetched = FetchMockResource();
EXPECT_NE(no_cache_resource, fetched);
}
@@ -349,7 +349,7 @@ TEST_F(MemoryCacheCorrectnessTest, RequestWithNoStore) {
no_store_request.SetHttpHeaderField(http_names::kCacheControl, "no-store");
no_store_request.SetRequestorOrigin(GetSecurityOrigin());
MockResource* no_store_resource =
- ResourceFromResourceRequest(no_store_request);
+ ResourceFromResourceRequest(std::move(no_store_request));
MockResource* fetched = FetchMockResource();
EXPECT_NE(no_store_resource, fetched);
}
@@ -469,7 +469,7 @@ TEST_F(MemoryCacheCorrectnessTest, PostToSameURLTwice) {
ResourceRequest request2{KURL(kResourceURL)};
request2.SetHttpMethod(http_names::kPOST);
request2.SetRequestorOrigin(GetSecurityOrigin());
- FetchParameters fetch2(request2);
+ FetchParameters fetch2(std::move(request2));
RawResource* resource2 = RawResource::FetchSynchronously(fetch2, Fetcher());
EXPECT_NE(resource1, resource2);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
index fe682869223..73ce6bdb973 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
-#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -126,13 +125,7 @@ TEST_F(MemoryCacheTest, CapacityAccounting) {
EXPECT_EQ(kTotalCapacity, GetMemoryCache()->Capacity());
}
-// TODO(crbug.com/850788): Reenable this.
-#if defined(OS_ANDROID)
-#define MAYBE_VeryLargeResourceAccounting DISABLED_VeryLargeResourceAccounting
-#else
-#define MAYBE_VeryLargeResourceAccounting VeryLargeResourceAccounting
-#endif
-TEST_F(MemoryCacheTest, MAYBE_VeryLargeResourceAccounting) {
+TEST_F(MemoryCacheTest, VeryLargeResourceAccounting) {
const size_t kSizeMax = ~static_cast<size_t>(0);
const size_t kTotalCapacity = kSizeMax / 4;
const size_t kResourceSize1 = kSizeMax / 16;
@@ -140,7 +133,12 @@ TEST_F(MemoryCacheTest, MAYBE_VeryLargeResourceAccounting) {
GetMemoryCache()->SetCapacity(kTotalCapacity);
Persistent<MockResourceClient> client =
MakeGarbageCollected<MockResourceClient>();
- FetchParameters params(ResourceRequest("data:text/html,"));
+ // Here and below, use an image MIME type. This is because on Android
+ // non-image MIME types trigger a query to Java to check which video codecs
+ // are supported. This fails in tests. The solution is either to use an image
+ // type, or disable the tests on Android.
+ // crbug.com/850788.
+ FetchParameters params(ResourceRequest("data:image/jpeg,"));
FakeDecodedResource* cached_resource =
FakeDecodedResource::Fetch(params, fetcher_, client);
cached_resource->FakeEncodedSize(kResourceSize1);
@@ -200,14 +198,14 @@ static void TestResourcePruningLater(ResourceFetcher* fetcher,
EXPECT_EQ(0u, GetMemoryCache()->size());
const char kData[6] = "abcde";
- FetchParameters params1(ResourceRequest("data:text/html,resource1"));
+ FetchParameters params1(ResourceRequest("data:image/jpeg,resource1"));
Resource* resource1 = FakeDecodedResource::Fetch(params1, fetcher, nullptr);
GetMemoryCache()->Remove(resource1);
if (!identifier1.IsEmpty())
resource1->SetCacheIdentifier(identifier1);
resource1->AppendData(kData, 3u);
resource1->FinishForTest();
- FetchParameters params2(ResourceRequest("data:text/html,resource2"));
+ FetchParameters params2(ResourceRequest("data:image/jpeg,resource2"));
Persistent<MockResourceClient> client =
MakeGarbageCollected<MockResourceClient>();
Resource* resource2 = FakeDecodedResource::Fetch(params2, fetcher, client);
@@ -230,25 +228,11 @@ static void TestResourcePruningLater(ResourceFetcher* fetcher,
}
// Verified that when ordering a prune in a runLoop task, the prune is deferred.
-// TODO(crbug.com/850788): Reenable this.
-#if defined(OS_ANDROID)
-#define MAYBE_ResourcePruningLater_Basic DISABLED_ResourcePruningLater_Basic
-#else
-#define MAYBE_ResourcePruningLater_Basic ResourcePruningLater_Basic
-#endif
-TEST_F(MemoryCacheTest, MAYBE_ResourcePruningLater_Basic) {
+TEST_F(MemoryCacheTest, ResourcePruningLater_Basic) {
TestResourcePruningLater(fetcher_, "", "");
}
-// TODO(crbug.com/850788): Reenable this.
-#if defined(OS_ANDROID)
-#define MAYBE_ResourcePruningLater_MultipleResourceMaps \
- DISABLED_ResourcePruningLater_MultipleResourceMaps
-#else
-#define MAYBE_ResourcePruningLater_MultipleResourceMaps \
- ResourcePruningLater_MultipleResourceMaps
-#endif
-TEST_F(MemoryCacheTest, MAYBE_ResourcePruningLater_MultipleResourceMaps) {
+TEST_F(MemoryCacheTest, ResourcePruningLater_MultipleResourceMaps) {
{
TestResourcePruningLater(fetcher_, "foo", "");
GetMemoryCache()->EvictResources();
@@ -272,9 +256,9 @@ static void TestClientRemoval(ResourceFetcher* fetcher,
MakeGarbageCollected<MockResourceClient>();
Persistent<MockResourceClient> client2 =
MakeGarbageCollected<MockResourceClient>();
- FetchParameters params1(ResourceRequest("data:text/html,foo"));
+ FetchParameters params1(ResourceRequest("data:image/jpeg,foo"));
Resource* resource1 = FakeDecodedResource::Fetch(params1, fetcher, client1);
- FetchParameters params2(ResourceRequest("data:text/html,bar"));
+ FetchParameters params2(ResourceRequest("data:image/jpeg,bar"));
Resource* resource2 = FakeDecodedResource::Fetch(params2, fetcher, client2);
resource1->AppendData(kData, 4u);
resource2->AppendData(kData, 4u);
@@ -327,25 +311,11 @@ static void TestClientRemoval(ResourceFetcher* fetcher,
EXPECT_EQ(0u, GetMemoryCache()->size());
}
-// TODO(crbug.com/850788): Reenable this.
-#if defined(OS_ANDROID)
-#define MAYBE_ClientRemoval_Basic DISABLED_ClientRemoval_Basic
-#else
-#define MAYBE_ClientRemoval_Basic ClientRemoval_Basic
-#endif
-TEST_F(MemoryCacheTest, MAYBE_ClientRemoval_Basic) {
+TEST_F(MemoryCacheTest, ClientRemoval_Basic) {
TestClientRemoval(fetcher_, "", "");
}
-// TODO(crbug.com/850788): Reenable this.
-#if defined(OS_ANDROID)
-#define MAYBE_ClientRemoval_MultipleResourceMaps \
- DISABLED_ClientRemoval_MultipleResourceMaps
-#else
-#define MAYBE_ClientRemoval_MultipleResourceMaps \
- ClientRemoval_MultipleResourceMaps
-#endif
-TEST_F(MemoryCacheTest, MAYBE_ClientRemoval_MultipleResourceMaps) {
+TEST_F(MemoryCacheTest, ClientRemoval_MultipleResourceMaps) {
{
TestClientRemoval(fetcher_, "foo", "");
GetMemoryCache()->EvictResources();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc
index 8a00bb48575..3a93692ce8b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc
@@ -6,6 +6,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/fetch/https_state.h"
@@ -25,7 +26,7 @@ NullResourceFetcherProperties::NullResourceFetcherProperties()
HttpsState::kNone,
AllowedByNosniff::MimeTypeCheck::kStrict,
network::mojom::IPAddressSpace::kPublic,
- kLeaveInsecureRequestsAlone,
+ mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone,
FetchClientSettingsObject::InsecureNavigationsSet())) {}
void NullResourceFetcherProperties::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
index 4d15c82e932..449d18c456b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
@@ -55,6 +55,7 @@ RawResource* RawResource::FetchImport(FetchParameters& params,
ResourceFetcher* fetcher,
RawResourceClient* client) {
params.SetRequestContext(mojom::RequestContextType::IMPORT);
+ params.SetRequestDestination(network::mojom::RequestDestination::kEmpty);
return ToRawResource(fetcher->RequestResource(
params, RawResourceFactory(ResourceType::kImportResource), client));
}
@@ -85,6 +86,7 @@ RawResource* RawResource::FetchTextTrack(FetchParameters& params,
ResourceFetcher* fetcher,
RawResourceClient* client) {
params.SetRequestContext(mojom::RequestContextType::TRACK);
+ params.SetRequestDestination(network::mojom::RequestDestination::kTrack);
return ToRawResource(fetcher->RequestResource(
params, RawResourceFactory(ResourceType::kTextTrack), client));
}
@@ -171,8 +173,8 @@ void RawResource::DidAddClient(ResourceClient* c) {
RevalidationStartForbiddenScope revalidation_start_forbidden_scope(this);
RawResourceClient* client = static_cast<RawResourceClient*>(c);
for (const auto& redirect : RedirectChain()) {
- ResourceRequest request(redirect.request_);
- client->RedirectReceived(this, request, redirect.redirect_response_);
+ client->RedirectReceived(this, ResourceRequest(redirect.request_),
+ redirect.redirect_response_);
if (!HasClient(c))
return;
}
@@ -406,8 +408,6 @@ void RawResourceClient::DidDownloadToBlob(Resource*,
RawResourceClientStateChecker::RawResourceClientStateChecker()
: state_(kNotAddedAsClient) {}
-RawResourceClientStateChecker::~RawResourceClientStateChecker() = default;
-
NOINLINE void RawResourceClientStateChecker::WillAddClient() {
SECURITY_CHECK(state_ == kNotAddedAsClient);
state_ = kStarted;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
index 11aa7531c9a..3a22921c1f3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
@@ -63,7 +63,7 @@ class PLATFORM_EXPORT RawResource final : public Resource {
RawResourceClient*);
// Exposed for testing
- static RawResource* CreateForTest(ResourceRequest request,
+ static RawResource* CreateForTest(const ResourceRequest& request,
ResourceType type) {
ResourceLoaderOptions options;
return MakeGarbageCollected<RawResource>(request, type, options);
@@ -207,7 +207,6 @@ class PLATFORM_EXPORT RawResourceClientStateChecker final {
public:
RawResourceClientStateChecker();
- ~RawResourceClientStateChecker();
// Call before addClient()/removeClient() is called.
void WillAddClient();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
index 4a1276b11b0..a469fe6ae20 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
@@ -92,7 +92,7 @@ TEST_F(RawResourceTest, DontIgnoreAcceptForCacheReuse) {
ResourceRequest png_request;
png_request.SetHTTPAccept("image/png");
png_request.SetRequestorOrigin(source_origin);
- EXPECT_NE(jpeg_resource->CanReuse(FetchParameters(png_request)),
+ EXPECT_NE(jpeg_resource->CanReuse(FetchParameters(std::move(png_request))),
Resource::MatchStatus::kOk);
}
@@ -124,9 +124,7 @@ class DummyClient final : public GarbageCollected<DummyClient>,
return number_of_redirects_received_;
}
const Vector<char>& Data() { return data_; }
- void Trace(blink::Visitor* visitor) override {
- RawResourceClient::Trace(visitor);
- }
+ void Trace(Visitor* visitor) override { RawResourceClient::Trace(visitor); }
private:
bool called_;
@@ -162,7 +160,7 @@ class AddingClient final : public GarbageCollected<AddingClient>,
void RemoveClient() { resource_->RemoveClient(dummy_client_); }
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(dummy_client_);
visitor->Trace(resource_);
RawResourceClient::Trace(visitor);
@@ -207,7 +205,7 @@ class RemovingClient : public GarbageCollected<RemovingClient>,
resource->RemoveClient(this);
}
String DebugName() const override { return "RemovingClient"; }
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(dummy_client_);
RawResourceClient::Trace(visitor);
}
@@ -255,7 +253,7 @@ TEST_F(RawResourceTest, PreloadWithAsynchronousAddClient) {
// Set the response first to make ResourceClient addition asynchronous.
raw->SetResponse(ResourceResponse(KURL("http://600.613/")));
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
params.MutableResourceRequest().SetUseStreamOnResponse(false);
raw->MatchPreload(params, platform_->test_task_runner().get());
raw->AddClient(dummy_client, platform_->test_task_runner().get());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
index a94e9665eaf..d7c24f32f9e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -122,8 +122,7 @@ const char* const kHeaderPrefixesToIgnoreAfterRevalidation[] = {
static inline bool ShouldUpdateHeaderAfterRevalidation(
const AtomicString& header) {
for (size_t i = 0; i < base::size(kHeadersToIgnoreAfterRevalidation); i++) {
- if (DeprecatedEqualIgnoringCase(header,
- kHeadersToIgnoreAfterRevalidation[i]))
+ if (EqualIgnoringASCIICase(header, kHeadersToIgnoreAfterRevalidation[i]))
return false;
}
for (size_t i = 0; i < base::size(kHeaderPrefixesToIgnoreAfterRevalidation);
@@ -146,7 +145,7 @@ static inline base::Time Now() {
return clock->Now();
}
-Resource::Resource(const ResourceRequest& request,
+Resource::Resource(const ResourceRequestHead& request,
ResourceType type,
const ResourceLoaderOptions& options)
: type_(type),
@@ -174,7 +173,7 @@ Resource::~Resource() {
InstanceCounters::DecrementCounter(InstanceCounters::kResourceCounter);
}
-void Resource::Trace(blink::Visitor* visitor) {
+void Resource::Trace(Visitor* visitor) {
visitor->Trace(loader_);
visitor->Trace(cache_handler_);
visitor->Trace(clients_);
@@ -472,7 +471,7 @@ static bool CanUseResponse(const ResourceResponse& response,
return CurrentAge(response, response_timestamp) <= max_life;
}
-const ResourceRequest& Resource::LastResourceRequest() const {
+const ResourceRequestHead& Resource::LastResourceRequest() const {
if (!redirect_chain_.size())
return GetResourceRequest();
return redirect_chain_.back().request_;
@@ -484,7 +483,7 @@ const ResourceResponse* Resource::LastResourceResponse() const {
return &redirect_chain_.back().redirect_response_;
}
-void Resource::SetRevalidatingRequest(const ResourceRequest& request) {
+void Resource::SetRevalidatingRequest(const ResourceRequestHead& request) {
SECURITY_CHECK(redirect_chain_.IsEmpty());
SECURITY_CHECK(!is_unused_preload_);
DCHECK(!request.IsNull());
@@ -567,22 +566,23 @@ String Resource::ReasonNotDeletable() const {
return builder.ToString();
}
-void Resource::DidAddClient(ResourceClient* c) {
+void Resource::DidAddClient(ResourceClient* client) {
if (scoped_refptr<SharedBuffer> data = Data()) {
for (const auto& span : *data) {
- c->DataReceived(this, span.data(), span.size());
+ client->DataReceived(this, span.data(), span.size());
// Stop pushing data if the client removed itself.
- if (!HasClient(c))
+ if (!HasClient(client))
break;
}
}
- if (!HasClient(c))
+ if (!HasClient(client))
return;
if (IsFinishedInternal()) {
- c->NotifyFinished(this);
- if (clients_.Contains(c)) {
- finished_clients_.insert(c);
- clients_.erase(c);
+ client->SetHasFinishedFromMemoryCache();
+ client->NotifyFinished(this);
+ if (clients_.Contains(client)) {
+ finished_clients_.insert(client);
+ clients_.erase(client);
}
}
}
@@ -823,12 +823,13 @@ Resource::MatchStatus Resource::CanReuse(const FetchParameters& params) const {
if (resource_request_.GetKeepalive() || new_request.GetKeepalive())
return MatchStatus::kKeepaliveSet;
- if (GetResourceRequest().HttpMethod() != new_request.HttpMethod())
+ if (GetResourceRequest().HttpMethod() != http_names::kGET ||
+ new_request.HttpMethod() != http_names::kGET) {
return MatchStatus::kRequestMethodDoesNotMatch;
+ }
- if (GetResourceRequest().HttpBody() != new_request.HttpBody())
- return MatchStatus::kUnknownFailure;
-
+ // A GET request doesn't have a request body.
+ DCHECK(!new_request.HttpBody());
// Don't reuse an existing resource when the source origin is different.
if (!existing_origin->IsSameOriginWith(new_origin.get()))
@@ -851,8 +852,6 @@ Resource::MatchStatus Resource::CanReuse(const FetchParameters& params) const {
switch (new_mode) {
case network::mojom::RequestMode::kNoCors:
case network::mojom::RequestMode::kNavigate:
- case network::mojom::RequestMode::kNavigateNestedFrame:
- case network::mojom::RequestMode::kNavigateNestedObject:
break;
case network::mojom::RequestMode::kCors:
@@ -887,7 +886,7 @@ void Resource::OnPurgeMemory() {
Prune();
if (!cache_handler_)
return;
- cache_handler_->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally);
+ cache_handler_->ClearCachedMetadata(CachedMetadataHandler::kClearLocally);
}
void Resource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
@@ -1068,8 +1067,7 @@ bool Resource::MustRevalidateDueToCacheHeaders(bool allow_stale) const {
GetResourceRequest().CacheControlContainsNoStore();
}
-static bool ShouldRevalidateStaleResponse(const ResourceRequest& request,
- const ResourceResponse& response,
+static bool ShouldRevalidateStaleResponse(const ResourceResponse& response,
base::Time response_timestamp) {
base::TimeDelta staleness = response.CacheControlStaleWhileRevalidate();
if (staleness.is_zero())
@@ -1083,15 +1081,14 @@ bool Resource::ShouldRevalidateStaleResponse() const {
for (auto& redirect : redirect_chain_) {
// Use |response_timestamp_| since we don't store the timestamp
// of each redirect response.
- if (blink::ShouldRevalidateStaleResponse(redirect.request_,
- redirect.redirect_response_,
+ if (blink::ShouldRevalidateStaleResponse(redirect.redirect_response_,
response_timestamp_)) {
return true;
}
}
- return blink::ShouldRevalidateStaleResponse(
- GetResourceRequest(), GetResponse(), response_timestamp_);
+ return blink::ShouldRevalidateStaleResponse(GetResponse(),
+ response_timestamp_);
}
bool Resource::StaleRevalidationRequested() const {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
index 9b83d433ec0..4dc121198b8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -157,7 +157,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
~Resource() override;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
virtual WTF::TextEncoding Encoding() const { return WTF::TextEncoding(); }
virtual void AppendData(const char*, size_t);
@@ -176,13 +176,13 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
virtual bool ShouldIgnoreHTTPStatusCodeErrors() const { return false; }
- const ResourceRequest& GetResourceRequest() const {
+ const ResourceRequestHead& GetResourceRequest() const {
return resource_request_;
}
- const ResourceRequest& LastResourceRequest() const;
+ const ResourceRequestHead& LastResourceRequest() const;
const ResourceResponse* LastResourceResponse() const;
- virtual void SetRevalidatingRequest(const ResourceRequest&);
+ virtual void SetRevalidatingRequest(const ResourceRequestHead&);
// This url can have a fragment, but it can match resources that differ by the
// fragment only.
@@ -374,13 +374,6 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
// be triggered right away in ResourceLoader.
virtual void WillReloadAfterDiskCacheMiss() {}
- // TODO(shaochuan): This is for saving back the actual ResourceRequest sent
- // in ResourceFetcher::StartLoad() for retry in cache-aware loading, remove
- // once ResourceRequest is not modified in StartLoad(). crbug.com/632580
- void SetResourceRequest(const ResourceRequest& resource_request) {
- resource_request_ = resource_request;
- }
-
// Used by the MemoryCache to reduce the memory consumption of the entry.
void Prune();
@@ -426,8 +419,14 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
// The caller owns the |clock| which must outlive the Resource.
static void SetClockForTesting(const base::Clock* clock);
+ size_t CalculateOverheadSizeForTest() const {
+ return CalculateOverheadSize();
+ }
+
protected:
- Resource(const ResourceRequest&, ResourceType, const ResourceLoaderOptions&);
+ Resource(const ResourceRequestHead&,
+ ResourceType,
+ const ResourceLoaderOptions&);
// Returns true if the resource has finished any processing it wanted to do
// after loading. Should only be used to decide whether to call
@@ -473,11 +472,11 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
DISALLOW_NEW();
public:
- explicit RedirectPair(const ResourceRequest& request,
+ explicit RedirectPair(const ResourceRequestHead& request,
const ResourceResponse& redirect_response)
: request_(request), redirect_response_(redirect_response) {}
- ResourceRequest request_;
+ ResourceRequestHead request_;
ResourceResponse redirect_response_;
};
const Vector<RedirectPair>& RedirectChain() const { return redirect_chain_; }
@@ -566,7 +565,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
TaskHandle async_finish_pending_clients_task_;
- ResourceRequest resource_request_;
+ ResourceRequestHead resource_request_;
// Resource::CalculateOverheadSize() is affected by changes in
// |m_resourceRequest.url()|, but |m_overheadSize| is not updated after
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h
index dced85b7646..a4ea28e5e0f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h
@@ -64,6 +64,9 @@ class PLATFORM_EXPORT ResourceClient : public GarbageCollectedMixin {
Resource* GetResource() const { return resource_; }
+ bool FinishedFromMemoryCache() const { return finished_from_memory_cache_; }
+ void SetHasFinishedFromMemoryCache() { finished_from_memory_cache_ = true; }
+
// Name for debugging, e.g. shown in memory-infra.
virtual String DebugName() const = 0;
@@ -86,6 +89,10 @@ class PLATFORM_EXPORT ResourceClient : public GarbageCollectedMixin {
base::SingleThreadTaskRunner* task_runner);
Member<Resource> resource_;
+
+ // If true, the Resource was already available from the memory cache when this
+ // ResourceClient was setup, so that the request finished immediately.
+ bool finished_from_memory_cache_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
index 8451bf18965..a6706847ef4 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -96,10 +96,12 @@ ResourceError::ResourceError(const KURL& url,
ResourceError::ResourceError(const WebURLError& error)
: error_code_(error.reason()),
extended_error_code_(error.extended_reason()),
+ resolve_error_info_(error.resolve_error_info()),
failing_url_(error.url()),
is_access_check_(error.is_web_security_violation()),
has_copy_in_cache_(error.has_copy_in_cache()),
- cors_error_status_(error.cors_error_status()) {
+ cors_error_status_(error.cors_error_status()),
+ blocked_by_response_reason_(error.blocked_by_response_reason()) {
DCHECK_NE(error_code_, 0);
InitializeDescription();
}
@@ -108,6 +110,7 @@ ResourceError ResourceError::Copy() const {
ResourceError error_copy(error_code_, failing_url_.Copy(),
cors_error_status_);
error_copy.extended_error_code_ = extended_error_code_;
+ error_copy.resolve_error_info_ = resolve_error_info_;
error_copy.has_copy_in_cache_ = has_copy_in_cache_;
error_copy.localized_description_ = localized_description_.IsolatedCopy();
error_copy.is_access_check_ = is_access_check_;
@@ -124,11 +127,11 @@ ResourceError::operator WebURLError() const {
return WebURLError(*cors_error_status_, has_copy_in_cache, failing_url_);
}
- return WebURLError(error_code_, extended_error_code_, has_copy_in_cache,
- is_access_check_
- ? WebURLError::IsWebSecurityViolation::kTrue
- : WebURLError::IsWebSecurityViolation::kFalse,
- failing_url_);
+ return WebURLError(
+ error_code_, extended_error_code_, resolve_error_info_, has_copy_in_cache,
+ is_access_check_ ? WebURLError::IsWebSecurityViolation::kTrue
+ : WebURLError::IsWebSecurityViolation::kFalse,
+ failing_url_);
}
bool ResourceError::Compare(const ResourceError& a, const ResourceError& b) {
@@ -153,6 +156,9 @@ bool ResourceError::Compare(const ResourceError& a, const ResourceError& b) {
if (a.extended_error_code_ != b.extended_error_code_)
return false;
+ if (a.resolve_error_info_ != b.resolve_error_info_)
+ return false;
+
return true;
}
@@ -178,12 +184,45 @@ bool ResourceError::ShouldCollapseInitiator() const {
ResourceRequestBlockedReason::kCollapsedByClient;
}
+namespace {
+
+blink::ResourceRequestBlockedReason
+BlockedByResponseReasonToResourceRequestBlockedReason(
+ network::BlockedByResponseReason reason) {
+ switch (reason) {
+ case network::BlockedByResponseReason::kCoepFrameResourceNeedsCoepHeader:
+ return blink::ResourceRequestBlockedReason::
+ kCoepFrameResourceNeedsCoepHeader;
+ case network::BlockedByResponseReason::
+ kCoopSandboxedIFrameCannotNavigateToCoopPage:
+ return blink::ResourceRequestBlockedReason::
+ kCoopSandboxedIFrameCannotNavigateToCoopPage;
+ case network::BlockedByResponseReason::kCorpNotSameOrigin:
+ return blink::ResourceRequestBlockedReason::kCorpNotSameOrigin;
+ case network::BlockedByResponseReason::
+ kCorpNotSameOriginAfterDefaultedToSameOriginByCoep:
+ return blink::ResourceRequestBlockedReason::
+ kCorpNotSameOriginAfterDefaultedToSameOriginByCoep;
+ break;
+ case network::BlockedByResponseReason::kCorpNotSameSite:
+ return blink::ResourceRequestBlockedReason::kCorpNotSameSite;
+ break;
+ }
+ NOTREACHED();
+ return blink::ResourceRequestBlockedReason::kOther;
+}
+
+} // namespace
base::Optional<ResourceRequestBlockedReason>
ResourceError::GetResourceRequestBlockedReason() const {
if (error_code_ != net::ERR_BLOCKED_BY_CLIENT &&
error_code_ != net::ERR_BLOCKED_BY_RESPONSE) {
return base::nullopt;
}
+ if (blocked_by_response_reason_) {
+ return BlockedByResponseReasonToResourceRequestBlockedReason(
+ *blocked_by_response_reason_);
+ }
return static_cast<ResourceRequestBlockedReason>(extended_error_code_);
}
@@ -217,6 +256,23 @@ String DescriptionForBlockedByClientOrResponse(int error, int extended_error) {
case ResourceRequestBlockedReason::kCollapsedByClient:
detail = "Collapsed";
break;
+ case ResourceRequestBlockedReason::kCoepFrameResourceNeedsCoepHeader:
+ detail = "ResponseNeedsCrossOriginEmbedderPolicy";
+ break;
+ case ResourceRequestBlockedReason::
+ kCoopSandboxedIFrameCannotNavigateToCoopPage:
+ detail = "SandboxedIFrameCannotNavigateToOriginIsolatedPage";
+ break;
+ case ResourceRequestBlockedReason::kCorpNotSameOrigin:
+ detail = "NotSameOrigin";
+ break;
+ case ResourceRequestBlockedReason::
+ kCorpNotSameOriginAfterDefaultedToSameOriginByCoep:
+ detail = "NotSameOriginAfterDefaultedToSameOriginByCoep";
+ break;
+ case ResourceRequestBlockedReason::kCorpNotSameSite:
+ detail = "NotSameSite";
+ break;
}
return WebString::FromASCII(net::ErrorToString(error) + "." + detail);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
index 592174eae92..19c60919c24 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
@@ -29,6 +29,8 @@
#include <iosfwd>
#include "base/optional.h"
+#include "net/dns/public/resolve_error_info.h"
+#include "services/network/public/cpp/blocked_by_response_reason.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -99,12 +101,15 @@ class PLATFORM_EXPORT ResourceError final {
int error_code_;
int extended_error_code_ = 0;
+ net::ResolveErrorInfo resolve_error_info_;
KURL failing_url_;
String localized_description_;
bool is_access_check_ = false;
bool has_copy_in_cache_ = false;
bool blocked_by_subresource_filter_ = false;
base::Optional<network::CorsErrorStatus> cors_error_status_;
+
+ base::Optional<network::BlockedByResponseReason> blocked_by_response_reason_;
};
inline bool operator==(const ResourceError& a, const ResourceError& b) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index d55eaa3ac98..04ed5036553 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -34,15 +34,15 @@
#include "base/auto_reset.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "services/network/public/cpp/request_mode.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/loader/request_destination.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -78,10 +78,10 @@
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/known_ports.h"
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
+#include "third_party/blink/renderer/platform/weborigin/reporting_disposition.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
-#include "third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -98,13 +98,12 @@ namespace {
constexpr base::TimeDelta kKeepaliveLoadersTimeout =
base::TimeDelta::FromSeconds(30);
-#define DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, name) \
- case ResourceType::k##name: { \
- DEFINE_THREAD_SAFE_STATIC_LOCAL( \
- EnumerationHistogram, _single_resource_histogram, \
- ("Blink.MemoryCache.RevalidationPolicy." prefix #name, kLoad + 1)); \
- _single_resource_histogram.Count(policy); \
- break; \
+#define RESOURCE_HISTOGRAM_PREFIX "Blink.MemoryCache.RevalidationPolicy."
+
+#define DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, name) \
+ case ResourceType::k##name: { \
+ UMA_HISTOGRAM_ENUMERATION(RESOURCE_HISTOGRAM_PREFIX prefix #name, policy); \
+ break; \
}
#define DEFINE_RESOURCE_HISTOGRAM(prefix) \
@@ -159,24 +158,12 @@ ResourceLoadPriority TypeToPriority(ResourceType type) {
return ResourceLoadPriority::kUnresolved;
}
-static bool IsCacheableHTTPMethod(const AtomicString& method) {
- // Per http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.10,
- // these methods always invalidate the cache entry.
- return method != http_names::kPOST && method != http_names::kPUT &&
- method != "DELETE";
-}
-
bool ShouldResourceBeAddedToMemoryCache(const FetchParameters& params,
Resource* resource) {
- if (!IsMainThread())
- return false;
- if (params.Options().data_buffering_policy == kDoNotBufferData)
- return false;
- if (IsRawResource(*resource))
- return false;
- if (!IsCacheableHTTPMethod(params.GetResourceRequest().HttpMethod()))
- return false;
- return true;
+ return IsMainThread() &&
+ params.GetResourceRequest().HttpMethod() == http_names::kGET &&
+ params.Options().data_buffering_policy != kDoNotBufferData &&
+ !IsRawResource(*resource);
}
static ResourceFetcher::ResourceFetcherSet& MainThreadFetchersSet() {
@@ -204,7 +191,7 @@ static ThreadSpecific<PriorityObserverMap>& PriorityObservers() {
ResourceLoadPriority AdjustPriorityWithPriorityHint(
ResourceLoadPriority priority_so_far,
ResourceType type,
- const ResourceRequest& resource_request,
+ const ResourceRequestHead& resource_request,
FetchParameters::DeferOption defer_option,
bool is_link_preload) {
mojom::FetchImportanceMode importance_mode =
@@ -254,7 +241,7 @@ ResourceLoadPriority AdjustPriorityWithDeferScriptIntervention(
const FetchContext& fetch_context,
ResourceLoadPriority priority_so_far,
ResourceType type,
- const ResourceRequest& resource_request,
+ const ResourceRequestHead& resource_request,
FetchParameters::DeferOption defer_option,
bool is_link_preload) {
if (!base::FeatureList::IsEnabled(
@@ -307,65 +294,20 @@ std::unique_ptr<TracedValue> ResourcePrioritySetData(
void SetReferrer(
ResourceRequest& request,
const FetchClientSettingsObject& fetch_client_settings_object) {
- if (!request.DidSetHttpReferrer()) {
- String referrer_to_use = request.ReferrerString();
- network::mojom::ReferrerPolicy referrer_policy_to_use =
- request.GetReferrerPolicy();
-
- if (referrer_to_use == Referrer::ClientReferrerString())
- referrer_to_use = fetch_client_settings_object.GetOutgoingReferrer();
-
- if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault)
- referrer_policy_to_use = fetch_client_settings_object.GetReferrerPolicy();
-
- request.SetReferrerString(referrer_to_use);
- request.SetReferrerPolicy(referrer_policy_to_use);
- // TODO(domfarolino): Stop storing ResourceRequest's referrer as a header
- // and store it elsewhere. See https://crbug.com/850813.
- request.SetHttpReferrer(SecurityPolicy::GenerateReferrer(
- referrer_policy_to_use, request.Url(), referrer_to_use));
- } else {
- // In the case of stale requests that are being revalidated, these requests
- // will already have their HttpReferrer set, and we will end up here. We
- // won't regenerate the referrer, but instead check that it's still correct.
- CHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(),
- request.Url(),
- request.ReferrerString())
- .referrer,
- request.HttpReferrer());
- }
-}
+ String referrer_to_use = request.ReferrerString();
+ network::mojom::ReferrerPolicy referrer_policy_to_use =
+ request.GetReferrerPolicy();
-void SetSecFetchHeaders(
- ResourceRequest& request,
- const FetchClientSettingsObject& fetch_client_settings_object) {
- scoped_refptr<SecurityOrigin> url_origin =
- SecurityOrigin::Create(request.Url());
- if (blink::RuntimeEnabledFeatures::FetchMetadataEnabled() &&
- url_origin->IsPotentiallyTrustworthy()) {
- const char* destination_value =
- GetRequestDestinationFromContext(request.GetRequestContext());
-
- // If the request's destination is the empty string (e.g. `fetch()`), then
- // we'll use the identifier "empty" instead.
- if (strlen(destination_value) == 0)
- destination_value = "empty";
-
- // We'll handle adding these headers to navigations outside of Blink.
- if ((strncmp(destination_value, "document", 8) != 0 ||
- strncmp(destination_value, "iframe", 6) != 0 ||
- strncmp(destination_value, "frame", 5) != 0) &&
- request.GetRequestContext() != mojom::RequestContextType::INTERNAL) {
- if (blink::RuntimeEnabledFeatures::FetchMetadataDestinationEnabled()) {
- request.SetHttpHeaderField("Sec-Fetch-Dest", destination_value);
- }
+ if (referrer_to_use == Referrer::ClientReferrerString())
+ referrer_to_use = fetch_client_settings_object.GetOutgoingReferrer();
- // Note that the `Sec-Fetch-User` header is always false (and therefore
- // omitted) for subresource requests. Likewise, note that we rely on
- // Blink's embedder to set `Sec-Fetch-Site`, as we don't want to trust the
- // renderer to assert its own origin. Ditto for `Sec-Fetch-Mode`.
- }
- }
+ if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault)
+ referrer_policy_to_use = fetch_client_settings_object.GetReferrerPolicy();
+
+ Referrer generated_referrer = SecurityPolicy::GenerateReferrer(
+ referrer_policy_to_use, request.Url(), referrer_to_use);
+ request.SetReferrerString(generated_referrer.referrer);
+ request.SetReferrerPolicy(generated_referrer.referrer_policy);
}
} // namespace
@@ -375,7 +317,7 @@ ResourceFetcherInit::ResourceFetcherInit(
FetchContext* context,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
ResourceFetcher::LoaderFactory* loader_factory)
- : properties(properties),
+ : properties(&properties),
context(context),
task_runner(std::move(task_runner)),
loader_factory(loader_factory) {
@@ -426,6 +368,40 @@ mojom::RequestContextType ResourceFetcher::DetermineRequestContext(
return mojom::RequestContextType::SUBRESOURCE;
}
+network::mojom::RequestDestination ResourceFetcher::DetermineRequestDestination(
+ ResourceType type) {
+ switch (type) {
+ case ResourceType::kXSLStyleSheet:
+ DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
+ FALLTHROUGH;
+ case ResourceType::kCSSStyleSheet:
+ return network::mojom::RequestDestination::kStyle;
+ case ResourceType::kScript:
+ return network::mojom::RequestDestination::kScript;
+ case ResourceType::kFont:
+ return network::mojom::RequestDestination::kFont;
+ case ResourceType::kImage:
+ return network::mojom::RequestDestination::kImage;
+ case ResourceType::kTextTrack:
+ return network::mojom::RequestDestination::kTrack;
+ case ResourceType::kSVGDocument:
+ return network::mojom::RequestDestination::kImage;
+ case ResourceType::kAudio:
+ return network::mojom::RequestDestination::kAudio;
+ case ResourceType::kVideo:
+ return network::mojom::RequestDestination::kVideo;
+ case ResourceType::kManifest:
+ return network::mojom::RequestDestination::kManifest;
+ case ResourceType::kRaw:
+ case ResourceType::kImportResource:
+ case ResourceType::kLinkPrefetch:
+ case ResourceType::kMock:
+ return network::mojom::RequestDestination::kEmpty;
+ }
+ NOTREACHED();
+ return network::mojom::RequestDestination::kEmpty;
+}
+
// static
void ResourceFetcher::AddPriorityObserverForTesting(
const KURL& resource_url,
@@ -441,7 +417,7 @@ void ResourceFetcher::AddPriorityObserverForTesting(
// images, which may need to be reprioritized.
ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
ResourceType type,
- const ResourceRequest& resource_request,
+ const ResourceRequestHead& resource_request,
ResourcePriority::VisibilityStatus visibility,
FetchParameters::DeferOption defer_option,
FetchParameters::SpeculativePreloadType speculative_preload_type,
@@ -524,17 +500,13 @@ ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
if (properties_->IsSubframeDeprioritizationEnabled()) {
if (properties_->IsMainFrame()) {
- DEFINE_STATIC_LOCAL(
- EnumerationHistogram, main_frame_priority_histogram,
- ("LowPriorityIframes.MainFrameRequestPriority",
- static_cast<int>(ResourceLoadPriority::kHighest) + 1));
- main_frame_priority_histogram.Count(static_cast<int>(priority));
+ UMA_HISTOGRAM_ENUMERATION(
+ "LowPriorityIframes.MainFrameRequestPriority", priority,
+ static_cast<int>(ResourceLoadPriority::kHighest) + 1);
} else {
- DEFINE_STATIC_LOCAL(
- EnumerationHistogram, iframe_priority_histogram,
- ("LowPriorityIframes.IframeRequestPriority",
- static_cast<int>(ResourceLoadPriority::kHighest) + 1));
- iframe_priority_histogram.Count(static_cast<int>(priority));
+ UMA_HISTOGRAM_ENUMERATION(
+ "LowPriorityIframes.IframeRequestPriority", priority,
+ static_cast<int>(ResourceLoadPriority::kHighest) + 1);
// When enabled, the priority of all resources in subframe is dropped.
// Non-delayable resources are assigned a priority of kLow, and the rest
// of them are assigned a priority of kLowest. This ensures that if the
@@ -556,10 +528,10 @@ ResourceFetcher::ResourceFetcher(const ResourceFetcherInit& init)
context_(init.context),
task_runner_(init.task_runner),
use_counter_(init.use_counter
- ? init.use_counter.Get()
+ ? init.use_counter
: MakeGarbageCollected<DetachableUseCounter>(nullptr)),
console_logger_(init.console_logger
- ? init.console_logger.Get()
+ ? init.console_logger
: MakeGarbageCollected<DetachableConsoleLogger>()),
loader_factory_(init.loader_factory),
scheduler_(MakeGarbageCollected<ResourceLoadScheduler>(
@@ -622,7 +594,7 @@ bool ResourceFetcher::ResourceNeedsLoad(Resource* resource,
FetchParameters::kDeferImageLoad)) {
return false;
}
- return policy != kUse || resource->StillNeedsLoad();
+ return policy != RevalidationPolicy::kUse || resource->StillNeedsLoad();
}
void ResourceFetcher::DidLoadResourceFromMemoryCache(
@@ -653,7 +625,7 @@ void ResourceFetcher::DidLoadResourceFromMemoryCache(
// they're used.
scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
resource->Options().initiator_info.name, base::TimeTicks::Now(),
- request.GetRequestContext());
+ request.GetRequestContext(), request.GetRequestDestination());
// TODO(yoav): GetInitialUrlForResourceTiming() is only needed until
// Out-of-Blink CORS lands: https://crbug.com/736308
info->SetInitialURL(
@@ -772,11 +744,6 @@ void ResourceFetcher::UpdateMemoryCacheStats(Resource* resource,
if (is_static_data)
return;
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- BooleanHistogram, resource_histogram,
- ("Blink.ResourceFetcher.StaleWhileRevalidate"));
- resource_histogram.Count(params.IsStaleRevalidation());
-
if (params.IsSpeculativePreload() || params.IsLinkPreload()) {
DEFINE_RESOURCE_HISTOGRAM("Preload.");
} else {
@@ -790,6 +757,13 @@ void ResourceFetcher::UpdateMemoryCacheStats(Resource* resource,
if (resource && !resource->IsAlive() && !ContainsAsPreload(resource)) {
DEFINE_RESOURCE_HISTOGRAM("Dead.");
}
+
+ // Async (and defer) scripts may have more cache misses, track them
+ // separately. See https://crbug.com/1043679 for context.
+ if (params.Defer() != FetchParameters::DeferOption::kNoDefer &&
+ factory.GetType() == ResourceType::kScript) {
+ UMA_HISTOGRAM_ENUMERATION(RESOURCE_HISTOGRAM_PREFIX "AsyncScript", policy);
+ }
}
bool ResourceFetcher::ContainsAsPreload(Resource* resource) const {
@@ -821,10 +795,9 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
params.OverrideContentType(factory.ContentType());
// Don't send security violation reports for speculative preloads.
- SecurityViolationReportingPolicy reporting_policy =
- params.IsSpeculativePreload()
- ? SecurityViolationReportingPolicy::kSuppressReporting
- : SecurityViolationReportingPolicy::kReport;
+ ReportingDisposition reporting_disposition =
+ params.IsSpeculativePreload() ? ReportingDisposition::kSuppressReporting
+ : ReportingDisposition::kReport;
// Note that resource_request.GetRedirectStatus() may return kFollowedRedirect
// here since e.g. ThreadableLoader may create a new Resource from
@@ -837,7 +810,7 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
Context().CheckCSPForRequest(
resource_request.GetRequestContext(),
MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), options,
- reporting_policy, resource_request.GetRedirectStatus());
+ reporting_disposition, resource_request.GetRedirectStatus());
// This may modify params.Url() (via the resource_request argument).
Context().PopulateResourceRequest(
@@ -868,6 +841,8 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
mojom::RequestContextType::UNSPECIFIED) {
resource_request.SetRequestContext(
DetermineRequestContext(resource_type, kImageNotImageSet));
+ resource_request.SetRequestDestination(
+ DetermineRequestDestination(resource_type));
}
if (resource_type == ResourceType::kLinkPrefetch)
resource_request.SetPurposeHeader("prefetch");
@@ -885,9 +860,6 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
resource_request.SetExternalRequestStateFromRequestorAddressSpace(
properties_->GetFetchClientSettingsObject().GetAddressSpace());
- SetSecFetchHeaders(resource_request,
- properties_->GetFetchClientSettingsObject());
-
Context().AddAdditionalRequestHeaders(resource_request);
TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
@@ -898,7 +870,7 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
KURL url = MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url());
base::Optional<ResourceRequestBlockedReason> blocked_reason =
Context().CanRequest(resource_type, resource_request, url, options,
- reporting_policy,
+ reporting_disposition,
resource_request.GetRedirectStatus());
if (Context().CalculateIfAdSubresource(resource_request, resource_type))
@@ -952,10 +924,6 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
if (should_log_request_as_invalid_in_imported_document_) {
DCHECK(properties_->IsDetached());
- // We don't expect the fetcher to be used, so count such unexpected use.
- UMA_HISTOGRAM_ENUMERATION("HTMLImport.UnexpectedRequest",
- factory.GetType());
-
base::debug::DumpWithoutCrashing();
}
@@ -1012,7 +980,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
}
Resource* resource = nullptr;
- RevalidationPolicy policy = kLoad;
+ RevalidationPolicy policy = RevalidationPolicy::kLoad;
bool is_data_url = resource_request.Url().ProtocolIsData();
bool is_static_data = is_data_url || archive_;
@@ -1035,7 +1003,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
if (!is_stale_revalidation && !resource) {
resource = MatchPreload(params, resource_type);
if (resource) {
- policy = kUse;
+ policy = RevalidationPolicy::kUse;
// If |params| is for a blocking resource and a preloaded resource is
// found, we may need to make it block the onload event.
MakePreloadedResourceBlockOnloadIfNeeded(resource, params);
@@ -1052,16 +1020,16 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
UpdateMemoryCacheStats(resource, policy, params, factory, is_static_data);
switch (policy) {
- case kReload:
+ case RevalidationPolicy::kReload:
GetMemoryCache()->Remove(resource);
FALLTHROUGH;
- case kLoad:
+ case RevalidationPolicy::kLoad:
resource = CreateResourceForLoading(params, factory);
break;
- case kRevalidate:
+ case RevalidationPolicy::kRevalidate:
InitializeRevalidation(resource_request, resource);
break;
- case kUse:
+ case RevalidationPolicy::kUse:
if (resource_request.AllowsStaleResponse() &&
resource->ShouldRevalidateStaleResponse()) {
ScheduleStaleRevalidate(resource);
@@ -1072,7 +1040,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
DCHECK(resource);
DCHECK_EQ(resource->GetType(), resource_type);
- if (policy != kUse)
+ if (policy != RevalidationPolicy::kUse)
resource->VirtualTimePauser() = std::move(pauser);
if (client)
@@ -1080,7 +1048,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
// TODO(yoav): It is not clear why preloads are exempt from this check. Can we
// remove the exemption?
- if (!params.IsSpeculativePreload() || policy != kUse) {
+ if (!params.IsSpeculativePreload() || policy != RevalidationPolicy::kUse) {
// When issuing another request for a resource that is already in-flight
// make sure to not demote the priority of the in-flight request. If the new
// request isn't at the same priority as the in-flight request, only allow
@@ -1095,7 +1063,8 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
// If only the fragment identifiers differ, it is the same resource.
DCHECK(EqualIgnoringFragmentIdentifier(resource->Url(), params.Url()));
- if (policy == kUse && resource->GetStatus() == ResourceStatus::kCached &&
+ if (policy == RevalidationPolicy::kUse &&
+ resource->GetStatus() == ResourceStatus::kCached &&
!cached_resources_map_.Contains(
MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()))) {
// Loaded from MemoryCache.
@@ -1124,13 +1093,14 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
// the resource was already initialized for the revalidation here, but won't
// start loading.
if (ResourceNeedsLoad(resource, params, policy)) {
- if (!StartLoad(resource)) {
+ if (!StartLoad(resource,
+ std::move(params.MutableResourceRequest().MutableBody()))) {
resource->FinishAsError(ResourceError::CancelledError(params.Url()),
task_runner_.get());
}
}
- if (policy != kUse)
+ if (policy != RevalidationPolicy::kUse)
InsertAsPreloadIfNecessary(resource, params, resource_type);
if (resource->InspectorId() != identifier ||
@@ -1240,7 +1210,8 @@ void ResourceFetcher::StorePerformanceTimingInitiatorInformation(
scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
fetch_initiator, base::TimeTicks::Now(),
- resource->GetResourceRequest().GetRequestContext());
+ resource->GetResourceRequest().GetRequestContext(),
+ resource->GetResourceRequest().GetRequestDestination());
resource_timing_info_map_.insert(resource, std::move(info));
}
@@ -1430,13 +1401,13 @@ ResourceFetcher::DetermineRevalidationPolicy(
const char* ResourceFetcher::GetNameFor(RevalidationPolicy policy) {
switch (policy) {
- case kUse:
+ case RevalidationPolicy::kUse:
return "use";
- case kRevalidate:
+ case RevalidationPolicy::kRevalidate:
return "revalidate";
- case kReload:
+ case RevalidationPolicy::kReload:
return "reload";
- case kLoad:
+ case RevalidationPolicy::kLoad:
return "load";
}
NOTREACHED();
@@ -1451,11 +1422,13 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
const ResourceRequest& request = fetch_params.GetResourceRequest();
if (IsDownloadOrStreamRequest(request)) {
- return std::make_pair(kReload, "It is for download or for streaming.");
+ return {RevalidationPolicy::kReload,
+ "It is for download or for streaming."};
}
if (IsImageResourceDisallowedToBeReused(existing_resource)) {
- return std::make_pair(kReload, "Reload due to 'allow image' settings.");
+ return {RevalidationPolicy::kReload,
+ "Reload due to 'allow image' settings."};
}
// If the existing resource is loading and the associated fetcher is not equal
@@ -1463,8 +1436,8 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// happen in redirect handling.
if (existing_resource.Loader() &&
existing_resource.Loader()->Fetcher() != this) {
- return std::make_pair(
- kReload, "The existing resource is loading in a foreign fetcher.");
+ return {RevalidationPolicy::kReload,
+ "The existing resource is loading in a foreign fetcher."};
}
// It's hard to share a not-yet-referenced preloads via MemoryCache correctly.
@@ -1472,9 +1445,9 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// the memory cache could be used without this block.
if ((fetch_params.IsLinkPreload() || fetch_params.IsSpeculativePreload()) &&
existing_resource.IsUnusedPreload()) {
- return std::make_pair(kReload,
- "The existing resource is an unused preload made "
- "from a foreign fetcher.");
+ return {RevalidationPolicy::kReload,
+ "The existing resource is an unused preload made "
+ "from a foreign fetcher."};
}
// Checks if the resource has an explicit policy about integrity metadata.
@@ -1493,7 +1466,7 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// uncommon case, however, as it implies two same-origin requests to the same
// resource, but with different integrity metadata.
if (existing_resource.MustRefetchDueToIntegrityMetadata(fetch_params)) {
- return std::make_pair(kReload, "Reload due to resource integrity.");
+ return {RevalidationPolicy::kReload, "Reload due to resource integrity."};
}
// If the same URL has been loaded as a different type, we need to reload.
@@ -1502,35 +1475,36 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// We really should discard the new prefetch since the preload has more
// specific type information! crbug.com/379893
// fast/dom/HTMLLinkElement/link-and-subresource-test hits this case.
- return std::make_pair(kReload, "Reload due to type mismatch.");
+ return {RevalidationPolicy::kReload, "Reload due to type mismatch."};
}
// If resource was populated from archive or data: url, use it.
// This doesn't necessarily mean that |resource| was just created by using
// ResourceForStaticData().
if (is_static_data) {
- return std::make_pair(kUse, "Use the existing static resource.");
+ return {RevalidationPolicy::kUse, "Use the existing static resource."};
}
if (existing_resource.CanReuse(fetch_params) != Resource::MatchStatus::kOk) {
- return std::make_pair(kReload, "Reload due to Resource::CanReuse.");
+ return {RevalidationPolicy::kReload, "Reload due to Resource::CanReuse."};
}
// Don't reload resources while pasting.
if (allow_stale_resources_) {
- return std::make_pair(
- kUse, "Use the existing resource due to |allow_stale_resources_|.");
+ return {RevalidationPolicy::kUse,
+ "Use the existing resource due to |allow_stale_resources_|."};
}
// FORCE_CACHE uses the cache no matter what.
if (request.GetCacheMode() == mojom::FetchCacheMode::kForceCache) {
- return std::make_pair(
- kUse, "Use the existing resource due to cache-mode: 'force-cache'.");
+ return {RevalidationPolicy::kUse,
+ "Use the existing resource due to cache-mode: 'force-cache'."};
}
// Don't reuse resources with Cache-control: no-store.
if (existing_resource.HasCacheControlNoStoreHeader()) {
- return std::make_pair(kReload, "Reload due to cache-control: no-sotre.");
+ return {RevalidationPolicy::kReload,
+ "Reload due to cache-control: no-sotre."};
}
// During the initial load, avoid loading the same resource multiple times for
@@ -1543,25 +1517,25 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
cached_resources_map_.Contains(
MemoryCache::RemoveFragmentIdentifierIfNeeded(
existing_resource.Url()))) {
- return std::make_pair(kUse,
- "Avoid making multiple requests for the same URL "
- "during the initial load.");
+ return {RevalidationPolicy::kUse,
+ "Avoid making multiple requests for the same URL "
+ "during the initial load."};
}
if (existing_resource.IsLoading()) {
- return std::make_pair(
- kUse, "Use the existing resource because it's being loaded.");
+ return {RevalidationPolicy::kUse,
+ "Use the existing resource because it's being loaded."};
}
}
// RELOAD always reloads
if (request.GetCacheMode() == mojom::FetchCacheMode::kBypassCache) {
- return std::make_pair(kReload, "Reload due to cache-mode: 'reload'.");
+ return {RevalidationPolicy::kReload, "Reload due to cache-mode: 'reload'."};
}
// We'll try to reload the resource if it failed last time.
if (existing_resource.ErrorOccurred()) {
- return std::make_pair(
- kReload, "Reload because the existing resource has failed loading.");
+ return {RevalidationPolicy::kReload,
+ "Reload because the existing resource has failed loading."};
}
// List of available images logic allows images to be re-used without cache
@@ -1569,18 +1543,19 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// same as the version in the current document.
if (type == ResourceType::kImage &&
&existing_resource == CachedResource(request.Url())) {
- return std::make_pair(kUse,
- "Images can be reused without cache validation.");
+ return {RevalidationPolicy::kUse,
+ "Images can be reused without cache validation."};
}
if (existing_resource.MustReloadDueToVaryHeader(request)) {
- return std::make_pair(kReload, "Reload due to vary header.");
+ return {RevalidationPolicy::kReload, "Reload due to vary header."};
}
// If any of the redirects in the chain to loading the resource were not
// cacheable, we cannot reuse our cached resource.
if (!existing_resource.CanReuseRedirectChain()) {
- return std::make_pair(kReload, "Reload due to an uncacheable redirect.");
+ return {RevalidationPolicy::kReload,
+ "Reload due to an uncacheable redirect."};
}
// Check if the cache headers requires us to revalidate (cache expiration for
@@ -1592,8 +1567,8 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// Revalidation is harmful for non-matched preloads because it may lead to
// sharing one preloaded resource among multiple ResourceFetchers.
if (existing_resource.IsUnusedPreload()) {
- return std::make_pair(
- kReload, "Revalidation is harmful for non-matched preloads.");
+ return {RevalidationPolicy::kReload,
+ "Revalidation is harmful for non-matched preloads."};
}
// See if the resource has usable ETag or Last-modified headers. If the page
@@ -1612,20 +1587,19 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// |Use| policy should be applied to subsequent requests.
if (existing_resource.IsCacheValidator()) {
DCHECK(existing_resource.StillNeedsLoad());
- return std::make_pair(
- kUse,
- "Merged to the revalidate request which has not yet started.");
+ return {RevalidationPolicy::kUse,
+ "Merged to the revalidate request which has not yet started."};
}
- return std::make_pair(kRevalidate, "");
+ return {RevalidationPolicy::kRevalidate, ""};
}
// No, must reload.
- return std::make_pair(kReload, "Reload due to missing cache validators.");
+ return {RevalidationPolicy::kReload,
+ "Reload due to missing cache validators."};
}
- return std::make_pair(
- kUse,
- "Use the existing resource because there is no reason not to do so.");
+ return {RevalidationPolicy::kUse,
+ "Use the existing resource because there is no reason not to do so."};
}
void ResourceFetcher::SetAutoLoadImages(bool enable) {
@@ -1877,6 +1851,11 @@ void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) {
}
bool ResourceFetcher::StartLoad(Resource* resource) {
+ return StartLoad(resource, ResourceRequestBody());
+}
+
+bool ResourceFetcher::StartLoad(Resource* resource,
+ ResourceRequestBody request_body) {
DCHECK(resource);
DCHECK(resource->StillNeedsLoad());
@@ -1894,11 +1873,13 @@ bool ResourceFetcher::StartLoad(Resource* resource) {
return false;
}
- const auto& request = resource->GetResourceRequest();
- ResourceResponse response;
+ const ResourceRequestHead& request_head = resource->GetResourceRequest();
if (resource_load_observer_) {
DCHECK(!IsDetached());
+ ResourceRequest request(request_head);
+ request.SetHttpBody(request_body.FormBody());
+ ResourceResponse response;
resource_load_observer_->WillSendRequest(
resource->InspectorId(), request, response, resource->GetType(),
resource->Options().initiator_info);
@@ -1906,8 +1887,8 @@ bool ResourceFetcher::StartLoad(Resource* resource) {
using QuotaType = decltype(inflight_keepalive_bytes_);
QuotaType size = 0;
- if (request.GetKeepalive() && request.HttpBody()) {
- auto original_size = request.HttpBody()->SizeInBytes();
+ if (request_head.GetKeepalive() && request_body.FormBody()) {
+ auto original_size = request_body.FormBody()->SizeInBytes();
DCHECK_LE(inflight_keepalive_bytes_, kKeepaliveInflightBytesQuota);
if (original_size > std::numeric_limits<QuotaType>::max())
return false;
@@ -1918,8 +1899,8 @@ bool ResourceFetcher::StartLoad(Resource* resource) {
inflight_keepalive_bytes_ += size;
}
- loader =
- MakeGarbageCollected<ResourceLoader>(this, scheduler_, resource, size);
+ loader = MakeGarbageCollected<ResourceLoader>(
+ this, scheduler_, resource, std::move(request_body), size);
// Preload requests should not block the load event. IsLinkPreload()
// actually continues to return true for Resources matched from the preload
// cache that must block the load event, but that is OK because this method
@@ -2037,12 +2018,14 @@ void ResourceFetcher::EmulateLoadStartedForInspector(
Resource* resource,
const KURL& url,
mojom::RequestContextType request_context,
+ network::mojom::RequestDestination request_destination,
const AtomicString& initiator_name) {
base::AutoReset<bool> r(&is_in_request_resource_, true);
if (CachedResource(url))
return;
ResourceRequest resource_request(url);
resource_request.SetRequestContext(request_context);
+ resource_request.SetRequestDestination(request_destination);
if (!resource_request.PriorityHasBeenSet()) {
resource_request.SetPriority(ComputeLoadPriority(
resource->GetType(), resource_request, ResourcePriority::kNotVisible,
@@ -2050,14 +2033,17 @@ void ResourceFetcher::EmulateLoadStartedForInspector(
FetchParameters::SpeculativePreloadType::kNotSpeculative,
false /* is_link_preload */));
}
+ resource_request.SetReferrerString(Referrer::NoReferrer());
+ resource_request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
ResourceLoaderOptions options = resource->Options();
options.initiator_info.name = initiator_name;
- FetchParameters params(resource_request, options);
- Context().CanRequest(resource->GetType(), resource->LastResourceRequest(),
- resource->LastResourceRequest().Url(), params.Options(),
- SecurityViolationReportingPolicy::kReport,
- resource->LastResourceRequest().GetRedirectStatus());
+ FetchParameters params(std::move(resource_request), options);
+ ResourceRequest last_resource_request(resource->LastResourceRequest());
+ Context().CanRequest(resource->GetType(), last_resource_request,
+ last_resource_request.Url(), params.Options(),
+ ReportingDisposition::kReport,
+ last_resource_request.GetRedirectStatus());
DidLoadResourceFromMemoryCache(resource->InspectorId(), resource,
params.GetResourceRequest(),
false /* is_static_data */);
@@ -2113,7 +2099,9 @@ void ResourceFetcher::RevalidateStaleResource(Resource* stale_resource) {
// purpose this is probably fine.
// TODO(dtapuska): revisit this when we have a better way to re-dispatch
// requests.
- FetchParameters params(stale_resource->GetResourceRequest());
+ ResourceRequest request;
+ request.CopyHeadFrom(stale_resource->GetResourceRequest());
+ FetchParameters params(std::move(request));
params.SetStaleRevalidation(true);
params.MutableResourceRequest().SetSkipServiceWorker(true);
// Stale revalidation resource requests should be very low regardless of
@@ -2126,7 +2114,7 @@ void ResourceFetcher::RevalidateStaleResource(Resource* stale_resource) {
mojom::blink::BlobRegistry* ResourceFetcher::GetBlobRegistry() {
if (!blob_registry_remote_) {
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
blob_registry_remote_.BindNewPipeAndPassReceiver(task_runner_));
}
return blob_registry_remote_.get();
@@ -2136,7 +2124,7 @@ FrameScheduler* ResourceFetcher::GetFrameScheduler() {
return frame_scheduler_.get();
}
-void ResourceFetcher::Trace(blink::Visitor* visitor) {
+void ResourceFetcher::Trace(Visitor* visitor) {
visitor->Trace(context_);
visitor->Trace(properties_);
visitor->Trace(resource_load_observer_);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 9c3ad282fc6..75ac2446bee 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -102,7 +102,7 @@ class PLATFORM_EXPORT ResourceFetcher
// in ResourceFetcherInit to ensure correctness of this ResourceFetcher.
explicit ResourceFetcher(const ResourceFetcherInit&);
virtual ~ResourceFetcher();
- virtual void Trace(blink::Visitor*);
+ virtual void Trace(Visitor*);
// - This function returns the same object throughout this fetcher's
// entire life.
@@ -168,6 +168,7 @@ class PLATFORM_EXPORT ResourceFetcher
// call this method explicitly on cases such as ResourceNeedsLoad() returning
// false.
bool StartLoad(Resource*);
+ bool StartLoad(Resource*, ResourceRequestBody);
void SetAutoLoadImages(bool);
void SetImagesEnabled(bool);
@@ -223,6 +224,9 @@ class PLATFORM_EXPORT ResourceFetcher
ResourceType,
IsImageSet);
+ static network::mojom::RequestDestination DetermineRequestDestination(
+ ResourceType);
+
void UpdateAllImageResourcePriorities();
// Returns whether the given resource is contained as a preloaded resource.
@@ -237,6 +241,7 @@ class PLATFORM_EXPORT ResourceFetcher
void EmulateLoadStartedForInspector(Resource*,
const KURL&,
mojom::RequestContextType,
+ network::mojom::RequestDestination,
const AtomicString& initiator_name);
// This is called from leak detectors (Real-world leak detector & web test
@@ -253,7 +258,7 @@ class PLATFORM_EXPORT ResourceFetcher
ResourceLoadPriority ComputeLoadPriorityForTesting(
ResourceType type,
- const ResourceRequest& request,
+ const ResourceRequestHead& request,
ResourcePriority::VisibilityStatus visibility_statue,
FetchParameters::DeferOption defer_option,
FetchParameters::SpeculativePreloadType speculative_preload_type,
@@ -284,7 +289,7 @@ class PLATFORM_EXPORT ResourceFetcher
void StorePerformanceTimingInitiatorInformation(Resource*);
ResourceLoadPriority ComputeLoadPriority(
ResourceType,
- const ResourceRequest&,
+ const ResourceRequestHead&,
ResourcePriority::VisibilityStatus,
FetchParameters::DeferOption = FetchParameters::kNoDefer,
FetchParameters::SpeculativePreloadType =
@@ -319,7 +324,13 @@ class PLATFORM_EXPORT ResourceFetcher
void StopFetchingIncludingKeepaliveLoaders();
// RevalidationPolicy enum values are used in UMAs https://crbug.com/579496.
- enum RevalidationPolicy { kUse, kRevalidate, kReload, kLoad };
+ enum class RevalidationPolicy {
+ kUse,
+ kRevalidate,
+ kReload,
+ kLoad,
+ kMaxValue = kLoad
+ };
// A wrapper just for placing a trace_event macro.
RevalidationPolicy DetermineRevalidationPolicy(
@@ -445,7 +456,7 @@ class ResourceCacheValidationSuppressor {
}
private:
- Member<ResourceFetcher> loader_;
+ ResourceFetcher* loader_;
bool previous_state_;
DISALLOW_COPY_AND_ASSIGN(ResourceCacheValidationSuppressor);
@@ -465,15 +476,15 @@ struct PLATFORM_EXPORT ResourceFetcherInit final {
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
ResourceFetcher::LoaderFactory* loader_factory);
- const Member<DetachableResourceFetcherProperties> properties;
- const Member<FetchContext> context;
+ DetachableResourceFetcherProperties* const properties;
+ FetchContext* const context;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner;
- const Member<ResourceFetcher::LoaderFactory> loader_factory;
- Member<DetachableUseCounter> use_counter;
- Member<DetachableConsoleLogger> console_logger;
+ ResourceFetcher::LoaderFactory* const loader_factory;
+ DetachableUseCounter* use_counter = nullptr;
+ DetachableConsoleLogger* console_logger = nullptr;
ResourceLoadScheduler::ThrottlingPolicy initial_throttling_policy =
ResourceLoadScheduler::ThrottlingPolicy::kNormal;
- Member<MHTMLArchive> archive;
+ MHTMLArchive* archive = nullptr;
FrameScheduler* frame_scheduler = nullptr;
DISALLOW_COPY_AND_ASSIGN(ResourceFetcherInit);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
index 3b14d081582..8890de7be67 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
@@ -6,6 +6,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
@@ -26,7 +27,7 @@ class DetachableResourceFetcherPropertiesTest : public testing::Test {
network::mojom::ReferrerPolicy::kDefault,
"https://example.com/foo.html", HttpsState::kModern,
AllowedByNosniff::MimeTypeCheck::kStrict, address_space,
- kLeaveInsecureRequestsAlone,
+ mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone,
FetchClientSettingsObject::InsecureNavigationsSet());
}
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index bb529c83964..980d15a3fd0 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -37,6 +37,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -103,10 +104,26 @@ const FetchClientSettingsObjectSnapshot& CreateFetchClientSettingsObject(
SecurityOrigin::Create(KURL("https://example.com/")),
network::mojom::ReferrerPolicy::kDefault, "https://example.com/foo.html",
HttpsState::kModern, AllowedByNosniff::MimeTypeCheck::kStrict,
- address_space, kLeaveInsecureRequestsAlone,
+ address_space,
+ mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone,
FetchClientSettingsObject::InsecureNavigationsSet());
}
+class PartialResourceRequest {
+ public:
+ PartialResourceRequest() : PartialResourceRequest(ResourceRequest()) {}
+ PartialResourceRequest(const ResourceRequest& request)
+ : is_ad_resource_(request.IsAdResource()),
+ priority_(request.Priority()) {}
+
+ bool IsAdResource() const { return is_ad_resource_; }
+ ResourceLoadPriority Priority() const { return priority_; }
+
+ private:
+ bool is_ad_resource_;
+ ResourceLoadPriority priority_;
+};
+
} // namespace
class ResourceFetcherTest : public testing::Test {
@@ -123,7 +140,7 @@ class ResourceFetcherTest : public testing::Test {
const ResourceResponse& redirect_response,
ResourceType,
const FetchInitiatorInfo&) override {
- request_ = request;
+ request_ = PartialResourceRequest(request);
}
void DidChangePriority(uint64_t identifier,
ResourceLoadPriority,
@@ -149,12 +166,12 @@ class ResourceFetcherTest : public testing::Test {
int64_t encoded_data_length,
IsInternalRequest is_internal_request) override {}
- const base::Optional<ResourceRequest>& GetLastRequest() const {
+ const base::Optional<PartialResourceRequest>& GetLastRequest() const {
return request_;
}
private:
- base::Optional<ResourceRequest> request_;
+ base::Optional<PartialResourceRequest> request_;
};
protected:
@@ -194,7 +211,7 @@ TEST_F(ResourceFetcherTest, StartLoadAfterFrameDetach) {
fetcher->ClearContext();
ResourceRequest resource_request(secure_url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
Resource* resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
ASSERT_TRUE(resource);
EXPECT_TRUE(resource->ErrorOccurred());
@@ -256,12 +273,13 @@ TEST_F(ResourceFetcherTest, WillSendRequestAdBit) {
ResourceRequest resource_request(url);
resource_request.SetIsAdResource();
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
platform_->GetURLLoaderMockFactory()->RegisterURL(url, WebURLResponse(), "");
Resource* new_resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_EQ(resource, new_resource);
- base::Optional<ResourceRequest> new_request = observer->GetLastRequest();
+ base::Optional<PartialResourceRequest> new_request =
+ observer->GetLastRequest();
EXPECT_TRUE(new_request.has_value());
EXPECT_TRUE(new_request.value().IsAdResource());
}
@@ -286,7 +304,7 @@ TEST_F(ResourceFetcherTest, Vary) {
*MakeGarbageCollected<TestResourceFetcherProperties>(source_origin));
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
platform_->GetURLLoaderMockFactory()->RegisterURL(url, WebURLResponse(), "");
Resource* new_resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_NE(resource, new_resource);
@@ -296,7 +314,8 @@ TEST_F(ResourceFetcherTest, Vary) {
TEST_F(ResourceFetcherTest, ResourceTimingInfo) {
auto info = ResourceTimingInfo::Create(
fetch_initiator_type_names::kDocument, base::TimeTicks::Now(),
- mojom::RequestContextType::UNSPECIFIED);
+ mojom::RequestContextType::UNSPECIFIED,
+ network::mojom::RequestDestination::kEmpty);
info->AddFinalTransferSize(5);
EXPECT_EQ(info->TransferSize(), static_cast<uint64_t>(5));
ResourceResponse redirect_response(KURL("https://example.com/original"));
@@ -328,7 +347,7 @@ TEST_F(ResourceFetcherTest, VaryOnBack) {
ResourceRequest resource_request(url);
resource_request.SetCacheMode(mojom::FetchCacheMode::kForceCache);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
Resource* new_resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_EQ(resource, new_resource);
}
@@ -383,7 +402,7 @@ class RequestSameResourceOnComplete
MakeGarbageCollected<TestLoaderFactory>()));
ResourceRequest resource_request2(GetResource()->Url());
resource_request2.SetCacheMode(mojom::FetchCacheMode::kValidateCache);
- FetchParameters fetch_params2(resource_request2);
+ FetchParameters fetch_params2(std::move(resource_request2));
Resource* resource2 = MockResource::Fetch(fetch_params2, fetcher2, nullptr);
EXPECT_EQ(GetResource(), resource2);
notify_finished_called_ = true;
@@ -391,9 +410,7 @@ class RequestSameResourceOnComplete
}
bool NotifyFinishedCalled() const { return notify_finished_called_; }
- void Trace(blink::Visitor* visitor) override {
- RawResourceClient::Trace(visitor);
- }
+ void Trace(Visitor* visitor) override { RawResourceClient::Trace(visitor); }
String DebugName() const override { return "RequestSameResourceOnComplete"; }
@@ -419,7 +436,7 @@ TEST_F(ResourceFetcherTest, RevalidateWhileFinishingLoading) {
*MakeGarbageCollected<TestResourceFetcherProperties>(source_origin));
ResourceRequest request1(url);
request1.SetHttpHeaderField(http_names::kCacheControl, "no-cache");
- FetchParameters fetch_params1(request1);
+ FetchParameters fetch_params1(std::move(request1));
Persistent<RequestSameResourceOnComplete> client =
MakeGarbageCollected<RequestSameResourceOnComplete>(fetch_params1,
fetcher1);
@@ -440,7 +457,7 @@ TEST_F(ResourceFetcherTest, MAYBE_DontReuseMediaDataUrl) {
ResourceLoaderOptions options;
options.data_buffering_policy = kDoNotBufferData;
options.initiator_info.name = fetch_initiator_type_names::kInternal;
- FetchParameters fetch_params(request, options);
+ FetchParameters fetch_params(std::move(request), options);
Resource* resource1 = RawResource::FetchMedia(fetch_params, fetcher, nullptr);
Resource* resource2 = RawResource::FetchMedia(fetch_params, fetcher, nullptr);
EXPECT_NE(resource1, resource2);
@@ -477,9 +494,7 @@ class ServeRequestsOnCompleteClient final
}
void DataDownloaded(Resource*, uint64_t) override { ASSERT_TRUE(false); }
- void Trace(blink::Visitor* visitor) override {
- RawResourceClient::Trace(visitor);
- }
+ void Trace(Visitor* visitor) override { RawResourceClient::Trace(visitor); }
String DebugName() const override { return "ServeRequestsOnCompleteClient"; }
};
@@ -496,7 +511,7 @@ TEST_F(ResourceFetcherTest, ResponseOnCancel) {
auto* fetcher = CreateFetcher();
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
Persistent<ServeRequestsOnCompleteClient> client =
MakeGarbageCollected<ServeRequestsOnCompleteClient>();
Resource* resource = RawResource::Fetch(fetch_params, fetcher, client);
@@ -536,13 +551,13 @@ class ScopedMockRedirectRequester {
MakeGarbageCollected<TestLoaderFactory>()));
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
RawResource::Fetch(fetch_params, fetcher, nullptr);
url_test_helpers::ServeAsynchronousRequests();
}
private:
- Member<MockFetchContext> context_;
+ MockFetchContext* context_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(ScopedMockRedirectRequester);
@@ -596,7 +611,7 @@ TEST_F(ResourceFetcherTest, SynchronousRequest) {
auto* fetcher = CreateFetcher();
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
fetch_params.MakeSynchronous();
Resource* resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_TRUE(resource->IsLoaded());
@@ -611,7 +626,7 @@ TEST_F(ResourceFetcherTest, PingPriority) {
auto* fetcher = CreateFetcher();
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::PING);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
Resource* resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_EQ(ResourceLoadPriority::kVeryLow,
resource->GetResourceRequest().Priority());
@@ -849,7 +864,7 @@ TEST_F(ResourceFetcherTest, Revalidate304) {
*MakeGarbageCollected<TestResourceFetcherProperties>(source_origin));
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
platform_->GetURLLoaderMockFactory()->RegisterURL(url, WebURLResponse(), "");
Resource* new_resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
fetcher->StopFetching();
@@ -918,7 +933,7 @@ TEST_F(ResourceFetcherTest, ContentIdURL) {
{
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::VIDEO);
- FetchParameters fetch_params(resource_request);
+ FetchParameters fetch_params(std::move(resource_request));
RawResource* resource =
RawResource::FetchMedia(fetch_params, fetcher, nullptr);
ASSERT_NE(nullptr, resource);
@@ -956,7 +971,7 @@ TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
- FetchParameters fetch_params2 = FetchParameters(resource_request);
+ FetchParameters fetch_params2 = FetchParameters(std::move(resource_request));
Resource* new_resource = MockResource::Fetch(fetch_params2, fetcher, nullptr);
EXPECT_EQ(resource, new_resource);
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
@@ -976,7 +991,8 @@ TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
EXPECT_TRUE(GetMemoryCache()->Contains(resource));
static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get())
->RunUntilIdle();
- base::Optional<ResourceRequest> swr_request = observer->GetLastRequest();
+ base::Optional<PartialResourceRequest> swr_request =
+ observer->GetLastRequest();
ASSERT_TRUE(swr_request.has_value());
EXPECT_EQ(ResourceLoadPriority::kVeryLow, swr_request->Priority());
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h
index 72cfbda8334..376800c68cd 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h
@@ -14,12 +14,13 @@ namespace blink {
// ResourceFinishObserver is different from ResourceClient in several ways.
// - NotifyFinished is dispatched asynchronously.
// - ResourceFinishObservers will be removed from Resource when the load
-// finishes. - This class is not intended to be "subclassed" per each Resource
-// subclass.
+// finishes.
+// - This class is not intended to be "subclassed" per each Resource subclass.
// There is no ImageResourceFinishObserver, for example.
// ResourceFinishObserver should be quite simple. All notifications must be
// notified AFTER the loading finishes.
-class PLATFORM_EXPORT ResourceFinishObserver : public GarbageCollectedMixin {
+class PLATFORM_EXPORT ResourceFinishObserver
+ : public GarbageCollected<ResourceFinishObserver> {
public:
virtual ~ResourceFinishObserver() = default;
@@ -30,7 +31,7 @@ class PLATFORM_EXPORT ResourceFinishObserver : public GarbageCollectedMixin {
// Name for debugging
virtual String DebugName() const = 0;
- void Trace(blink::Visitor* visitor) override {}
+ virtual void Trace(Visitor* visitor) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
index 6496f9fe7e8..c79595b9005 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
@@ -235,7 +235,7 @@ ResourceLoadScheduler::ResourceLoadScheduler(
ResourceLoadScheduler::~ResourceLoadScheduler() = default;
-void ResourceLoadScheduler::Trace(blink::Visitor* visitor) {
+void ResourceLoadScheduler::Trace(Visitor* visitor) {
visitor->Trace(pending_request_map_);
visitor->Trace(resource_fetcher_properties_);
visitor->Trace(console_logger_);
@@ -275,7 +275,7 @@ void ResourceLoadScheduler::Request(ResourceLoadSchedulerClient* client,
// Check if the request can be throttled.
ClientIdWithPriority request_info(*id, priority, intra_priority);
- if (!IsClientDelayable(request_info, option)) {
+ if (!IsClientDelayable(option)) {
Run(*id, client, false);
return;
}
@@ -356,27 +356,15 @@ void ResourceLoadScheduler::SetOutstandingLimitForTesting(size_t tight_limit,
MaybeRun();
}
-bool ResourceLoadScheduler::IsClientDelayable(const ClientIdWithPriority& info,
- ThrottleOption option) const {
- const bool throttleable = option == ThrottleOption::kThrottleable &&
- info.priority < ResourceLoadPriority::kHigh;
- const bool stoppable = option != ThrottleOption::kCanNotBeStoppedOrThrottled;
-
- // Also takes the lifecycle state of the associated FrameScheduler
- // into account to determine if the request should be throttled
- // regardless of the priority.
+bool ResourceLoadScheduler::IsClientDelayable(ThrottleOption option) const {
switch (frame_scheduler_lifecycle_state_) {
case scheduler::SchedulingLifecycleState::kNotThrottled:
- return throttleable;
case scheduler::SchedulingLifecycleState::kHidden:
case scheduler::SchedulingLifecycleState::kThrottled:
return option == ThrottleOption::kThrottleable;
case scheduler::SchedulingLifecycleState::kStopped:
- return stoppable;
+ return option != ThrottleOption::kCanNotBeStoppedOrThrottled;
}
-
- NOTREACHED() << static_cast<int>(frame_scheduler_lifecycle_state_);
- return throttleable;
}
void ResourceLoadScheduler::OnLifecycleStateChanged(
@@ -419,9 +407,6 @@ bool ResourceLoadScheduler::IsPendingRequestEffectivelyEmpty(
}
bool ResourceLoadScheduler::GetNextPendingRequest(ClientId* id) {
- bool needs_throttling =
- running_throttleable_requests_.size() >= GetOutstandingLimit();
-
auto& stoppable_queue = pending_requests_[ThrottleOption::kStoppable];
auto& throttleable_queue = pending_requests_[ThrottleOption::kThrottleable];
@@ -429,14 +414,16 @@ bool ResourceLoadScheduler::GetNextPendingRequest(ClientId* id) {
auto stoppable_it = stoppable_queue.begin();
bool has_runnable_stoppable_request =
stoppable_it != stoppable_queue.end() &&
- (!IsClientDelayable(*stoppable_it, ThrottleOption::kStoppable) ||
- !needs_throttling);
+ (!IsClientDelayable(ThrottleOption::kStoppable) ||
+ running_throttleable_requests_.size() <
+ GetOutstandingLimit(stoppable_it->priority));
auto throttleable_it = throttleable_queue.begin();
bool has_runnable_throttleable_request =
throttleable_it != throttleable_queue.end() &&
- (!IsClientDelayable(*throttleable_it, ThrottleOption::kThrottleable) ||
- !needs_throttling);
+ (!IsClientDelayable(ThrottleOption::kThrottleable) ||
+ running_throttleable_requests_.size() <
+ GetOutstandingLimit(throttleable_it->priority));
if (!has_runnable_throttleable_request && !has_runnable_stoppable_request)
return false;
@@ -489,7 +476,8 @@ void ResourceLoadScheduler::Run(ResourceLoadScheduler::ClientId id,
client->Run();
}
-size_t ResourceLoadScheduler::GetOutstandingLimit() const {
+size_t ResourceLoadScheduler::GetOutstandingLimit(
+ ResourceLoadPriority priority) const {
size_t limit = kOutstandingUnlimited;
switch (frame_scheduler_lifecycle_state_) {
@@ -506,7 +494,9 @@ size_t ResourceLoadScheduler::GetOutstandingLimit() const {
switch (policy_) {
case ThrottlingPolicy::kTight:
- limit = std::min(limit, tight_outstanding_limit_);
+ limit = std::min(limit, priority < ResourceLoadPriority::kHigh
+ ? tight_outstanding_limit_
+ : normal_outstanding_limit_);
break;
case ThrottlingPolicy::kNormal:
limit = std::min(limit, normal_outstanding_limit_);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
index b951ecfd303..eb66476c349 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
@@ -33,7 +33,7 @@ class PLATFORM_EXPORT ResourceLoadSchedulerClient
// Called when the request is granted to run.
virtual void Run() = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
// ResourceLoadScheduler provides a unified per-frame infrastructure to schedule
@@ -157,7 +157,7 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
DetachableConsoleLogger& console_logger);
~ResourceLoadScheduler() override;
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
// Changes the policy from |kTight| to |kNormal|. This function can be called
// multiple times, and does nothing when the scheduler is already working with
@@ -245,7 +245,7 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
priority(priority),
intra_priority(intra_priority) {}
- void Trace(blink::Visitor* visitor) { visitor->Trace(client); }
+ void Trace(Visitor* visitor) { visitor->Trace(client); }
Member<ResourceLoadSchedulerClient> client;
ThrottleOption option;
@@ -261,10 +261,9 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
// Gets the highest priority pending request that is allowed to be run.
bool GetNextPendingRequest(ClientId* id);
- // Returns whether we can throttle a request with the given client info based
+ // Returns whether we can throttle a request with the given option based
// on life cycle state.
- bool IsClientDelayable(const ClientIdWithPriority& info,
- ThrottleOption option) const;
+ bool IsClientDelayable(ThrottleOption option) const;
// Generates the next ClientId.
ClientId GenerateClientId();
@@ -275,7 +274,7 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
// Grants a client to run,
void Run(ClientId, ResourceLoadSchedulerClient*, bool throttleable);
- size_t GetOutstandingLimit() const;
+ size_t GetOutstandingLimit(ResourceLoadPriority priority) const;
void ShowConsoleMessageIfNeeded();
@@ -283,7 +282,6 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
resource_fetcher_properties_;
// A flag to indicate an internal running state.
- // TODO(toyoshim): We may want to use enum once we start to have more states.
bool is_shutdown_ = false;
ThrottlingPolicy policy_ = ThrottlingPolicy::kNormal;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
index a5056c1becf..ffe0d245cfc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -38,7 +38,7 @@ class MockClient final : public GarbageCollected<MockClient>,
return client_order_;
}
- void Trace(blink::Visitor* visitor) { visitor->Trace(client_order_); }
+ void Trace(Visitor* visitor) { visitor->Trace(client_order_); }
private:
HeapVector<Member<MockClient>> client_order_;
@@ -56,7 +56,7 @@ class MockClient final : public GarbageCollected<MockClient>,
}
bool WasRun() { return was_run_; }
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
ResourceLoadSchedulerClient::Trace(visitor);
visitor->Trace(console_logger_);
}
@@ -349,7 +349,8 @@ TEST_F(ResourceLoadSchedulerTest, PriorityIsConsidered) {
// Push three requests.
MockClient* client1 = MakeGarbageCollected<MockClient>();
- Scheduler()->SetOutstandingLimitForTesting(0);
+ // Allows one kHigh priority request by limits below.
+ Scheduler()->SetOutstandingLimitForTesting(0, 1);
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
Scheduler()->Request(client1, ThrottleOption::kThrottleable,
@@ -383,23 +384,21 @@ TEST_F(ResourceLoadSchedulerTest, PriorityIsConsidered) {
EXPECT_FALSE(client3->WasRun());
EXPECT_TRUE(client4->WasRun());
- // Client 4 does not count against the limit as it was not delayable when it
- // was created.
- Scheduler()->SetOutstandingLimitForTesting(1);
+ Scheduler()->SetOutstandingLimitForTesting(2);
EXPECT_FALSE(client1->WasRun());
EXPECT_FALSE(client2->WasRun());
EXPECT_TRUE(client3->WasRun());
EXPECT_TRUE(client4->WasRun());
- Scheduler()->SetOutstandingLimitForTesting(2);
+ Scheduler()->SetOutstandingLimitForTesting(3);
EXPECT_FALSE(client1->WasRun());
EXPECT_TRUE(client2->WasRun());
EXPECT_TRUE(client3->WasRun());
EXPECT_TRUE(client4->WasRun());
- Scheduler()->SetOutstandingLimitForTesting(3);
+ Scheduler()->SetOutstandingLimitForTesting(4);
EXPECT_TRUE(client1->WasRun());
EXPECT_TRUE(client2->WasRun());
@@ -407,7 +406,6 @@ TEST_F(ResourceLoadSchedulerTest, PriorityIsConsidered) {
EXPECT_TRUE(client4->WasRun());
// Release the rest.
- EXPECT_TRUE(Release(id4));
EXPECT_TRUE(Release(id3));
EXPECT_TRUE(Release(id2));
EXPECT_TRUE(Release(id1));
@@ -511,12 +509,11 @@ TEST_F(ResourceLoadSchedulerTest, StoppableRequestResumesWhenThrottled) {
}
TEST_F(ResourceLoadSchedulerTest, SetPriority) {
- // Start with the normal scheduling policy.
- Scheduler()->LoosenThrottlingPolicy();
// Push three requests.
MockClient* client1 = MakeGarbageCollected<MockClient>();
- Scheduler()->SetOutstandingLimitForTesting(0);
+ // Allows one kHigh priority request by limits below.
+ Scheduler()->SetOutstandingLimitForTesting(0, 1);
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
Scheduler()->Request(client1, ThrottleOption::kThrottleable,
@@ -554,7 +551,16 @@ TEST_F(ResourceLoadSchedulerTest, SetPriority) {
EXPECT_FALSE(client2->WasRun());
EXPECT_FALSE(client3->WasRun());
- Scheduler()->SetOutstandingLimitForTesting(2);
+ // Loosen the policy to adopt the normal limit for all.
+ Scheduler()->LoosenThrottlingPolicy();
+ Scheduler()->SetOutstandingLimitForTesting(0, 2);
+
+ EXPECT_TRUE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+ EXPECT_FALSE(client3->WasRun());
+
+ // kHigh priority does not help here.
+ Scheduler()->SetPriority(id3, ResourceLoadPriority::kHigh, 0);
EXPECT_TRUE(client1->WasRun());
EXPECT_TRUE(client2->WasRun());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
index 838094ab45a..d09e6c051fb 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
@@ -4,35 +4,79 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
+#include "services/network/public/mojom/load_timing_info.mojom-blink.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
-ResourceLoadTiming::ResourceLoadTiming() {}
+ResourceLoadTiming::ResourceLoadTiming() = default;
+
+ResourceLoadTiming::ResourceLoadTiming(base::TimeTicks request_time,
+ base::TimeTicks proxy_start,
+ base::TimeTicks proxy_end,
+ base::TimeTicks dns_start,
+ base::TimeTicks dns_end,
+ base::TimeTicks connect_start,
+ base::TimeTicks connect_end,
+ base::TimeTicks worker_start,
+ base::TimeTicks worker_ready,
+ base::TimeTicks send_start,
+ base::TimeTicks send_end,
+ base::TimeTicks receive_headers_start,
+ base::TimeTicks receive_headers_end,
+ base::TimeTicks ssl_start,
+ base::TimeTicks ssl_end,
+ base::TimeTicks push_start,
+ base::TimeTicks push_end)
+ : request_time_(request_time),
+ proxy_start_(proxy_start),
+ proxy_end_(proxy_end),
+ dns_start_(dns_start),
+ dns_end_(dns_end),
+ connect_start_(connect_start),
+ connect_end_(connect_end),
+ worker_start_(worker_start),
+ worker_ready_(worker_ready),
+ send_start_(send_start),
+ send_end_(send_end),
+ receive_headers_start_(receive_headers_start),
+ receive_headers_end_(receive_headers_end),
+ ssl_start_(ssl_start),
+ ssl_end_(ssl_end),
+ push_start_(push_start),
+ push_end_(push_end) {}
scoped_refptr<ResourceLoadTiming> ResourceLoadTiming::Create() {
return base::AdoptRef(new ResourceLoadTiming);
}
-scoped_refptr<ResourceLoadTiming> ResourceLoadTiming::DeepCopy() {
- scoped_refptr<ResourceLoadTiming> timing = Create();
- timing->request_time_ = request_time_;
- timing->proxy_start_ = proxy_start_;
- timing->proxy_end_ = proxy_end_;
- timing->dns_start_ = dns_start_;
- timing->dns_end_ = dns_end_;
- timing->connect_start_ = connect_start_;
- timing->connect_end_ = connect_end_;
- timing->worker_start_ = worker_start_;
- timing->worker_ready_ = worker_ready_;
- timing->send_start_ = send_start_;
- timing->send_end_ = send_end_;
- timing->receive_headers_start_ = receive_headers_start_;
- timing->receive_headers_end_ = receive_headers_end_;
- timing->ssl_start_ = ssl_start_;
- timing->ssl_end_ = ssl_end_;
- timing->push_start_ = push_start_;
- timing->push_end_ = push_end_;
+scoped_refptr<ResourceLoadTiming> ResourceLoadTiming::FromMojo(
+ const network::mojom::blink::LoadTimingInfo* mojo_timing) {
+ if (!mojo_timing)
+ return ResourceLoadTiming::Create();
+ return base::AdoptRef(new ResourceLoadTiming(
+ mojo_timing->request_start, mojo_timing->proxy_resolve_start,
+ mojo_timing->proxy_resolve_end, mojo_timing->connect_timing->dns_start,
+ mojo_timing->connect_timing->dns_end,
+ mojo_timing->connect_timing->connect_start,
+ mojo_timing->connect_timing->connect_end,
+ mojo_timing->service_worker_start_time,
+ mojo_timing->service_worker_ready_time, mojo_timing->send_start,
+ mojo_timing->send_end, mojo_timing->receive_headers_start,
+ mojo_timing->receive_headers_end, mojo_timing->connect_timing->ssl_start,
+ mojo_timing->connect_timing->ssl_end, mojo_timing->push_start,
+ mojo_timing->push_end));
+}
+
+network::mojom::blink::LoadTimingInfoPtr ResourceLoadTiming::ToMojo() const {
+ network::mojom::blink::LoadTimingInfoPtr timing =
+ network::mojom::blink::LoadTimingInfo::New(
+ false, 0, base::Time(), request_time_, proxy_start_, proxy_end_,
+ network::mojom::blink::LoadTimingInfoConnectTiming::New(
+ dns_start_, dns_end_, connect_start_, connect_end_, ssl_start_,
+ ssl_end_),
+ send_start_, send_end_, receive_headers_start_, receive_headers_end_,
+ push_start_, push_end_, worker_start_, worker_ready_);
return timing;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h
index ef8321289d3..b87da1d183f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_TIMING_H_
#include "base/memory/scoped_refptr.h"
+#include "services/network/public/mojom/load_timing_info.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -37,10 +38,13 @@ class PLATFORM_EXPORT ResourceLoadTiming
public:
static scoped_refptr<ResourceLoadTiming> Create();
- scoped_refptr<ResourceLoadTiming> DeepCopy();
bool operator==(const ResourceLoadTiming&) const;
bool operator!=(const ResourceLoadTiming&) const;
+ static scoped_refptr<ResourceLoadTiming> FromMojo(
+ const network::mojom::blink::LoadTimingInfo*);
+ network::mojom::blink::LoadTimingInfoPtr ToMojo() const;
+
void SetDnsStart(base::TimeTicks);
void SetRequestTime(base::TimeTicks);
void SetProxyStart(base::TimeTicks);
@@ -81,6 +85,23 @@ class PLATFORM_EXPORT ResourceLoadTiming
private:
ResourceLoadTiming();
+ ResourceLoadTiming(base::TimeTicks request_time,
+ base::TimeTicks proxy_start,
+ base::TimeTicks proxy_end,
+ base::TimeTicks dns_start,
+ base::TimeTicks dns_end,
+ base::TimeTicks connect_start,
+ base::TimeTicks connect_end,
+ base::TimeTicks worker_start,
+ base::TimeTicks worker_ready,
+ base::TimeTicks send_start,
+ base::TimeTicks send_end,
+ base::TimeTicks receive_headers_start,
+ base::TimeTicks receive_headers_end,
+ base::TimeTicks ssl_start,
+ base::TimeTicks ssl_end,
+ base::TimeTicks push_start,
+ base::TimeTicks push_end);
// We want to present a unified timeline to Javascript. Using walltime is
// problematic, because the clock may skew while resources load. To prevent
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 58399f33fd1..7f1a04c6fe4 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -41,6 +41,7 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
@@ -67,6 +68,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
#include "third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h"
#include "third_party/blink/renderer/platform/loader/mixed_content_autoupgrade_status.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
@@ -74,8 +76,8 @@
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+#include "third_party/blink/renderer/platform/weborigin/reporting_disposition.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
-#include "third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
@@ -147,7 +149,7 @@ void LogMixedAutoupgradeMetrics(blink::MixedContentAutoupgradeStatus status,
builder.Record(recorder);
}
-bool CanHandleDataURLRequestLocally(const ResourceRequest& request) {
+bool CanHandleDataURLRequestLocally(const ResourceRequestHead& request) {
if (!request.Url().ProtocolIsData())
return false;
@@ -156,11 +158,6 @@ bool CanHandleDataURLRequestLocally(const ResourceRequest& request) {
if (request.DownloadToBlob())
return false;
- // Data url requests from object tags may need to be intercepted as streams
- // and so need to be sent to the browser.
- if (request.GetRequestContext() == mojom::RequestContextType::OBJECT)
- return false;
-
// Main resources are handled in the browser, so we can handle data url
// subresources locally.
return true;
@@ -178,6 +175,18 @@ bool RequestContextObserveResponse(mojom::RequestContextType type) {
}
}
+SchedulingPolicy::Feature GetFeatureFromRequestContextType(
+ mojom::RequestContextType type) {
+ switch (type) {
+ case mojom::RequestContextType::FETCH:
+ return SchedulingPolicy::Feature::kOutstandingNetworkRequestFetch;
+ case mojom::RequestContextType::XML_HTTP_REQUEST:
+ return SchedulingPolicy::Feature::kOutstandingNetworkRequestXHR;
+ default:
+ return SchedulingPolicy::Feature::kOutstandingNetworkRequestOthers;
+ }
+}
+
} // namespace
// CodeCacheRequest handles the requests to fetch data from code cache.
@@ -372,11 +381,13 @@ void ResourceLoader::CodeCacheRequest::MaybeSendCachedCode(
ResourceLoader::ResourceLoader(ResourceFetcher* fetcher,
ResourceLoadScheduler* scheduler,
Resource* resource,
+ ResourceRequestBody request_body,
uint32_t inflight_keepalive_bytes)
: scheduler_client_id_(ResourceLoadScheduler::kInvalidClientId),
fetcher_(fetcher),
scheduler_(scheduler),
resource_(resource),
+ request_body_(std::move(request_body)),
inflight_keepalive_bytes_(inflight_keepalive_bytes),
is_cache_aware_loading_activated_(false),
cancel_timer_(fetcher_->GetTaskRunner(),
@@ -389,11 +400,12 @@ ResourceLoader::ResourceLoader(ResourceFetcher* fetcher,
// If they are keepalive request && their responses are not observable to web
// content, we can have them survive without breaking web content when the
// page is put into BackForwardCache.
- auto request = resource_->GetResourceRequest();
- if (!RequestContextObserveResponse(request.GetRequestContext())) {
+ auto& request = resource_->GetResourceRequest();
+ auto request_context = request.GetRequestContext();
+ if (!RequestContextObserveResponse(request_context)) {
if (FrameScheduler* frame_scheduler = fetcher->GetFrameScheduler()) {
feature_handle_for_scheduler_ = frame_scheduler->RegisterFeature(
- SchedulingPolicy::Feature::kOutstandingNetworkRequest,
+ GetFeatureFromRequestContextType(request_context),
{SchedulingPolicy::RecordMetricsForBackForwardCache()});
}
}
@@ -403,7 +415,7 @@ ResourceLoader::ResourceLoader(ResourceFetcher* fetcher,
ResourceLoader::~ResourceLoader() = default;
-void ResourceLoader::Trace(blink::Visitor* visitor) {
+void ResourceLoader::Trace(Visitor* visitor) {
visitor->Trace(fetcher_);
visitor->Trace(scheduler_);
visitor->Trace(resource_);
@@ -415,11 +427,8 @@ void ResourceLoader::Trace(blink::Visitor* visitor) {
bool ResourceLoader::ShouldFetchCodeCache() {
if (!RuntimeEnabledFeatures::IsolatedCodeCacheEnabled())
return false;
- if (resource_->GetType() == ResourceType::kRaw &&
- !RuntimeEnabledFeatures::WasmCodeCacheEnabled())
- return false;
- const ResourceRequest& request = resource_->GetResourceRequest();
+ const ResourceRequestHead& request = resource_->GetResourceRequest();
if (!request.Url().ProtocolIsInHTTPFamily())
return false;
// When loading the service worker scripts, we don't need to check the
@@ -448,9 +457,12 @@ bool ResourceLoader::ShouldFetchCodeCache() {
}
void ResourceLoader::Start() {
- const ResourceRequest& request = resource_->GetResourceRequest();
+ const ResourceRequestHead& request = resource_->GetResourceRequest();
ActivateCacheAwareLoadingIfNeeded(request);
- loader_ = fetcher_->CreateURLLoader(request, resource_->Options());
+ // TODO(yoichio): Have CreateURLLoader take a ResourceRequestHead, not
+ // ResourceRequest.
+ loader_ =
+ fetcher_->CreateURLLoader(ResourceRequest(request), resource_->Options());
task_runner_for_body_loader_ = loader_->GetTaskRunner();
DCHECK_EQ(ResourceLoadScheduler::kInvalidClientId, scheduler_client_id_);
auto throttle_option = ResourceLoadScheduler::ThrottleOption::kThrottleable;
@@ -547,7 +559,7 @@ void ResourceLoader::DidCancelLoadingBody() {
Cancel();
}
-void ResourceLoader::StartWith(const ResourceRequest& request) {
+void ResourceLoader::StartWith(const ResourceRequestHead& request) {
DCHECK_NE(ResourceLoadScheduler::kInvalidClientId, scheduler_client_id_);
DCHECK(loader_);
@@ -570,7 +582,7 @@ void ResourceLoader::StartWith(const ResourceRequest& request) {
if (is_cache_aware_loading_activated_) {
// Override cache policy for cache-aware loading. If this request fails, a
// reload with original request will be triggered in DidFail().
- ResourceRequest cache_aware_request(request);
+ ResourceRequestHead cache_aware_request(request);
cache_aware_request.SetCacheMode(
mojom::FetchCacheMode::kUnspecifiedOnlyIfCachedStrict);
RequestAsynchronously(cache_aware_request);
@@ -594,9 +606,10 @@ void ResourceLoader::Release(
feature_handle_for_scheduler_.reset();
}
-void ResourceLoader::Restart(const ResourceRequest& request) {
+void ResourceLoader::Restart(const ResourceRequestHead& request) {
CHECK_EQ(resource_->Options().synchronous_policy, kRequestAsynchronously);
- loader_ = fetcher_->CreateURLLoader(request, resource_->Options());
+ loader_ =
+ fetcher_->CreateURLLoader(ResourceRequest(request), resource_->Options());
task_runner_for_body_loader_ = loader_->GetTaskRunner();
StartWith(request);
}
@@ -678,14 +691,14 @@ void ResourceLoader::CancelForRedirectAccessCheckError(
}
}
-static bool IsManualRedirectFetchRequest(const ResourceRequest& request) {
+static bool IsManualRedirectFetchRequest(const ResourceRequestHead& request) {
return request.GetRedirectMode() == network::mojom::RedirectMode::kManual &&
request.GetRequestContext() == mojom::RequestContextType::FETCH;
}
bool ResourceLoader::WillFollowRedirect(
const WebURL& new_url,
- const WebURL& new_site_for_cookies,
+ const net::SiteForCookies& new_site_for_cookies,
const WebString& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
const WebString& new_method,
@@ -704,12 +717,16 @@ bool ResourceLoader::WillFollowRedirect(
resource_->LastResourceRequest().CreateRedirectRequest(
new_url, new_method, new_site_for_cookies, new_referrer,
new_referrer_policy,
-
!passed_redirect_response.WasFetchedViaServiceWorker());
+ if (!RuntimeEnabledFeatures::OutOfBlinkCorsEnabled() &&
+ (new_request->HttpMethod() != http_names::kGET &&
+ new_request->HttpMethod() != http_names::kHEAD)) {
+ new_request->SetHttpBody(request_body_.FormBody());
+ }
ResourceType resource_type = resource_->GetType();
- const ResourceRequest& initial_request = resource_->GetResourceRequest();
+ const ResourceRequestHead& initial_request = resource_->GetResourceRequest();
// The following parameters never change during the lifetime of a request.
mojom::RequestContextType request_context =
initial_request.GetRequestContext();
@@ -726,19 +743,20 @@ bool ResourceLoader::WillFollowRedirect(
bool unused_preload = resource_->IsUnusedPreload();
// Don't send security violation reports for unused preloads.
- SecurityViolationReportingPolicy reporting_policy =
- unused_preload ? SecurityViolationReportingPolicy::kSuppressReporting
- : SecurityViolationReportingPolicy::kReport;
+ ReportingDisposition reporting_disposition =
+ unused_preload ? ReportingDisposition::kSuppressReporting
+ : ReportingDisposition::kReport;
// CanRequest() checks only enforced CSP, so check report-only here to
// ensure that violations are sent.
Context().CheckCSPForRequest(
- request_context, new_url, options, reporting_policy,
+ request_context, new_url, options, reporting_disposition,
ResourceRequest::RedirectStatus::kFollowedRedirect);
base::Optional<ResourceRequestBlockedReason> blocked_reason =
Context().CanRequest(
- resource_type, *new_request, new_url, options, reporting_policy,
+ resource_type, *new_request, new_url, options,
+ reporting_disposition,
ResourceRequest::RedirectStatus::kFollowedRedirect);
if (Context().CalculateIfAdSubresource(*new_request, resource_type))
@@ -756,9 +774,9 @@ bool ResourceLoader::WillFollowRedirect(
new_url, request_mode, origin.get(),
GetCorsFlag() ? CorsFlag::Set : CorsFlag::Unset);
if (!cors_error && GetCorsFlag()) {
- cors_error = cors::CheckAccess(
- new_url, redirect_response.HttpStatusCode(),
- redirect_response.HttpHeaderFields(), credentials_mode, *origin);
+ cors_error =
+ cors::CheckAccess(new_url, redirect_response.HttpHeaderFields(),
+ credentials_mode, *origin);
}
if (cors_error) {
HandleError(
@@ -809,18 +827,20 @@ bool ResourceLoader::WillFollowRedirect(
redirect_response_with_type ? *redirect_response_with_type
: redirect_response;
- // The following two calls may rewrite the new_request.Url() to
+ // The following two calls may rewrite the new_request->Url() to
// something else not for rejecting redirect but for other reasons.
// E.g. WebFrameTestClient::WillSendRequest() and
// RenderFrameImpl::WillSendRequest(). We should reflect the
- // rewriting but currently we cannot. So, compare new_request.Url() and
+ // rewriting but currently we cannot. So, compare new_request->Url() and
// new_url after calling them, and return false to make the redirect fail on
// mismatch.
WebScopedVirtualTimePauser unused_virtual_time_pauser;
+ // TODO(yoichio): Have PrepareRequest use ResourceRequestHead.
Context().PrepareRequest(*new_request, resource_->Options().initiator_info,
- unused_virtual_time_pauser,
- resource_->GetType());
+ unused_virtual_time_pauser, resource_->GetType());
+ if (RuntimeEnabledFeatures::OutOfBlinkCorsEnabled())
+ DCHECK(!new_request->HttpBody());
if (auto* observer = fetcher_->GetResourceLoadObserver()) {
observer->WillSendRequest(resource_->InspectorId(), *new_request,
redirect_response_to_pass, resource_->GetType(),
@@ -830,7 +850,7 @@ bool ResourceLoader::WillFollowRedirect(
// First-party cookie logic moved from DocumentLoader in Blink to
// net::URLRequest in the browser. Assert that Blink didn't try to change it
// to something else.
- DCHECK(KURL(new_site_for_cookies) == new_request->SiteForCookies());
+ DCHECK(new_request->SiteForCookies().IsEquivalent(new_site_for_cookies));
// The following parameters never change during the lifetime of a request.
DCHECK_EQ(new_request->GetRequestContext(), request_context);
@@ -909,7 +929,7 @@ void ResourceLoader::DidReceiveResponse(const WebURLResponse& response) {
void ResourceLoader::DidReceiveResponseInternal(
const ResourceResponse& response) {
- const ResourceRequest& request = resource_->GetResourceRequest();
+ const ResourceRequestHead& request = resource_->GetResourceRequest();
if (request.IsAutomaticUpgrade()) {
mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> pending_recorder;
@@ -932,7 +952,7 @@ void ResourceLoader::DidReceiveResponseInternal(
ResourceType resource_type = resource_->GetType();
- const ResourceRequest& initial_request = resource_->GetResourceRequest();
+ const ResourceRequestHead& initial_request = resource_->GetResourceRequest();
// The following parameters never change during the lifetime of a request.
mojom::RequestContextType request_context =
initial_request.GetRequestContext();
@@ -957,12 +977,25 @@ void ResourceLoader::DidReceiveResponseInternal(
return;
}
+ // https://wicg.github.io/cross-origin-embedder-policy/#integration-html
+ // TODO(crbug.com/1064920): Remove this once PlzDedicatedWorker ships.
+ if (options.reject_coep_unsafe_none &&
+ response.GetCrossOriginEmbedderPolicy() !=
+ network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp &&
+ !response.CurrentRequestUrl().ProtocolIsData() &&
+ !response.CurrentRequestUrl().ProtocolIs("blob")) {
+ DCHECK(!base::FeatureList::IsEnabled(features::kPlzDedicatedWorker));
+ HandleError(ResourceError::Failure(response.CurrentRequestUrl()));
+ return;
+ }
+
if (response.WasFetchedViaServiceWorker()) {
if (options.cors_handling_by_resource_fetcher ==
kEnableCorsHandlingByResourceFetcher &&
request_mode == network::mojom::RequestMode::kCors &&
response.WasFallbackRequiredByServiceWorker()) {
- ResourceRequest last_request = resource_->LastResourceRequest();
+ DCHECK(resource_->RedirectChain().IsEmpty());
+ ResourceRequestHead last_request(resource_->GetResourceRequest());
DCHECK(!last_request.GetSkipServiceWorker());
// This code handles the case when a controlling service worker doesn't
// handle a cross origin request.
@@ -999,14 +1032,13 @@ void ResourceLoader::DidReceiveResponseInternal(
// CanRequest() below only checks enforced policies: check report-only
// here to ensure violations are sent.
Context().CheckCSPForRequest(
- request_context, response_url, options,
- SecurityViolationReportingPolicy::kReport,
+ request_context, response_url, options, ReportingDisposition::kReport,
ResourceRequest::RedirectStatus::kFollowedRedirect);
base::Optional<ResourceRequestBlockedReason> blocked_reason =
Context().CanRequest(
- resource_type, initial_request, response_url, options,
- SecurityViolationReportingPolicy::kReport,
+ resource_type, ResourceRequest(initial_request), response_url,
+ options, ReportingDisposition::kReport,
ResourceRequest::RedirectStatus::kFollowedRedirect);
if (blocked_reason) {
HandleError(ResourceError::CancelledDueToAccessCheckError(
@@ -1021,9 +1053,8 @@ void ResourceLoader::DidReceiveResponseInternal(
!(resource_->IsCacheValidator() && response.HttpStatusCode() == 304)) {
if (GetCorsFlag()) {
base::Optional<network::CorsErrorStatus> cors_error = cors::CheckAccess(
- response.CurrentRequestUrl(), response.HttpStatusCode(),
- response.HttpHeaderFields(), initial_request.GetCredentialsMode(),
- *resource_->GetOrigin());
+ response.CurrentRequestUrl(), response.HttpHeaderFields(),
+ initial_request.GetCredentialsMode(), *resource_->GetOrigin());
if (cors_error) {
HandleError(ResourceError(response.CurrentRequestUrl(), *cors_error));
return;
@@ -1040,9 +1071,12 @@ void ResourceLoader::DidReceiveResponseInternal(
// FrameType never changes during the lifetime of a request.
if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+ ResourceRequest request_for_obserber(initial_request);
+ // TODO(yoichio): Have DidReceiveResponse take a ResourceResponseHead, not
+ // ResourceRequest.
observer->DidReceiveResponse(
- resource_->InspectorId(), initial_request, response_to_pass, resource_,
- ResourceLoadObserver::ResponseSource::kNotFromMemoryCache);
+ resource_->InspectorId(), request_for_obserber, response_to_pass,
+ resource_, ResourceLoadObserver::ResponseSource::kNotFromMemoryCache);
}
resource_->ResponseReceived(response_to_pass);
@@ -1182,7 +1216,7 @@ void ResourceLoader::DidFail(const WebURLError& error,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
- const ResourceRequest& request = resource_->GetResourceRequest();
+ const ResourceRequestHead& request = resource_->GetResourceRequest();
if (request.IsAutomaticUpgrade()) {
mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> pending_recorder;
@@ -1242,11 +1276,16 @@ void ResourceLoader::HandleError(const ResourceError& error) {
inflight_keepalive_bytes_);
}
-void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
+void ResourceLoader::RequestSynchronously(const ResourceRequestHead& request) {
DCHECK(loader_);
DCHECK_EQ(request.Priority(), ResourceLoadPriority::kHighest);
- WrappedResourceRequest request_in(request);
+ auto network_resource_request = std::make_unique<network::ResourceRequest>();
+ scoped_refptr<EncodedFormData> form_body = request_body_.FormBody();
+ PopulateResourceRequest(request, std::move(request_body_),
+ network_resource_request.get());
+ if (form_body)
+ request_body_ = ResourceRequestBody(std::move(form_body));
WebURLResponse response_out;
base::Optional<WebURLError> error_out;
WebData data_out;
@@ -1271,9 +1310,15 @@ void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
data_out = WebData(std::move(data));
}
} else {
- loader_->LoadSynchronously(request_in, this, response_out, error_out,
- data_out, encoded_data_length,
- encoded_body_length, downloaded_blob);
+ // Don't do mime sniffing for fetch (crbug.com/2016)
+ bool no_mime_sniffing =
+ request.GetRequestContext() == blink::mojom::RequestContextType::FETCH;
+ loader_->LoadSynchronously(
+ std::move(network_resource_request), request.GetExtraData(),
+ request.RequestorID(), request.IsDownloadToNetworkCacheOnly(),
+ request.DownloadToBlob(), no_mime_sniffing, request.TimeoutInterval(),
+ this, response_out, error_out, data_out, encoded_data_length,
+ encoded_body_length, downloaded_blob);
}
// A message dispatched while synchronously fetching the resource
// can bring about the cancellation of this load.
@@ -1312,7 +1357,7 @@ void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
encoded_body_length, decoded_body_length, false);
}
-void ResourceLoader::RequestAsynchronously(const ResourceRequest& request) {
+void ResourceLoader::RequestAsynchronously(const ResourceRequestHead& request) {
DCHECK(loader_);
if (CanHandleDataURLRequestLocally(request)) {
DCHECK(!code_cache_request_);
@@ -1323,7 +1368,19 @@ void ResourceLoader::RequestAsynchronously(const ResourceRequest& request) {
return;
}
- loader_->LoadAsynchronously(WrappedResourceRequest(request), this);
+ auto network_resource_request = std::make_unique<network::ResourceRequest>();
+ // Don't do mime sniffing for fetch (crbug.com/2016)
+ bool no_mime_sniffing =
+ request.GetRequestContext() == blink::mojom::RequestContextType::FETCH;
+ scoped_refptr<EncodedFormData> form_body = request_body_.FormBody();
+ PopulateResourceRequest(request, std::move(request_body_),
+ network_resource_request.get());
+ if (form_body)
+ request_body_ = ResourceRequestBody(std::move(form_body));
+ loader_->LoadAsynchronously(std::move(network_resource_request),
+ request.GetExtraData(), request.RequestorID(),
+ request.IsDownloadToNetworkCacheOnly(),
+ no_mime_sniffing, this);
if (code_cache_request_) {
// Sets defers loading and initiates a fetch from code cache.
code_cache_request_->FetchFromCodeCache(loader_.get(), this);
@@ -1346,7 +1403,7 @@ void ResourceLoader::Dispose() {
}
void ResourceLoader::ActivateCacheAwareLoadingIfNeeded(
- const ResourceRequest& request) {
+ const ResourceRequestHead& request) {
DCHECK(!is_cache_aware_loading_activated_);
if (resource_->Options().cache_aware_loading_enabled !=
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
index 0046f323f2e..ba73d21ca9d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -75,9 +75,10 @@ class PLATFORM_EXPORT ResourceLoader final
ResourceLoader(ResourceFetcher*,
ResourceLoadScheduler*,
Resource*,
+ ResourceRequestBody request_body = ResourceRequestBody(),
uint32_t inflight_keepalive_bytes = 0);
~ResourceLoader() override;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
void Start();
@@ -90,7 +91,7 @@ class PLATFORM_EXPORT ResourceLoader final
// Called before start() to activate cache-aware loading if enabled in
// |m_resource->options()| and applicable.
- void ActivateCacheAwareLoadingIfNeeded(const ResourceRequest&);
+ void ActivateCacheAwareLoadingIfNeeded(const ResourceRequestHead&);
bool IsCacheAwareLoadingActivated() const {
return is_cache_aware_loading_activated_;
@@ -113,14 +114,13 @@ class PLATFORM_EXPORT ResourceLoader final
// A failed load is indicated by 1 DidFail(), which can occur at any time
// before DidFinishLoading(), including synchronous inside one of the other
// callbacks via ResourceLoader::cancel()
- bool WillFollowRedirect(
- const WebURL& new_url,
- const WebURL& new_site_for_cookies,
- const WebString& new_referrer,
- network::mojom::ReferrerPolicy new_referrer_policy,
- const WebString& new_method,
- const WebURLResponse& passed_redirect_response,
- bool& report_raw_headers) override;
+ bool WillFollowRedirect(const WebURL& new_url,
+ const net::SiteForCookies& new_site_for_cookies,
+ const WebString& new_referrer,
+ network::mojom::ReferrerPolicy new_referrer_policy,
+ const WebString& new_method,
+ const WebURLResponse& passed_redirect_response,
+ bool& report_raw_headers) override;
void DidSendData(uint64_t bytes_sent,
uint64_t total_bytes_to_be_sent) override;
void DidReceiveResponse(const WebURLResponse&) override;
@@ -166,7 +166,7 @@ class PLATFORM_EXPORT ResourceLoader final
void DidCancelLoadingBody() override;
bool ShouldFetchCodeCache();
- void StartWith(const ResourceRequest&);
+ void StartWith(const ResourceRequestHead&);
void Release(ResourceLoadScheduler::ReleaseOption,
const ResourceLoadScheduler::TrafficReportHints&);
@@ -174,7 +174,7 @@ class PLATFORM_EXPORT ResourceLoader final
// This method is currently only used for service worker fallback request and
// cache-aware loading, other users should be careful not to break
// ResourceLoader state.
- void Restart(const ResourceRequest&);
+ void Restart(const ResourceRequestHead&);
FetchContext& Context() const;
@@ -184,8 +184,8 @@ class PLATFORM_EXPORT ResourceLoader final
void CancelForRedirectAccessCheckError(const KURL&,
ResourceRequestBlockedReason);
- void RequestSynchronously(const ResourceRequest&);
- void RequestAsynchronously(const ResourceRequest&);
+ void RequestSynchronously(const ResourceRequestHead&);
+ void RequestAsynchronously(const ResourceRequestHead&);
void Dispose();
void DidReceiveResponseInternal(const ResourceResponse&);
@@ -211,6 +211,7 @@ class PLATFORM_EXPORT ResourceLoader final
Member<ResourceFetcher> fetcher_;
Member<ResourceLoadScheduler> scheduler_;
Member<Resource> resource_;
+ ResourceRequestBody request_body_;
Member<ResponseBodyLoader> response_body_loader_;
Member<DataPipeBytesConsumer::CompletionNotifier>
data_pipe_completion_notifier_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
index 16769297a2d..b074e42e062 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
@@ -91,17 +91,30 @@ class ResourceLoaderDefersLoadingTest::TestWebURLLoader final
: defers_flag_ptr_(defers_flag_ptr) {}
~TestWebURLLoader() override = default;
- void LoadSynchronously(const WebURLRequest&,
- WebURLLoaderClient*,
- WebURLResponse&,
- base::Optional<WebURLError>&,
- WebData&,
- int64_t& encoded_data_length,
- int64_t& encoded_body_length,
- WebBlobInfo& downloaded_blob) override {
+ void LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient*,
+ WebURLResponse&,
+ base::Optional<WebURLError>&,
+ WebData&,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ WebBlobInfo& downloaded_blob) override {
NOTREACHED();
}
- void LoadAsynchronously(const WebURLRequest&, WebURLLoaderClient*) override {}
+ void LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool no_mime_sniffing,
+ WebURLLoaderClient*) override {}
void SetDefersLoading(bool defers) override { *defers_flag_ptr_ = defers; }
void DidChangePriority(WebURLRequest::Priority, int) override {
@@ -177,7 +190,7 @@ TEST_F(ResourceLoaderDefersLoadingTest, CodeCacheFetchCheckDefers) {
ResourceRequest request;
request.SetUrl(test_url_);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
@@ -200,7 +213,7 @@ TEST_F(ResourceLoaderDefersLoadingTest, CodeCacheFetchSyncReturn) {
ResourceRequest request;
request.SetUrl(test_url_);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
DCHECK(resource);
@@ -214,7 +227,7 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToFalse) {
ResourceRequest request;
request.SetUrl(test_url_);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
DCHECK(web_url_loader_defers_);
@@ -232,7 +245,7 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersToTrue) {
ResourceRequest request;
request.SetUrl(test_url_);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
DCHECK(web_url_loader_defers_);
@@ -254,7 +267,7 @@ TEST_F(ResourceLoaderDefersLoadingTest, ChangeDefersMultipleTimes) {
request.SetUrl(test_url_);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
DCHECK(web_url_loader_defers_);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
index df25cab69b1..cb2c29d1c77 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
@@ -36,7 +36,7 @@ namespace blink {
ResourceLoaderOptions::ResourceLoaderOptions()
: data_buffering_policy(kBufferData),
- content_security_policy_option(kCheckContentSecurityPolicy),
+ content_security_policy_option(network::mojom::CSPDisposition::CHECK),
request_initiator_context(kDocumentContext),
synchronous_policy(kRequestAsynchronously),
cors_handling_by_resource_fetcher(kEnableCorsHandlingByResourceFetcher),
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
index b233ca5deed..8cc09706c37 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
@@ -32,7 +32,9 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOADER_OPTIONS_H_
#include "base/memory/scoped_refptr.h"
+#include "base/util/type_safety/strong_alias.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
@@ -44,11 +46,6 @@ namespace blink {
enum DataBufferingPolicy : uint8_t { kBufferData, kDoNotBufferData };
-enum ContentSecurityPolicyDisposition : uint8_t {
- kCheckContentSecurityPolicy,
- kDoNotCheckContentSecurityPolicy
-};
-
enum RequestInitiatorContext : uint8_t {
kDocumentContext,
kWorkerContext,
@@ -75,6 +72,12 @@ enum CacheAwareLoadingEnabled : uint8_t {
kIsCacheAwareLoadingEnabled
};
+// https://github.com/WICG/cross-origin-embedder-policy/pull/13
+// When true, a response is blocked unless it has
+// cross-origin-embedder-policy: require-corp.
+using RejectCoepUnsafeNone =
+ util::StrongAlias<class RejectCoepUnsafeNoneTag, bool>;
+
// This class is thread-bound. Do not copy/pass an instance across threads.
struct PLATFORM_EXPORT ResourceLoaderOptions {
USING_FAST_MALLOC(ResourceLoaderOptions);
@@ -93,7 +96,7 @@ struct PLATFORM_EXPORT ResourceLoaderOptions {
DataBufferingPolicy data_buffering_policy;
- ContentSecurityPolicyDisposition content_security_policy_option;
+ network::mojom::CSPDisposition content_security_policy_option;
RequestInitiatorContext request_initiator_context;
SynchronousPolicy synchronous_policy;
@@ -105,6 +108,9 @@ struct PLATFORM_EXPORT ResourceLoaderOptions {
// Corresponds to the CORS flag in the Fetch spec.
bool cors_flag;
+ // TODO(crbug.com/1064920): Remove this once PlzDedicatedWorker ships.
+ RejectCoepUnsafeNone reject_coep_unsafe_none = RejectCoepUnsafeNone(false);
+
String content_security_policy_nonce;
IntegrityMetadataSet integrity_metadata;
ParserDisposition parser_disposition;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
index 9a88c03ab81..7d307cefc7c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
@@ -75,21 +75,34 @@ class ResourceLoaderTest : public testing::Test {
private:
class NoopWebURLLoader final : public WebURLLoader {
public:
- NoopWebURLLoader(scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ explicit NoopWebURLLoader(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(task_runner) {}
~NoopWebURLLoader() override = default;
- void LoadSynchronously(const WebURLRequest&,
- WebURLLoaderClient*,
- WebURLResponse&,
- base::Optional<WebURLError>&,
- WebData&,
- int64_t& encoded_data_length,
- int64_t& encoded_body_length,
- WebBlobInfo& downloaded_blob) override {
+ void LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient*,
+ WebURLResponse&,
+ base::Optional<WebURLError>&,
+ WebData&,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ WebBlobInfo& downloaded_blob) override {
NOTREACHED();
}
- void LoadAsynchronously(const WebURLRequest&,
- WebURLLoaderClient*) override {}
+ void LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool no_mime_sniffing,
+ WebURLLoaderClient*) override {}
void SetDefersLoading(bool) override {}
void DidChangePriority(WebURLRequest::Priority, int) override {
@@ -182,7 +195,7 @@ TEST_F(ResourceLoaderTest, ResponseType) {
request.SetMode(test.request_mode);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
if (test.request_mode == network::mojom::RequestMode::kCors) {
fetch_parameters.SetCrossOriginAccessControl(
origin.get(), network::mojom::CredentialsMode::kOmit);
@@ -216,7 +229,7 @@ TEST_F(ResourceLoaderTest, LoadResponseBody) {
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
Resource* resource = RawResource::Fetch(params, fetcher, nullptr);
ResourceLoader* loader = resource->Loader();
@@ -280,7 +293,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndNonStream) {
KURL url("data:text/plain,Hello%20World!");
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
Resource* resource = RawResource::Fetch(params, fetcher, nullptr);
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get())
@@ -338,7 +351,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndStream) {
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
request.SetUseStreamOnResponse(true);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
auto* raw_resource_client = MakeGarbageCollected<TestRawResourceClient>();
Resource* resource = RawResource::Fetch(params, fetcher, raw_resource_client);
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
@@ -374,7 +387,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncEmptyData) {
KURL url("data:text/html,");
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
Resource* resource = RawResource::Fetch(params, fetcher, nullptr);
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get())
@@ -397,7 +410,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_Sync) {
KURL url("data:text/plain,Hello%20World!");
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
Resource* resource =
RawResource::FetchSynchronously(params, fetcher, nullptr);
@@ -422,7 +435,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_SyncEmptyData) {
KURL url("data:text/html,");
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
Resource* resource =
RawResource::FetchSynchronously(params, fetcher, nullptr);
@@ -445,7 +458,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndNonStream) {
KURL url("data:text/plain,Hello%20World!");
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
Resource* resource = RawResource::Fetch(params, fetcher, nullptr);
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
@@ -492,7 +505,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndStream) {
ResourceRequest request(url);
request.SetRequestContext(mojom::RequestContextType::FETCH);
request.SetUseStreamOnResponse(true);
- FetchParameters params(request);
+ FetchParameters params(std::move(request));
auto* raw_resource_client = MakeGarbageCollected<TestRawResourceClient>();
Resource* resource = RawResource::Fetch(params, fetcher, raw_resource_client);
EXPECT_EQ(resource->GetStatus(), ResourceStatus::kPending);
@@ -561,7 +574,7 @@ class ResourceLoaderIsolatedCodeCacheTest : public ResourceLoaderTest {
request.SetUrl(foo_url_);
request.SetRequestContext(mojom::RequestContextType::FETCH);
- FetchParameters fetch_parameters(request);
+ FetchParameters fetch_parameters(std::move(request));
Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
ResourceLoader* loader = resource->Loader();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index b36dbcf738b..8ee020a6df7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -40,15 +40,12 @@
namespace blink {
-const base::TimeDelta ResourceRequest::default_timeout_interval_ =
+const base::TimeDelta ResourceRequestHead::default_timeout_interval_ =
base::TimeDelta::Max();
-ResourceRequest::ResourceRequest() : ResourceRequest(NullURL()) {}
+ResourceRequestHead::ResourceRequestHead() : ResourceRequestHead(NullURL()) {}
-ResourceRequest::ResourceRequest(const String& url_string)
- : ResourceRequest(KURL(url_string)) {}
-
-ResourceRequest::ResourceRequest(const KURL& url)
+ResourceRequestHead::ResourceRequestHead(const KURL& url)
: url_(url),
timeout_interval_(default_timeout_interval_),
http_method_(http_names::kGET),
@@ -64,33 +61,86 @@ ResourceRequest::ResourceRequest(const KURL& url)
cache_mode_(mojom::FetchCacheMode::kDefault),
skip_service_worker_(false),
download_to_cache_only_(false),
+ site_for_cookies_set_(false),
priority_(ResourceLoadPriority::kUnresolved),
intra_priority_value_(0),
requestor_id_(0),
previews_state_(WebURLRequest::kPreviewsUnspecified),
request_context_(mojom::RequestContextType::UNSPECIFIED),
+ destination_(network::mojom::RequestDestination::kEmpty),
mode_(network::mojom::RequestMode::kNoCors),
fetch_importance_mode_(mojom::FetchImportanceMode::kImportanceAuto),
credentials_mode_(network::mojom::CredentialsMode::kInclude),
redirect_mode_(network::mojom::RedirectMode::kFollow),
referrer_string_(Referrer::ClientReferrerString()),
referrer_policy_(network::mojom::ReferrerPolicy::kDefault),
- did_set_http_referrer_(false),
is_external_request_(false),
cors_preflight_policy_(
network::mojom::CorsPreflightPolicy::kConsiderPreflight),
redirect_status_(RedirectStatus::kNoRedirect) {}
-ResourceRequest::ResourceRequest(const ResourceRequest&) = default;
+ResourceRequestHead::ResourceRequestHead(const ResourceRequestHead&) = default;
+
+ResourceRequestHead& ResourceRequestHead::operator=(
+ const ResourceRequestHead&) = default;
+
+ResourceRequestHead::ResourceRequestHead(ResourceRequestHead&&) = default;
+
+ResourceRequestHead& ResourceRequestHead::operator=(ResourceRequestHead&&) =
+ default;
+
+ResourceRequestHead::~ResourceRequestHead() = default;
+
+ResourceRequestBody::ResourceRequestBody() : ResourceRequestBody(nullptr) {}
+
+ResourceRequestBody::ResourceRequestBody(
+ scoped_refptr<EncodedFormData> form_body)
+ : form_body_(form_body) {}
+
+ResourceRequestBody::ResourceRequestBody(ResourceRequestBody&& src)
+ : ResourceRequestBody(std::move(src.form_body_)) {}
+
+ResourceRequestBody& ResourceRequestBody::operator=(ResourceRequestBody&& src) {
+ form_body_ = std::move(src.form_body_);
+ return *this;
+}
+
+ResourceRequestBody::~ResourceRequestBody() = default;
+
+ResourceRequest::ResourceRequest() : ResourceRequestHead(NullURL()) {}
+
+ResourceRequest::ResourceRequest(const String& url_string)
+ : ResourceRequestHead(KURL(url_string)) {}
+
+ResourceRequest::ResourceRequest(const KURL& url) : ResourceRequestHead(url) {}
+
+ResourceRequest::ResourceRequest(const ResourceRequestHead& head)
+ : ResourceRequestHead(head) {}
+
+ResourceRequest& ResourceRequest::operator=(const ResourceRequest& src) {
+ this->ResourceRequestHead::operator=(src);
+ body_.SetFormBody(src.body_.FormBody());
+ return *this;
+}
+
+ResourceRequest::ResourceRequest(ResourceRequest&&) = default;
+
+ResourceRequest& ResourceRequest::operator=(ResourceRequest&&) = default;
ResourceRequest::~ResourceRequest() = default;
-ResourceRequest& ResourceRequest::operator=(const ResourceRequest&) = default;
+void ResourceRequest::CopyFrom(const ResourceRequest& src) {
+ *this = src;
+}
-std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
+void ResourceRequest::CopyHeadFrom(const ResourceRequestHead& src) {
+ this->ResourceRequestHead::operator=(src);
+}
+
+std::unique_ptr<ResourceRequest> ResourceRequestHead::CreateRedirectRequest(
const KURL& new_url,
const AtomicString& new_method,
- const KURL& new_site_for_cookies,
+ const net::SiteForCookies& new_site_for_cookies,
const String& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
bool skip_service_worker) const {
@@ -102,9 +152,8 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
request->SetSiteForCookies(new_site_for_cookies);
String referrer =
new_referrer.IsEmpty() ? Referrer::NoReferrer() : String(new_referrer);
- // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
- // header and instead use a separate member. See https://crbug.com/850813.
- request->SetHttpReferrer(Referrer(referrer, new_referrer_policy));
+ request->SetReferrerString(referrer);
+ request->SetReferrerPolicy(new_referrer_policy);
request->SetSkipServiceWorker(skip_service_worker);
request->SetRedirectStatus(RedirectStatus::kFollowedRedirect);
@@ -118,8 +167,6 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
request->SetKeepalive(GetKeepalive());
request->SetPriority(Priority());
- if (request->HttpMethod() == HttpMethod())
- request->SetHttpBody(HttpBody());
request->SetCorsPreflightPolicy(CorsPreflightPolicy());
if (IsAdResource())
request->SetIsAdResource();
@@ -138,27 +185,27 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
return request;
}
-bool ResourceRequest::IsNull() const {
+bool ResourceRequestHead::IsNull() const {
return url_.IsNull();
}
-const KURL& ResourceRequest::Url() const {
+const KURL& ResourceRequestHead::Url() const {
return url_;
}
-void ResourceRequest::SetUrl(const KURL& url) {
+void ResourceRequestHead::SetUrl(const KURL& url) {
url_ = url;
}
-const KURL& ResourceRequest::GetInitialUrlForResourceTiming() const {
+const KURL& ResourceRequestHead::GetInitialUrlForResourceTiming() const {
return initial_url_for_resource_timing_;
}
-void ResourceRequest::SetInitialUrlForResourceTiming(const KURL& url) {
+void ResourceRequestHead::SetInitialUrlForResourceTiming(const KURL& url) {
initial_url_for_resource_timing_ = url;
}
-void ResourceRequest::RemoveUserAndPassFromURL() {
+void ResourceRequestHead::RemoveUserAndPassFromURL() {
if (url_.User().IsEmpty() && url_.Pass().IsEmpty())
return;
@@ -166,155 +213,146 @@ void ResourceRequest::RemoveUserAndPassFromURL() {
url_.SetPass(String());
}
-mojom::FetchCacheMode ResourceRequest::GetCacheMode() const {
+mojom::FetchCacheMode ResourceRequestHead::GetCacheMode() const {
return cache_mode_;
}
-void ResourceRequest::SetCacheMode(mojom::FetchCacheMode cache_mode) {
+void ResourceRequestHead::SetCacheMode(mojom::FetchCacheMode cache_mode) {
cache_mode_ = cache_mode;
}
-base::TimeDelta ResourceRequest::TimeoutInterval() const {
+base::TimeDelta ResourceRequestHead::TimeoutInterval() const {
return timeout_interval_;
}
-void ResourceRequest::SetTimeoutInterval(
+void ResourceRequestHead::SetTimeoutInterval(
base::TimeDelta timout_interval_seconds) {
timeout_interval_ = timout_interval_seconds;
}
-const KURL& ResourceRequest::SiteForCookies() const {
+const net::SiteForCookies& ResourceRequestHead::SiteForCookies() const {
return site_for_cookies_;
}
-void ResourceRequest::SetSiteForCookies(const KURL& site_for_cookies) {
+void ResourceRequestHead::SetSiteForCookies(
+ const net::SiteForCookies& site_for_cookies) {
site_for_cookies_ = site_for_cookies;
+ site_for_cookies_set_ = true;
}
-const SecurityOrigin* ResourceRequest::TopFrameOrigin() const {
+const SecurityOrigin* ResourceRequestHead::TopFrameOrigin() const {
return top_frame_origin_.get();
}
-void ResourceRequest::SetTopFrameOrigin(
+void ResourceRequestHead::SetTopFrameOrigin(
scoped_refptr<const SecurityOrigin> origin) {
top_frame_origin_ = std::move(origin);
}
-const AtomicString& ResourceRequest::HttpMethod() const {
+const AtomicString& ResourceRequestHead::HttpMethod() const {
return http_method_;
}
-void ResourceRequest::SetHttpMethod(const AtomicString& http_method) {
+void ResourceRequestHead::SetHttpMethod(const AtomicString& http_method) {
http_method_ = http_method;
}
-const HTTPHeaderMap& ResourceRequest::HttpHeaderFields() const {
+const HTTPHeaderMap& ResourceRequestHead::HttpHeaderFields() const {
return http_header_fields_;
}
-const AtomicString& ResourceRequest::HttpHeaderField(
+const AtomicString& ResourceRequestHead::HttpHeaderField(
const AtomicString& name) const {
return http_header_fields_.Get(name);
}
-void ResourceRequest::SetHttpHeaderField(const AtomicString& name,
- const AtomicString& value) {
+void ResourceRequestHead::SetHttpHeaderField(const AtomicString& name,
+ const AtomicString& value) {
http_header_fields_.Set(name, value);
}
-void ResourceRequest::SetHttpReferrer(const Referrer& referrer) {
- if (referrer.referrer.IsEmpty())
- http_header_fields_.Remove(http_names::kReferer);
- else
- SetHttpHeaderField(http_names::kReferer, referrer.referrer);
- referrer_policy_ = referrer.referrer_policy;
- did_set_http_referrer_ = true;
-}
-
-void ResourceRequest::ClearHTTPReferrer() {
- http_header_fields_.Remove(http_names::kReferer);
- referrer_policy_ = network::mojom::ReferrerPolicy::kDefault;
- did_set_http_referrer_ = false;
-}
-
-void ResourceRequest::SetHTTPOrigin(const SecurityOrigin* origin) {
+void ResourceRequestHead::SetHTTPOrigin(const SecurityOrigin* origin) {
SetHttpHeaderField(http_names::kOrigin, origin->ToAtomicString());
}
-void ResourceRequest::ClearHTTPOrigin() {
+void ResourceRequestHead::ClearHTTPOrigin() {
http_header_fields_.Remove(http_names::kOrigin);
}
-void ResourceRequest::SetHttpOriginIfNeeded(const SecurityOrigin* origin) {
+void ResourceRequestHead::SetHttpOriginIfNeeded(const SecurityOrigin* origin) {
if (NeedsHTTPOrigin())
SetHTTPOrigin(origin);
}
-void ResourceRequest::SetHTTPOriginToMatchReferrerIfNeeded() {
+void ResourceRequestHead::SetHTTPOriginToMatchReferrerIfNeeded() {
if (NeedsHTTPOrigin()) {
- SetHTTPOrigin(
- SecurityOrigin::CreateFromString(HttpHeaderField(http_names::kReferer))
- .get());
+ SetHTTPOrigin(SecurityOrigin::CreateFromString(ReferrerString()).get());
}
}
-void ResourceRequest::ClearHTTPUserAgent() {
+void ResourceRequestHead::ClearHTTPUserAgent() {
http_header_fields_.Remove(http_names::kUserAgent);
}
-EncodedFormData* ResourceRequest::HttpBody() const {
- return http_body_.get();
+void ResourceRequestBody::SetFormBody(
+ scoped_refptr<EncodedFormData> form_body) {
+ form_body_ = std::move(form_body);
+}
+
+const scoped_refptr<EncodedFormData>& ResourceRequest::HttpBody() const {
+ return body_.FormBody();
}
void ResourceRequest::SetHttpBody(scoped_refptr<EncodedFormData> http_body) {
- http_body_ = std::move(http_body);
+ body_.SetFormBody(std::move(http_body));
}
-bool ResourceRequest::AllowStoredCredentials() const {
+bool ResourceRequestHead::AllowStoredCredentials() const {
return allow_stored_credentials_;
}
-void ResourceRequest::SetAllowStoredCredentials(bool allow_credentials) {
+void ResourceRequestHead::SetAllowStoredCredentials(bool allow_credentials) {
allow_stored_credentials_ = allow_credentials;
}
-ResourceLoadPriority ResourceRequest::Priority() const {
+ResourceLoadPriority ResourceRequestHead::Priority() const {
return priority_;
}
-int ResourceRequest::IntraPriorityValue() const {
+int ResourceRequestHead::IntraPriorityValue() const {
return intra_priority_value_;
}
-bool ResourceRequest::PriorityHasBeenSet() const {
+bool ResourceRequestHead::PriorityHasBeenSet() const {
return priority_ != ResourceLoadPriority::kUnresolved;
}
-void ResourceRequest::SetPriority(ResourceLoadPriority priority,
- int intra_priority_value) {
+void ResourceRequestHead::SetPriority(ResourceLoadPriority priority,
+ int intra_priority_value) {
priority_ = priority;
intra_priority_value_ = intra_priority_value;
}
-void ResourceRequest::AddHttpHeaderField(const AtomicString& name,
- const AtomicString& value) {
+void ResourceRequestHead::AddHttpHeaderField(const AtomicString& name,
+ const AtomicString& value) {
HTTPHeaderMap::AddResult result = http_header_fields_.Add(name, value);
if (!result.is_new_entry)
result.stored_value->value = result.stored_value->value + ", " + value;
}
-void ResourceRequest::AddHTTPHeaderFields(const HTTPHeaderMap& header_fields) {
+void ResourceRequestHead::AddHTTPHeaderFields(
+ const HTTPHeaderMap& header_fields) {
HTTPHeaderMap::const_iterator end = header_fields.end();
for (HTTPHeaderMap::const_iterator it = header_fields.begin(); it != end;
++it)
AddHttpHeaderField(it->key, it->value);
}
-void ResourceRequest::ClearHttpHeaderField(const AtomicString& name) {
+void ResourceRequestHead::ClearHttpHeaderField(const AtomicString& name) {
http_header_fields_.Remove(name);
}
-void ResourceRequest::SetExternalRequestStateFromRequestorAddressSpace(
+void ResourceRequestHead::SetExternalRequestStateFromRequestorAddressSpace(
network::mojom::IPAddressSpace requestor_space) {
static_assert(network::mojom::IPAddressSpace::kLocal <
network::mojom::IPAddressSpace::kPrivate,
@@ -344,7 +382,7 @@ void ResourceRequest::SetExternalRequestStateFromRequestorAddressSpace(
is_external_request_ = requestor_space > target_space;
}
-bool ResourceRequest::IsConditional() const {
+bool ResourceRequestHead::IsConditional() const {
return (http_header_fields_.Contains(http_names::kIfMatch) ||
http_header_fields_.Contains(http_names::kIfModifiedSince) ||
http_header_fields_.Contains(http_names::kIfNoneMatch) ||
@@ -352,11 +390,11 @@ bool ResourceRequest::IsConditional() const {
http_header_fields_.Contains(http_names::kIfUnmodifiedSince));
}
-void ResourceRequest::SetHasUserGesture(bool has_user_gesture) {
+void ResourceRequestHead::SetHasUserGesture(bool has_user_gesture) {
has_user_gesture_ |= has_user_gesture;
}
-bool ResourceRequest::CanDisplay(const KURL& url) const {
+bool ResourceRequestHead::CanDisplay(const KURL& url) const {
if (RequestorOrigin()->CanDisplay(url))
return true;
@@ -366,7 +404,7 @@ bool ResourceRequest::CanDisplay(const KURL& url) const {
return false;
}
-const CacheControlHeader& ResourceRequest::GetCacheControlHeader() const {
+const CacheControlHeader& ResourceRequestHead::GetCacheControlHeader() const {
if (!cache_control_header_cache_.parsed) {
cache_control_header_cache_ = ParseCacheControlDirectives(
http_header_fields_.Get(http_names::kCacheControl),
@@ -375,20 +413,20 @@ const CacheControlHeader& ResourceRequest::GetCacheControlHeader() const {
return cache_control_header_cache_;
}
-bool ResourceRequest::CacheControlContainsNoCache() const {
+bool ResourceRequestHead::CacheControlContainsNoCache() const {
return GetCacheControlHeader().contains_no_cache;
}
-bool ResourceRequest::CacheControlContainsNoStore() const {
+bool ResourceRequestHead::CacheControlContainsNoStore() const {
return GetCacheControlHeader().contains_no_store;
}
-bool ResourceRequest::HasCacheValidatorFields() const {
+bool ResourceRequestHead::HasCacheValidatorFields() const {
return !http_header_fields_.Get(http_names::kLastModified).IsEmpty() ||
!http_header_fields_.Get(http_names::kETag).IsEmpty();
}
-bool ResourceRequest::NeedsHTTPOrigin() const {
+bool ResourceRequestHead::NeedsHTTPOrigin() const {
if (!HttpOrigin().IsEmpty())
return false; // Request already has an Origin header.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index 4148460ef54..71139b093a3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -34,10 +34,12 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
+#include "net/cookies/site_for_cookies.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/cors.mojom-blink-forward.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
+#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -52,36 +54,34 @@
namespace blink {
class EncodedFormData;
-struct Referrer;
-// A ResourceRequest is a "request" object for ResourceLoader. Conceptually
-// it is https://fetch.spec.whatwg.org/#concept-request, but it contains
-// a lot of blink specific fields. WebURLRequest is the "public version"
-// of this class and WebURLLoader needs it. See WebURLRequest and
-// WrappedResourceRequest.
-//
-// This class is thread-bound. Do not copy/pass an instance across threads.
-class PLATFORM_EXPORT ResourceRequest final {
- USING_FAST_MALLOC(ResourceRequest);
+// ResourceRequestHead represents request without request body.
+// See ResourceRequest below to see what request is.
+// ResourceRequestHead is implicitly copyable while ResourceRequest is not.
+// TODO(yoichio) : Migrate existing ResourceRequest occurrence not using request
+// body to ResourceRequestHead.
+class PLATFORM_EXPORT ResourceRequestHead {
+ DISALLOW_NEW();
public:
enum class RedirectStatus : uint8_t { kFollowedRedirect, kNoRedirect };
- ResourceRequest();
- explicit ResourceRequest(const String& url_string);
- explicit ResourceRequest(const KURL&);
+ ResourceRequestHead();
+ explicit ResourceRequestHead(const KURL&);
- // TODO(toyoshim): Use std::unique_ptr as much as possible, and hopefully
- // make ResourceRequest DISALLOW_COPY_AND_ASSIGN. See crbug.com/787704.
- ResourceRequest(const ResourceRequest&);
- ResourceRequest& operator=(const ResourceRequest&);
+ ResourceRequestHead(const ResourceRequestHead&);
+ ResourceRequestHead& operator=(const ResourceRequestHead&);
+ ResourceRequestHead(ResourceRequestHead&&);
+ ResourceRequestHead& operator=(ResourceRequestHead&&);
- ~ResourceRequest();
+ ~ResourceRequestHead();
// Constructs a new ResourceRequest for a redirect from this instance.
+ // Since body for a redirect request is kept and handled in the network
+ // service, the returned instance here in blink side doesn't contain body.
std::unique_ptr<ResourceRequest> CreateRedirectRequest(
const KURL& new_url,
const AtomicString& new_method,
- const KURL& new_site_for_cookies,
+ const net::SiteForCookies& new_site_for_cookies,
const String& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
bool skip_service_worker) const;
@@ -107,8 +107,12 @@ class PLATFORM_EXPORT ResourceRequest final {
base::TimeDelta TimeoutInterval() const;
void SetTimeoutInterval(base::TimeDelta);
- const KURL& SiteForCookies() const;
- void SetSiteForCookies(const KURL&);
+ const net::SiteForCookies& SiteForCookies() const;
+ void SetSiteForCookies(const net::SiteForCookies&);
+
+ // Returns true if SiteForCookies() was set either via SetSiteForCookies or
+ // CreateRedirectRequest.
+ bool SiteForCookiesSet() const { return site_for_cookies_set_; }
const SecurityOrigin* TopFrameOrigin() const;
void SetTopFrameOrigin(scoped_refptr<const SecurityOrigin>);
@@ -151,16 +155,6 @@ class PLATFORM_EXPORT ResourceRequest final {
SetHttpHeaderField(http_names::kContentType, http_content_type);
}
- // TODO(domfarolino): Remove this once we stop storing the generated referrer
- // as a header, and instead use a separate member. See
- // https://crbug.com/850813.
- const AtomicString& HttpReferrer() const {
- return HttpHeaderField(http_names::kReferer);
- }
- void SetHttpReferrer(const Referrer&);
- bool DidSetHttpReferrer() const { return did_set_http_referrer_; }
- void ClearHTTPReferrer();
-
void SetReferrerPolicy(network::mojom::ReferrerPolicy referrer_policy) {
referrer_policy_ = referrer_policy;
}
@@ -190,9 +184,6 @@ class PLATFORM_EXPORT ResourceRequest final {
SetHttpHeaderField(http_names::kAccept, http_accept);
}
- EncodedFormData* HttpBody() const;
- void SetHttpBody(scoped_refptr<EncodedFormData>);
-
bool AllowStoredCredentials() const;
void SetAllowStoredCredentials(bool allow_credentials);
@@ -256,16 +247,11 @@ class PLATFORM_EXPORT ResourceRequest final {
}
// Extra data associated with this request.
- WebURLRequest::ExtraData* GetExtraData() const {
- return sharable_extra_data_ ? sharable_extra_data_->data.get() : nullptr;
+ const scoped_refptr<WebURLRequest::ExtraData>& GetExtraData() const {
+ return extra_data_;
}
- void SetExtraData(std::unique_ptr<WebURLRequest::ExtraData> extra_data) {
- if (extra_data) {
- sharable_extra_data_ =
- base::MakeRefCounted<SharableExtraData>(std::move(extra_data));
- } else {
- sharable_extra_data_ = nullptr;
- }
+ void SetExtraData(scoped_refptr<WebURLRequest::ExtraData> extra_data) {
+ extra_data_ = extra_data;
}
bool IsDownloadToNetworkCacheOnly() const { return download_to_cache_only_; }
@@ -281,6 +267,13 @@ class PLATFORM_EXPORT ResourceRequest final {
request_context_ = context;
}
+ network::mojom::RequestDestination GetRequestDestination() const {
+ return destination_;
+ }
+ void SetRequestDestination(network::mojom::RequestDestination destination) {
+ destination_ = destination;
+ }
+
network::mojom::RequestMode GetMode() const { return mode_; }
void SetMode(network::mojom::RequestMode mode) { mode_ = mode; }
@@ -448,14 +441,20 @@ class PLATFORM_EXPORT ResourceRequest final {
prefetch_maybe_for_top_level_navigation;
}
+ const base::Optional<network::mojom::blink::TrustTokenParams>&
+ TrustTokenParams() const {
+ return trust_token_params_;
+ }
+ void SetTrustTokenParams(
+ base::Optional<network::mojom::blink::TrustTokenParams> params) {
+ trust_token_params_ = std::move(params);
+ }
+
// Whether either RequestorOrigin or IsolatedWorldOrigin can display the
// |url|,
bool CanDisplay(const KURL&) const;
private:
- using SharableExtraData =
- base::RefCountedData<std::unique_ptr<WebURLRequest::ExtraData>>;
-
const CacheControlHeader& GetCacheControlHeader() const;
bool NeedsHTTPOrigin() const;
@@ -467,7 +466,7 @@ class PLATFORM_EXPORT ResourceRequest final {
// base::TimeDelta::Max() represents the default timeout on platforms that
// have one.
base::TimeDelta timeout_interval_;
- KURL site_for_cookies_;
+ net::SiteForCookies site_for_cookies_;
scoped_refptr<const SecurityOrigin> top_frame_origin_;
scoped_refptr<const SecurityOrigin> requestor_origin_;
@@ -475,7 +474,6 @@ class PLATFORM_EXPORT ResourceRequest final {
AtomicString http_method_;
HTTPHeaderMap http_header_fields_;
- scoped_refptr<EncodedFormData> http_body_;
bool allow_stored_credentials_ : 1;
bool report_upload_progress_ : 1;
bool report_raw_headers_ : 1;
@@ -488,12 +486,14 @@ class PLATFORM_EXPORT ResourceRequest final {
mojom::FetchCacheMode cache_mode_;
bool skip_service_worker_ : 1;
bool download_to_cache_only_ : 1;
+ bool site_for_cookies_set_ : 1;
ResourceLoadPriority priority_;
int intra_priority_value_;
int requestor_id_;
WebURLRequest::PreviewsState previews_state_;
- scoped_refptr<SharableExtraData> sharable_extra_data_;
+ scoped_refptr<WebURLRequest::ExtraData> extra_data_;
mojom::RequestContextType request_context_;
+ network::mojom::RequestDestination destination_;
network::mojom::RequestMode mode_;
mojom::FetchImportanceMode fetch_importance_mode_;
network::mojom::CredentialsMode credentials_mode_;
@@ -501,10 +501,10 @@ class PLATFORM_EXPORT ResourceRequest final {
String fetch_integrity_;
String referrer_string_;
network::mojom::ReferrerPolicy referrer_policy_;
- bool did_set_http_referrer_;
bool is_external_request_;
network::mojom::CorsPreflightPolicy cors_preflight_policy_;
RedirectStatus redirect_status_;
+ base::Optional<network::mojom::blink::TrustTokenParams> trust_token_params_;
base::Optional<String> suggested_filename_;
@@ -547,6 +547,70 @@ class PLATFORM_EXPORT ResourceRequest final {
base::Optional<base::UnguessableToken> recursive_prefetch_token_;
};
+class PLATFORM_EXPORT ResourceRequestBody {
+ public:
+ ResourceRequestBody();
+ explicit ResourceRequestBody(scoped_refptr<EncodedFormData> form_body);
+ ResourceRequestBody(const ResourceRequestBody&) = delete;
+ ResourceRequestBody(ResourceRequestBody&&);
+
+ ResourceRequestBody& operator=(const ResourceRequestBody&) = delete;
+ ResourceRequestBody& operator=(ResourceRequestBody&&);
+
+ ~ResourceRequestBody();
+
+ const scoped_refptr<EncodedFormData>& FormBody() const { return form_body_; }
+ void SetFormBody(scoped_refptr<EncodedFormData>);
+
+ private:
+ scoped_refptr<EncodedFormData> form_body_;
+};
+
+// A ResourceRequest is a "request" object for ResourceLoader. Conceptually
+// it is https://fetch.spec.whatwg.org/#concept-request, but it contains
+// a lot of blink specific fields. WebURLRequest is the "public version"
+// of this class and WebURLLoader needs it. See WebURLRequest and
+// WrappedResourceRequest.
+//
+// This class is thread-bound. Do not copy/pass an instance across threads.
+//
+// Although request consists head and body, ResourceRequest is implemented by
+// inheriting ResourceRequestHead due in order to make it possible to use
+// property accessors through both ResourceRequestHead and ResourceRequest while
+// avoiding duplicate accessor definitions.
+// For those who want to add a new property in request, please implement its
+// member and accessors in ResourceRequestHead instead of ResourceRequest.
+class PLATFORM_EXPORT ResourceRequest final : public ResourceRequestHead {
+ USING_FAST_MALLOC(ResourceRequest);
+
+ public:
+ ResourceRequest();
+ explicit ResourceRequest(const String& url_string);
+ explicit ResourceRequest(const KURL&);
+ explicit ResourceRequest(const ResourceRequestHead&);
+
+ ResourceRequest(const ResourceRequest&) = delete;
+ ResourceRequest(ResourceRequest&&);
+ ResourceRequest& operator=(ResourceRequest&&);
+
+ ~ResourceRequest();
+
+ // TODO(yoichio): Use move semantics as much as possible.
+ // See crbug.com/787704.
+ void CopyFrom(const ResourceRequest&);
+ void CopyHeadFrom(const ResourceRequestHead&);
+
+ const scoped_refptr<EncodedFormData>& HttpBody() const;
+ void SetHttpBody(scoped_refptr<EncodedFormData>);
+
+ ResourceRequestBody& MutableBody() { return body_; }
+
+ private:
+ ResourceRequest& operator=(const ResourceRequest&);
+
+ ResourceRequestBody body_;
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_REQUEST_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
index ffb5fbcea4d..cde5b01c787 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
@@ -33,7 +33,7 @@ TEST(ResourceRequestTest, SetIsAdResource) {
std::unique_ptr<ResourceRequest> redirect_request =
original.CreateRedirectRequest(
KURL("https://example.test/redirect"), original.HttpMethod(),
- original.SiteForCookies(), original.HttpReferrer(),
+ original.SiteForCookies(), original.ReferrerString(),
original.GetReferrerPolicy(), original.GetSkipServiceWorker());
EXPECT_TRUE(redirect_request->IsAdResource());
}
@@ -48,7 +48,7 @@ TEST(ResourceRequestTest, UpgradeIfInsecureAcrossRedirects) {
std::unique_ptr<ResourceRequest> redirect_request =
original.CreateRedirectRequest(
KURL("https://example.test/redirect"), original.HttpMethod(),
- original.SiteForCookies(), original.HttpReferrer(),
+ original.SiteForCookies(), original.ReferrerString(),
original.GetReferrerPolicy(), original.GetSkipServiceWorker());
EXPECT_TRUE(redirect_request->UpgradeIfInsecure());
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
index e7a8fbad67f..f7848a110e7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -31,6 +31,7 @@
#include <memory>
#include <string>
+#include "net/http/structured_headers.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_response.h"
@@ -207,16 +208,16 @@ void ResourceResponse::UpdateHeaderParsedState(const AtomicString& name) {
static const char kExpiresHeader[] = "expires";
static const char kLastModifiedHeader[] = "last-modified";
- if (DeprecatedEqualIgnoringCase(name, kAgeHeader))
+ if (EqualIgnoringASCIICase(name, kAgeHeader))
have_parsed_age_header_ = false;
- else if (DeprecatedEqualIgnoringCase(name, kCacheControlHeader) ||
- DeprecatedEqualIgnoringCase(name, kPragmaHeader))
+ else if (EqualIgnoringASCIICase(name, kCacheControlHeader) ||
+ EqualIgnoringASCIICase(name, kPragmaHeader))
cache_control_header_ = CacheControlHeader();
- else if (DeprecatedEqualIgnoringCase(name, kDateHeader))
+ else if (EqualIgnoringASCIICase(name, kDateHeader))
have_parsed_date_header_ = false;
- else if (DeprecatedEqualIgnoringCase(name, kExpiresHeader))
+ else if (EqualIgnoringASCIICase(name, kExpiresHeader))
have_parsed_expires_header_ = false;
- else if (DeprecatedEqualIgnoringCase(name, kLastModifiedHeader))
+ else if (EqualIgnoringASCIICase(name, kLastModifiedHeader))
have_parsed_last_modified_header_ = false;
}
@@ -415,7 +416,7 @@ bool ResourceResponse::IsAttachment() const {
if (loc != kNotFound)
value = value.Left(loc);
value = value.StripWhiteSpace();
- return DeprecatedEqualIgnoringCase(value, kAttachmentString);
+ return EqualIgnoringASCIICase(value, kAttachmentString);
}
AtomicString ResourceResponse::HttpContentType() const {
@@ -489,6 +490,19 @@ void ResourceResponse::SetDecodedBodyLength(int64_t value) {
decoded_body_length_ = value;
}
+network::mojom::CrossOriginEmbedderPolicyValue
+ResourceResponse::GetCrossOriginEmbedderPolicy() const {
+ static constexpr char kHeaderName[] = "cross-origin-embedder-policy";
+ const std::string value = HttpHeaderField(kHeaderName).Utf8();
+ using Item = net::structured_headers::Item;
+ const auto item = net::structured_headers::ParseItem(value);
+ if (!item || item->item.Type() != Item::kTokenType ||
+ item->item.GetString() != "require-corp") {
+ return network::mojom::CrossOriginEmbedderPolicyValue::kNone;
+ }
+ return network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
+}
+
STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersionUnknown,
ResourceResponse::kHTTPVersionUnknown);
STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_0_9,
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
index 9ba1090ee2e..4028c6341d2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -33,6 +33,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/time/time.h"
+#include "services/network/public/mojom/cross_origin_embedder_policy.mojom-shared.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
@@ -282,6 +283,9 @@ class PLATFORM_EXPORT ResourceResponse final {
bool IsLegacyTLSVersion() const { return is_legacy_tls_version_; }
void SetIsLegacyTLSVersion(bool value) { is_legacy_tls_version_ = value; }
+ bool TimingAllowPassed() const { return timing_allow_passed_; }
+ void SetTimingAllowPassed(bool value) { timing_allow_passed_ = value; }
+
SecurityStyle GetSecurityStyle() const { return security_style_; }
void SetSecurityStyle(SecurityStyle security_style) {
security_style_ = security_style;
@@ -465,6 +469,9 @@ class PLATFORM_EXPORT ResourceResponse final {
was_in_prefetch_cache_ = was_in_prefetch_cache;
}
+ network::mojom::CrossOriginEmbedderPolicyValue GetCrossOriginEmbedderPolicy()
+ const;
+
private:
void UpdateHeaderParsedState(const AtomicString& name);
@@ -504,6 +511,10 @@ class PLATFORM_EXPORT ResourceResponse final {
// will be removed in the future.
bool is_legacy_tls_version_ = false;
+ // True if the Timing-Allow-Origin check passes.
+ // https://fetch.spec.whatwg.org/#concept-response-timing-allow-passed
+ bool timing_allow_passed_ = false;
+
// The time at which the resource's certificate expires. Null if there was no
// certificate.
base::Time cert_validity_start_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
index 599ec997269..4353c202b8a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
@@ -575,4 +575,11 @@ TEST(ResourceTest, StaleWhileRevalidateCacheControlWithRedirect) {
EXPECT_TRUE(resource->StaleRevalidationRequested());
}
+// This is a regression test for https://crbug.com/1062837.
+TEST(ResourceTest, DefaultOverheadSize) {
+ const KURL url("http://127.0.0.1:8000/foo.html");
+ auto* resource = MakeGarbageCollected<MockResource>(url);
+ EXPECT_EQ(resource->CalculateOverheadSizeForTest(), resource->OverheadSize());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
index 32f53487f19..9eaba1ab7fc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
@@ -51,8 +51,10 @@ class PLATFORM_EXPORT ResourceTimingInfo
static scoped_refptr<ResourceTimingInfo> Create(
const AtomicString& type,
const base::TimeTicks time,
- mojom::RequestContextType context) {
- return base::AdoptRef(new ResourceTimingInfo(type, time, context));
+ mojom::RequestContextType context,
+ network::mojom::RequestDestination destination) {
+ return base::AdoptRef(
+ new ResourceTimingInfo(type, time, context, destination));
}
base::TimeTicks InitialTime() const { return initial_time_; }
@@ -91,6 +93,9 @@ class PLATFORM_EXPORT ResourceTimingInfo
}
bool NegativeAllowed() const { return negative_allowed_; }
mojom::RequestContextType ContextType() const { return context_type_; }
+ network::mojom::RequestDestination RequestDestination() const {
+ return request_destination_;
+ }
void SetWorkerTimingReceiver(
mojo::PendingReceiver<mojom::blink::WorkerTimingContainer>
@@ -106,12 +111,17 @@ class PLATFORM_EXPORT ResourceTimingInfo
private:
ResourceTimingInfo(const AtomicString& type,
const base::TimeTicks time,
- mojom::RequestContextType context_type)
- : type_(type), initial_time_(time), context_type_(context_type) {}
+ mojom::RequestContextType context_type,
+ network::mojom::RequestDestination request_destination)
+ : type_(type),
+ initial_time_(time),
+ context_type_(context_type),
+ request_destination_(request_destination) {}
AtomicString type_;
base::TimeTicks initial_time_;
mojom::RequestContextType context_type_;
+ network::mojom::RequestDestination request_destination_;
base::TimeTicks load_response_end_;
KURL initial_url_;
ResourceResponse final_response_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc
index 07882629bc3..33cedf848d7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.cc
@@ -4,45 +4,73 @@
#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
+#include "base/metrics/histogram_macros.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
namespace blink {
+namespace {
+
+void RecordState(StateOnGet state) {
+ UMA_HISTOGRAM_ENUMERATION("Memory.Renderer.BlinkCachedMetadataGetResult",
+ state);
+}
+
+} // namespace
+
ScriptCachedMetadataHandler::ScriptCachedMetadataHandler(
const WTF::TextEncoding& encoding,
std::unique_ptr<CachedMetadataSender> sender)
: sender_(std::move(sender)), encoding_(encoding) {}
-void ScriptCachedMetadataHandler::Trace(blink::Visitor* visitor) {
+void ScriptCachedMetadataHandler::Trace(Visitor* visitor) {
CachedMetadataHandler::Trace(visitor);
}
-void ScriptCachedMetadataHandler::SetCachedMetadata(
- uint32_t data_type_id,
- const uint8_t* data,
- size_t size,
- CachedMetadataHandler::CacheType cache_type) {
- // Currently, only one type of cached metadata per resource is supported. If
- // the need arises for multiple types of metadata per resource this could be
- // enhanced to store types of metadata in a map.
+void ScriptCachedMetadataHandler::SetCachedMetadata(uint32_t data_type_id,
+ const uint8_t* data,
+ size_t size) {
DCHECK(!cached_metadata_);
+ // Having been discarded once, the further attempts to overwrite the
+ // CachedMetadata are ignored. This behavior is slightly easier to simulate in
+ // tests. Should happen rarely enough not to affect performance. The
+ // JSModuleScript behaves similarly by preventing the creation of the code
+ // cache.
+ if (cached_metadata_discarded_)
+ return;
cached_metadata_ = CachedMetadata::Create(data_type_id, data, size);
- if (cache_type == CachedMetadataHandler::kSendToPlatform)
- SendToPlatform();
+ if (!disable_send_to_platform_for_testing_)
+ CommitToPersistentStorage();
}
void ScriptCachedMetadataHandler::ClearCachedMetadata(
- CachedMetadataHandler::CacheType cache_type) {
+ ClearCacheType cache_type) {
cached_metadata_ = nullptr;
- if (cache_type == CachedMetadataHandler::kSendToPlatform)
- SendToPlatform();
+ switch (cache_type) {
+ case kClearLocally:
+ break;
+ case kDiscardLocally:
+ cached_metadata_discarded_ = true;
+ break;
+ case kClearPersistentStorage:
+ CommitToPersistentStorage();
+ break;
+ }
}
scoped_refptr<CachedMetadata> ScriptCachedMetadataHandler::GetCachedMetadata(
uint32_t data_type_id) const {
- if (!cached_metadata_ || cached_metadata_->DataTypeID() != data_type_id)
+ if (!cached_metadata_) {
+ RecordState(cached_metadata_discarded_ ? StateOnGet::kWasDiscarded
+ : StateOnGet::kWasNeverPresent);
+ return nullptr;
+ }
+ if (cached_metadata_->DataTypeID() != data_type_id) {
+ RecordState(StateOnGet::kDataTypeMismatch);
return nullptr;
+ }
+ RecordState(StateOnGet::kPresent);
return cached_metadata_;
}
@@ -79,7 +107,7 @@ size_t ScriptCachedMetadataHandler::GetCodeCacheSize() const {
return (cached_metadata_) ? cached_metadata_->SerializedData().size() : 0;
}
-void ScriptCachedMetadataHandler::SendToPlatform() {
+void ScriptCachedMetadataHandler::CommitToPersistentStorage() {
if (cached_metadata_) {
base::span<const uint8_t> serialized_data =
cached_metadata_->SerializedData();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
index 4d1099b6625..df5ca5535a1 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
@@ -33,9 +33,9 @@ class PLATFORM_EXPORT ScriptCachedMetadataHandler final
ScriptCachedMetadataHandler(const WTF::TextEncoding&,
std::unique_ptr<CachedMetadataSender>);
~ScriptCachedMetadataHandler() override = default;
- void Trace(blink::Visitor*) override;
- void SetCachedMetadata(uint32_t, const uint8_t*, size_t, CacheType) override;
- void ClearCachedMetadata(CacheType) override;
+ void Trace(Visitor*) override;
+ void SetCachedMetadata(uint32_t, const uint8_t*, size_t) override;
+ void ClearCachedMetadata(ClearCacheType) override;
scoped_refptr<CachedMetadata> GetCachedMetadata(uint32_t) const override;
// This returns the encoding at the time of ResponseReceived(). Therefore this
@@ -56,14 +56,31 @@ class PLATFORM_EXPORT ScriptCachedMetadataHandler final
size_t GetCodeCacheSize() const override;
private:
- void SendToPlatform();
+ friend class ModuleScriptTest;
+
+ void CommitToPersistentStorage();
scoped_refptr<CachedMetadata> cached_metadata_;
+ bool cached_metadata_discarded_ = false;
std::unique_ptr<CachedMetadataSender> sender_;
const WTF::TextEncoding encoding_;
};
+// Describes a few interesting states of the ScriptCachedMetadataHandler when
+// GetCachedMetadata() is called. These values are written to logs. New enum
+// values can be added, but existing enums must never be renumbered or deleted
+// and reused.
+enum class StateOnGet : int {
+ kPresent = 0,
+ kDataTypeMismatch = 1,
+ kWasNeverPresent = 2,
+ kWasDiscarded = 3,
+
+ // Must be equal to the greatest among enumeraiton values.
+ kMaxValue = kWasDiscarded
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_SCRIPT_CACHED_METADATA_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
index f5aebce8964..f2647226f07 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
@@ -23,8 +23,10 @@ FetchParameters ScriptFetchOptions::CreateFetchParameters(
// Step 1. ... "script", ... [spec text]
ResourceLoaderOptions resource_loader_options;
resource_loader_options.initiator_info.name = "script";
- FetchParameters params(resource_request, resource_loader_options);
+ resource_loader_options.reject_coep_unsafe_none = reject_coep_unsafe_none_;
+ FetchParameters params(std::move(resource_request), resource_loader_options);
params.SetRequestContext(mojom::RequestContextType::SCRIPT);
+ params.SetRequestDestination(network::mojom::RequestDestination::kScript);
// Step 1. ... and CORS setting. [spec text]
if (cross_origin != kCrossOriginAttributeNotSet)
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
index 24e2efe2f92..45977a46229 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -48,14 +48,17 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
ParserDisposition parser_state,
network::mojom::CredentialsMode credentials_mode,
network::mojom::ReferrerPolicy referrer_policy,
- mojom::FetchImportanceMode importance)
+ mojom::FetchImportanceMode importance,
+ RejectCoepUnsafeNone reject_coep_unsafe_none =
+ RejectCoepUnsafeNone(false))
: nonce_(nonce),
integrity_metadata_(integrity_metadata),
integrity_attribute_(integrity_attribute),
parser_state_(parser_state),
credentials_mode_(credentials_mode),
referrer_policy_(referrer_policy),
- importance_(importance) {}
+ importance_(importance),
+ reject_coep_unsafe_none_(reject_coep_unsafe_none) {}
~ScriptFetchOptions() = default;
const String& Nonce() const { return nonce_; }
@@ -73,6 +76,9 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
return referrer_policy_;
}
mojom::FetchImportanceMode Importance() const { return importance_; }
+ RejectCoepUnsafeNone GetRejectCoepUnsafeNone() const {
+ return reject_coep_unsafe_none_;
+ }
// https://html.spec.whatwg.org/C/#fetch-a-classic-script
// Steps 1 and 3.
@@ -104,6 +110,13 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
// https://github.com/whatwg/html/issues/3670 for some discussion on adding an
// "importance" member to the script fetch options struct.
const mojom::FetchImportanceMode importance_;
+
+ // True when we should reject a response with COEP: none.
+ // https://wicg.github.io/cross-origin-embedder-policy/#integration-html
+ // This is for dedicated workers.
+ // TODO(crbug.com/1064920): Remove this once PlzDedicatedWorker ships.
+ const RejectCoepUnsafeNone reject_coep_unsafe_none_ =
+ RejectCoepUnsafeNone(false);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc
index db355819f3d..58cc557ec78 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.cc
@@ -28,18 +28,17 @@ class SourceKeyedCachedMetadataHandler::SingleKeyHandler final
void SetCachedMetadata(uint32_t data_type_id,
const uint8_t* data,
- size_t size,
- CacheType cache_type) override {
+ size_t size) override {
DCHECK(!parent_->cached_metadata_map_.Contains(key_));
parent_->cached_metadata_map_.insert(
key_, CachedMetadata::Create(data_type_id, data, size));
- if (cache_type == CachedMetadataHandler::kSendToPlatform)
+ if (!disable_send_to_platform_for_testing_)
parent_->SendToPlatform();
}
- void ClearCachedMetadata(CacheType cache_type) override {
+ void ClearCachedMetadata(ClearCacheType cache_type) override {
parent_->cached_metadata_map_.erase(key_);
- if (cache_type == CachedMetadataHandler::kSendToPlatform)
+ if (cache_type == CachedMetadataHandler::kClearPersistentStorage)
parent_->SendToPlatform();
}
@@ -104,9 +103,9 @@ SingleCachedMetadataHandler* SourceKeyedCachedMetadataHandler::HandlerForSource(
}
void SourceKeyedCachedMetadataHandler::ClearCachedMetadata(
- CachedMetadataHandler::CacheType cache_type) {
+ CachedMetadataHandler::ClearCacheType cache_type) {
cached_metadata_map_.clear();
- if (cache_type == CachedMetadataHandler::kSendToPlatform)
+ if (cache_type == CachedMetadataHandler::kClearPersistentStorage)
SendToPlatform();
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h
index 045a52d8670..4460985757c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h
@@ -32,7 +32,7 @@ class PLATFORM_EXPORT SourceKeyedCachedMetadataHandler final
SingleCachedMetadataHandler* HandlerForSource(const String& source);
void ClearCachedMetadata(
- CachedMetadataHandler::CacheType cache_type) override;
+ CachedMetadataHandler::ClearCacheType cache_type) override;
String Encoding() const override;
bool IsServedFromCacheStorage() const override {
return sender_->IsServedFromCacheStorage();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc
index 287d8ec84cf..eec248b7b95 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc
@@ -236,7 +236,7 @@ TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_EmptyClearDoesSend) {
WTF::TextEncoding(), std::make_unique<MockCachedMetadataSender>(url));
// Clear and send to the platform
- handler->ClearCachedMetadata(CachedMetadataHandler::kSendToPlatform);
+ handler->ClearCachedMetadata(CachedMetadataHandler::kClearPersistentStorage);
// Load from platform
Vector<CacheMetadataEntry> cache_metadatas =
@@ -293,8 +293,8 @@ TEST(SourceKeyedCachedMetadataHandlerTest, Serialize_SetWithNoSendDoesNotSend) {
handler->HandlerForSource(source2);
Vector<uint8_t> data1 = {1, 2, 3};
- source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size(),
- CachedMetadataHandler::kCacheLocally);
+ source1_handler->DisableSendToPlatformForTesting();
+ source1_handler->SetCachedMetadata(0xbeef, data1.data(), data1.size());
Vector<uint8_t> data2 = {3, 4, 5, 6};
source2_handler->SetCachedMetadata(0x5eed, data2.data(), data2.size());
@@ -320,8 +320,9 @@ TEST(SourceKeyedCachedMetadataHandlerTest,
WTF::TextEncoding(),
std::make_unique<MockCachedMetadataSender>(url));
- // Clear and send to the platform
- handler->ClearCachedMetadata(CachedMetadataHandler::kSendToPlatform);
+ // Clear and persist in the platform.
+ handler->ClearCachedMetadata(
+ CachedMetadataHandler::kClearPersistentStorage);
}
// Reload from platform
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
index c20cf6b3f02..bd1ead40055 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
@@ -29,7 +29,7 @@ void StaleRevalidationResourceClient::NotifyFinished(Resource* resource) {
}
}
-void StaleRevalidationResourceClient::Trace(blink::Visitor* visitor) {
+void StaleRevalidationResourceClient::Trace(Visitor* visitor) {
visitor->Trace(stale_resource_);
RawResourceClient::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
index 6ef734efb47..b1b9a3eb226 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
@@ -24,7 +24,7 @@ class StaleRevalidationResourceClient
// RawResourceClient overloads.
void NotifyFinished(Resource* resource) override;
- void Trace(blink::Visitor* visitor) override;
+ void Trace(Visitor* visitor) override;
String DebugName() const override;
private:
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.cc
new file mode 100644
index 00000000000..6654f8e72d5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.cc
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h"
+#include "services/network/public/cpp/optional_trust_token_params.h"
+#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+
+namespace blink {
+
+network::OptionalTrustTokenParams ConvertTrustTokenParams(
+ const base::Optional<network::mojom::blink::TrustTokenParams>& maybe_in) {
+ if (!maybe_in)
+ return base::nullopt;
+ const network::mojom::blink::TrustTokenParams& in = *maybe_in;
+
+ network::mojom::TrustTokenParamsPtr out =
+ network::mojom::TrustTokenParams::New();
+ out->type = in.type;
+ out->refresh_policy = in.refresh_policy;
+ out->sign_request_data = in.sign_request_data;
+ out->include_timestamp_header = in.include_timestamp_header;
+ // Optional value:
+ if (in.issuer)
+ out->issuer = in.issuer->ToUrlOrigin();
+ for (const String& additional_header : in.additional_signed_headers) {
+ out->additional_signed_headers.push_back(additional_header.Latin1());
+ }
+
+ return network::OptionalTrustTokenParams(std::move(out));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h b/chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h
new file mode 100644
index 00000000000..9ba5fe77806
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_TRUST_TOKEN_PARAMS_CONVERSION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_TRUST_TOKEN_PARAMS_CONVERSION_H_
+
+#include "base/optional.h"
+#include "services/network/public/cpp/optional_trust_token_params.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+namespace network {
+namespace mojom {
+namespace blink {
+class TrustTokenParams;
+
+} // namespace blink
+} // namespace mojom
+} // namespace network
+
+namespace blink {
+
+// Converts a mojom::blink TrustTokenParams object to its non-Blink counterpart
+// by directly copying all fields, converting types where necessary.
+network::OptionalTrustTokenParams ConvertTrustTokenParams(
+ const base::Optional<network::mojom::blink::TrustTokenParams>& maybe_in);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_TRUST_TOKEN_PARAMS_CONVERSION_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
new file mode 100644
index 00000000000..e3fe5379677
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
@@ -0,0 +1,353 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h"
+
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_util.h"
+#include "services/network/public/cpp/constants.h"
+#include "services/network/public/cpp/optional_trust_token_params.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
+#include "services/network/public/mojom/data_pipe_getter.mojom.h"
+#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+#include "services/network/public/mojom/trust_tokens.mojom.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/url_conversion.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h"
+#include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h"
+
+namespace blink {
+
+namespace {
+
+constexpr char kStylesheetAcceptHeader[] = "text/css,*/*;q=0.1";
+constexpr char kImageAcceptHeader[] = "image/webp,image/apng,image/*,*/*;q=0.8";
+
+// TODO(yhirano): Unify these with variables in
+// content/public/common/content_constants.h.
+constexpr char kCorsExemptPurposeHeaderName[] = "Purpose";
+constexpr char kCorsExemptRequestedWithHeaderName[] = "X-Requested-With";
+
+// This is complementary to ConvertNetPriorityToWebKitPriority, defined in
+// service_worker_context_client.cc.
+net::RequestPriority ConvertWebKitPriorityToNetPriority(
+ WebURLRequest::Priority priority) {
+ switch (priority) {
+ case WebURLRequest::Priority::kVeryHigh:
+ return net::HIGHEST;
+
+ case WebURLRequest::Priority::kHigh:
+ return net::MEDIUM;
+
+ case WebURLRequest::Priority::kMedium:
+ return net::LOW;
+
+ case WebURLRequest::Priority::kLow:
+ return net::LOWEST;
+
+ case WebURLRequest::Priority::kVeryLow:
+ return net::IDLE;
+
+ case WebURLRequest::Priority::kUnresolved:
+ default:
+ NOTREACHED();
+ return net::LOW;
+ }
+}
+
+// TODO(yhirano) Dedupe this and the same-name function in
+// web_url_request_util.cc.
+std::string TrimLWSAndCRLF(const base::StringPiece& input) {
+ base::StringPiece string = net::HttpUtil::TrimLWS(input);
+ const char* begin = string.data();
+ const char* end = string.data() + string.size();
+ while (begin < end && (end[-1] == '\r' || end[-1] == '\n'))
+ --end;
+ return std::string(base::StringPiece(begin, end - begin));
+}
+
+mojom::ResourceType RequestContextToResourceType(
+ mojom::RequestContextType request_context) {
+ switch (request_context) {
+ // CSP report
+ case mojom::RequestContextType::CSP_REPORT:
+ return mojom::ResourceType::kCspReport;
+
+ // Favicon
+ case mojom::RequestContextType::FAVICON:
+ return mojom::ResourceType::kFavicon;
+
+ // Font
+ case mojom::RequestContextType::FONT:
+ return mojom::ResourceType::kFontResource;
+
+ // Image
+ case mojom::RequestContextType::IMAGE:
+ case mojom::RequestContextType::IMAGE_SET:
+ return mojom::ResourceType::kImage;
+
+ // Media
+ case mojom::RequestContextType::AUDIO:
+ case mojom::RequestContextType::VIDEO:
+ return mojom::ResourceType::kMedia;
+
+ // Object
+ case mojom::RequestContextType::EMBED:
+ case mojom::RequestContextType::OBJECT:
+ return mojom::ResourceType::kObject;
+
+ // Ping
+ case mojom::RequestContextType::BEACON:
+ case mojom::RequestContextType::PING:
+ return mojom::ResourceType::kPing;
+
+ // Subresource of plugins
+ case mojom::RequestContextType::PLUGIN:
+ return mojom::ResourceType::kPluginResource;
+
+ // Prefetch
+ case mojom::RequestContextType::PREFETCH:
+ return mojom::ResourceType::kPrefetch;
+
+ // Script
+ case mojom::RequestContextType::IMPORT:
+ case mojom::RequestContextType::SCRIPT:
+ return mojom::ResourceType::kScript;
+
+ // Style
+ case mojom::RequestContextType::XSLT:
+ case mojom::RequestContextType::STYLE:
+ return mojom::ResourceType::kStylesheet;
+
+ // Subresource
+ case mojom::RequestContextType::DOWNLOAD:
+ case mojom::RequestContextType::MANIFEST:
+ case mojom::RequestContextType::SUBRESOURCE:
+ return mojom::ResourceType::kSubResource;
+
+ // TextTrack
+ case mojom::RequestContextType::TRACK:
+ return mojom::ResourceType::kMedia;
+
+ // Workers
+ case mojom::RequestContextType::SERVICE_WORKER:
+ return mojom::ResourceType::kServiceWorker;
+ case mojom::RequestContextType::SHARED_WORKER:
+ return mojom::ResourceType::kSharedWorker;
+ case mojom::RequestContextType::WORKER:
+ return mojom::ResourceType::kWorker;
+
+ // Unspecified
+ case mojom::RequestContextType::INTERNAL:
+ case mojom::RequestContextType::UNSPECIFIED:
+ return mojom::ResourceType::kSubResource;
+
+ // XHR
+ case mojom::RequestContextType::EVENT_SOURCE:
+ case mojom::RequestContextType::FETCH:
+ case mojom::RequestContextType::XML_HTTP_REQUEST:
+ return mojom::ResourceType::kXhr;
+
+ // Navigation requests should not go through WebURLLoader.
+ case mojom::RequestContextType::FORM:
+ case mojom::RequestContextType::HYPERLINK:
+ case mojom::RequestContextType::LOCATION:
+ case mojom::RequestContextType::FRAME:
+ case mojom::RequestContextType::IFRAME:
+ NOTREACHED();
+ return mojom::ResourceType::kSubResource;
+
+ default:
+ NOTREACHED();
+ return mojom::ResourceType::kSubResource;
+ }
+}
+
+} // namespace
+
+void PopulateResourceRequestBody(const EncodedFormData& src,
+ network::ResourceRequestBody* dest) {
+ for (const auto& element : src.Elements()) {
+ switch (element.type_) {
+ case FormDataElement::kData:
+ dest->AppendBytes(element.data_.data(), element.data_.size());
+ break;
+ case FormDataElement::kEncodedFile:
+ if (element.file_length_ == -1) {
+ dest->AppendFileRange(
+ WebStringToFilePath(element.filename_), 0,
+ std::numeric_limits<uint64_t>::max(),
+ element.expected_file_modification_time_.value_or(base::Time()));
+ } else {
+ dest->AppendFileRange(
+ WebStringToFilePath(element.filename_),
+ static_cast<uint64_t>(element.file_start_),
+ static_cast<uint64_t>(element.file_length_),
+ element.expected_file_modification_time_.value_or(base::Time()));
+ }
+ break;
+ case FormDataElement::kEncodedBlob: {
+ DCHECK(element.optional_blob_data_handle_);
+ mojo::Remote<mojom::Blob> blob_remote(mojo::PendingRemote<mojom::Blob>(
+ element.optional_blob_data_handle_->CloneBlobRemote().PassPipe(),
+ mojom::Blob::Version_));
+ mojo::PendingRemote<network::mojom::DataPipeGetter>
+ data_pipe_getter_remote;
+ blob_remote->AsDataPipeGetter(
+ data_pipe_getter_remote.InitWithNewPipeAndPassReceiver());
+ dest->AppendDataPipe(std::move(data_pipe_getter_remote));
+ break;
+ }
+ case FormDataElement::kDataPipe: {
+ // Convert network::mojom::blink::DataPipeGetter to
+ // network::mojom::DataPipeGetter through a raw message pipe.
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ pending_data_pipe_getter;
+ element.data_pipe_getter_->GetDataPipeGetter()->Clone(
+ pending_data_pipe_getter.InitWithNewPipeAndPassReceiver());
+ dest->AppendDataPipe(
+ mojo::PendingRemote<network::mojom::DataPipeGetter>(
+ pending_data_pipe_getter.PassPipe(), 0u));
+ break;
+ }
+ }
+ }
+}
+
+void PopulateResourceRequest(const ResourceRequestHead& src,
+ ResourceRequestBody src_body,
+ network::ResourceRequest* dest) {
+ dest->method = src.HttpMethod().Latin1();
+ dest->url = src.Url();
+ dest->site_for_cookies = src.SiteForCookies();
+ dest->upgrade_if_insecure = src.UpgradeIfInsecure();
+ dest->is_revalidating = src.IsRevalidating();
+ if (src.RequestorOrigin()->ToString() == "null") {
+ // "file:" origin is treated like an opaque unique origin when
+ // allow-file-access-from-files is not specified. Such origin is not
+ // opaque (i.e., IsOpaque() returns false) but still serializes to
+ // "null".
+ dest->request_initiator = url::Origin();
+ } else {
+ dest->request_initiator = src.RequestorOrigin()->ToUrlOrigin();
+ }
+ if (src.IsolatedWorldOrigin()) {
+ dest->isolated_world_origin = src.IsolatedWorldOrigin()->ToUrlOrigin();
+ }
+ dest->referrer = WebStringToGURL(src.ReferrerString());
+
+ // "default" referrer policy has already been resolved.
+ DCHECK_NE(src.GetReferrerPolicy(), network::mojom::ReferrerPolicy::kDefault);
+ dest->referrer_policy =
+ network::ReferrerPolicyForUrlRequest(src.GetReferrerPolicy());
+
+ for (const auto& item : src.HttpHeaderFields()) {
+ const std::string name = item.key.Latin1();
+ const std::string value = TrimLWSAndCRLF(item.value.Latin1());
+ dest->headers.SetHeader(name, value);
+ }
+ // Set X-Requested-With header to cors_exempt_headers rather than headers to
+ // be exempted from CORS checks.
+ if (!src.GetRequestedWithHeader().IsEmpty()) {
+ dest->cors_exempt_headers.SetHeader(kCorsExemptRequestedWithHeaderName,
+ src.GetRequestedWithHeader().Utf8());
+ }
+ // Set Purpose header to cors_exempt_headers rather than headers to be
+ // exempted from CORS checks.
+ if (!src.GetPurposeHeader().IsEmpty()) {
+ dest->cors_exempt_headers.SetHeader(kCorsExemptPurposeHeaderName,
+ src.GetPurposeHeader().Utf8());
+ }
+
+ // TODO(yhirano): Remove this WrappedResourceRequest.
+ dest->load_flags = WrappedResourceRequest(ResourceRequest(src))
+ .GetLoadFlagsForWebUrlRequest();
+ dest->recursive_prefetch_token = src.RecursivePrefetchToken();
+ dest->priority = ConvertWebKitPriorityToNetPriority(src.Priority());
+ dest->should_reset_appcache = src.ShouldResetAppCache();
+ dest->is_external_request = src.IsExternalRequest();
+ dest->cors_preflight_policy = src.CorsPreflightPolicy();
+ dest->skip_service_worker = src.GetSkipServiceWorker();
+ dest->mode = src.GetMode();
+ dest->destination = src.GetRequestDestination();
+ dest->credentials_mode = src.GetCredentialsMode();
+ dest->redirect_mode = src.GetRedirectMode();
+ dest->fetch_integrity = src.GetFetchIntegrity().Utf8();
+
+ mojom::ResourceType resource_type =
+ RequestContextToResourceType(src.GetRequestContext());
+
+ // TODO(kinuko): Deprecate these.
+ dest->fetch_request_context_type = static_cast<int>(src.GetRequestContext());
+ dest->resource_type = static_cast<int>(resource_type);
+
+ if (resource_type == mojom::ResourceType::kXhr &&
+ (dest->url.has_username() || dest->url.has_password())) {
+ dest->do_not_prompt_for_login = true;
+ }
+ if (resource_type == mojom::ResourceType::kPrefetch ||
+ resource_type == mojom::ResourceType::kFavicon) {
+ dest->do_not_prompt_for_login = true;
+ }
+
+ dest->keepalive = src.GetKeepalive();
+ dest->has_user_gesture = src.HasUserGesture();
+ dest->enable_load_timing = true;
+ dest->enable_upload_progress = src.ReportUploadProgress();
+ dest->report_raw_headers = src.ReportRawHeaders();
+ // TODO(ryansturm): Remove dest->previews_state once it is no
+ // longer used in a network delegate. https://crbug.com/842233
+ dest->previews_state = static_cast<int>(src.GetPreviewsState());
+ dest->throttling_profile_id = src.GetDevToolsToken();
+ dest->trust_token_params = ConvertTrustTokenParams(src.TrustTokenParams());
+
+ if (base::UnguessableToken window_id = src.GetFetchWindowId())
+ dest->fetch_window_id = base::make_optional(window_id);
+
+ if (src.GetDevToolsId().has_value()) {
+ dest->devtools_request_id = src.GetDevToolsId().value().Ascii();
+ }
+
+ if (src.IsSignedExchangePrefetchCacheEnabled()) {
+ DCHECK_EQ(src.GetRequestContext(), mojom::RequestContextType::PREFETCH);
+ dest->is_signed_exchange_prefetch_cache_enabled = true;
+ }
+
+ if (const EncodedFormData* body = src_body.FormBody().get()) {
+ DCHECK_NE(dest->method, net::HttpRequestHeaders::kGetMethod);
+ DCHECK_NE(dest->method, net::HttpRequestHeaders::kHeadMethod);
+ dest->request_body = base::MakeRefCounted<network::ResourceRequestBody>();
+
+ PopulateResourceRequestBody(*body, dest->request_body.get());
+ }
+
+ if (resource_type == mojom::ResourceType::kStylesheet) {
+ dest->headers.SetHeader(net::HttpRequestHeaders::kAccept,
+ kStylesheetAcceptHeader);
+ } else if (resource_type == mojom::ResourceType::kImage ||
+ resource_type == mojom::ResourceType::kFavicon) {
+ dest->headers.SetHeader(net::HttpRequestHeaders::kAccept,
+ kImageAcceptHeader);
+ } else {
+ // Calling SetHeaderIfMissing() instead of SetHeader() because JS can
+ // manually set an accept header on an XHR.
+ dest->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kAccept,
+ network::kDefaultAcceptHeaderValue);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
new file mode 100644
index 00000000000..a94fba68d4c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_REQUEST_CONVERSION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_REQUEST_CONVERSION_H_
+
+// This file consists of request conversion functions between blink and network.
+
+namespace network {
+class ResourceRequestBody;
+struct ResourceRequest;
+} // namespace network
+
+namespace blink {
+
+class ResourceRequestHead;
+class ResourceRequestBody;
+class EncodedFormData;
+
+void PopulateResourceRequestBody(const EncodedFormData& src,
+ network::ResourceRequestBody* dest);
+
+void PopulateResourceRequest(const ResourceRequestHead& src,
+ ResourceRequestBody src_body,
+ network::ResourceRequest* dest);
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_REQUEST_CONVERSION_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h b/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h
index 918a3528df8..92271f1c6ed 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h
@@ -5,14 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_WORKER_RESOURCE_TIMING_NOTIFIER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_WORKER_RESOURCE_TIMING_NOTIFIER_H_
+#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
namespace blink {
-struct WebResourceTimingInfo;
-
// This class is used by WorkerFetchContext to add a resource timing to an
// appropriate Performance Timeline.
// https://w3c.github.io/performance-timeline/#performance-timeline
@@ -27,7 +26,7 @@ class WorkerResourceTimingNotifier
// Timeline which may be associated with a different thread from the current
// running thread.
virtual void AddResourceTiming(
- const WebResourceTimingInfo&,
+ mojom::blink::ResourceTimingInfoPtr,
const AtomicString& initiator_type,
mojo::PendingReceiver<mojom::blink::WorkerTimingContainer>
worker_timing_receiver) = 0;
diff --git a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc
index 5b3753c2fdb..cf9e2d5fbf2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity_test.cc
@@ -220,18 +220,17 @@ class SubresourceIntegrityTest : public testing::Test {
const KURL& url,
network::mojom::RequestMode request_mode,
network::mojom::FetchResponseType response_type) {
- Resource* resource = RawResource::CreateForTest(
- url, SecurityOrigin::CreateUniqueOpaque(), ResourceType::kRaw);
-
ResourceRequest request;
request.SetUrl(url);
request.SetMode(request_mode);
+ request.SetRequestorOrigin(SecurityOrigin::CreateUniqueOpaque());
+ Resource* resource =
+ RawResource::CreateForTest(request, ResourceType::kRaw);
ResourceResponse response(url);
response.SetHttpStatusCode(200);
response.SetType(response_type);
- resource->SetResourceRequest(request);
resource->SetResponse(response);
return resource;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h b/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h
index 6a321b75317..5fd5c9b36ac 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h
@@ -30,7 +30,7 @@ class BytesConsumerTestReader final
std::pair<BytesConsumer::Result, Vector<char>> Run(
scheduler::FakeTaskRunner*);
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(consumer_);
BytesConsumer::Client::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index 7f634061276..d98ded9ee9f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -39,7 +39,7 @@ class MockFetchContext : public FetchContext {
const ResourceRequest&,
const KURL&,
const ResourceLoaderOptions&,
- SecurityViolationReportingPolicy,
+ ReportingDisposition,
ResourceRequest::RedirectStatus redirect_status) const override {
return base::nullopt;
}
@@ -47,7 +47,7 @@ class MockFetchContext : public FetchContext {
mojom::RequestContextType,
const KURL& url,
const ResourceLoaderOptions& options,
- SecurityViolationReportingPolicy reporting_policy,
+ ReportingDisposition reporting_disposition,
ResourceRequest::RedirectStatus redirect_status) const override {
return base::nullopt;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
index 197807baa5d..773060d3bd5 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
@@ -80,8 +80,8 @@ void MockCacheHandler::Set(const uint8_t* data, size_t size) {
}
void MockCacheHandler::ClearCachedMetadata(
- CachedMetadataHandler::CacheType cache_type) {
- if (cache_type == CachedMetadataHandler::kSendToPlatform) {
+ CachedMetadataHandler::ClearCacheType cache_type) {
+ if (cache_type == CachedMetadataHandler::kClearPersistentStorage) {
Send();
}
data_.reset();
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
index 5c1e0690529..991860b1079 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
@@ -23,7 +23,7 @@ class MockCacheHandler : public CachedMetadataHandler {
MockCacheHandler(std::unique_ptr<CachedMetadataSender> send_callback);
void Set(const uint8_t* data, size_t);
- void ClearCachedMetadata(CachedMetadataHandler::CacheType) override;
+ void ClearCachedMetadata(CachedMetadataHandler::ClearCacheType) override;
void Send();
String Encoding() const override { return "mock encoding"; }
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.cc b/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.cc
index 401bed1de75..d699ef377ea 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.cc
@@ -137,7 +137,7 @@ void ReplayingBytesConsumer::MakeErrored(const Error& e) {
++notification_token_;
}
-void ReplayingBytesConsumer::Trace(blink::Visitor* visitor) {
+void ReplayingBytesConsumer::Trace(Visitor* visitor) {
visitor->Trace(client_);
BytesConsumer::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h
index e3dc0ae9af2..de29497afc4 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h
@@ -65,7 +65,7 @@ class ReplayingBytesConsumer final : public BytesConsumer {
bool IsCancelled() const { return is_cancelled_; }
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
void NotifyAsReadable(int notification_token);
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc
index 723d4c721e0..9b222e3c600 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc
@@ -6,6 +6,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/fetch/https_state.h"
@@ -29,7 +30,7 @@ TestResourceFetcherProperties::TestResourceFetcherProperties(
HttpsState::kNone,
AllowedByNosniff::MimeTypeCheck::kStrict,
network::mojom::IPAddressSpace::kPublic,
- kLeaveInsecureRequestsAlone,
+ mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone,
FetchClientSettingsObject::InsecureNavigationsSet())) {}
TestResourceFetcherProperties::TestResourceFetcherProperties(
diff --git a/chromium/third_party/blink/renderer/platform/media/web_audio_source_provider_client.h b/chromium/third_party/blink/renderer/platform/media/web_audio_source_provider_client.h
new file mode 100644
index 00000000000..748e189444e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/web_audio_source_provider_client.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_AUDIO_SOURCE_PROVIDER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_AUDIO_SOURCE_PROVIDER_CLIENT_H_
+
+namespace blink {
+
+class WebAudioSourceProviderClient {
+ public:
+ virtual void SetFormat(uint32_t number_of_channels, float sample_rate) = 0;
+
+ protected:
+ virtual ~WebAudioSourceProviderClient() = default;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_WEB_AUDIO_SOURCE_PROVIDER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
index 979fb044f71..a38efb3e55b 100644
--- a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
@@ -16,7 +16,7 @@
#include "media/base/audio_timestamp_helper.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/media_log.h"
-#include "third_party/blink/public/platform/web_audio_source_provider_client.h"
+#include "third_party/blink/renderer/platform/media/web_audio_source_provider_client.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -74,8 +74,34 @@ class WebAudioSourceProviderImpl::TeeFilter
int Render(base::TimeDelta delay,
base::TimeTicks delay_timestamp,
int prior_frames_skipped,
- media::AudioBus* dest) override;
- void OnRenderError() override;
+ media::AudioBus* audio_bus) override {
+ DCHECK(initialized());
+
+ const int num_rendered_frames = renderer_->Render(
+ delay, delay_timestamp, prior_frames_skipped, audio_bus);
+
+ // Avoid taking the copy lock for the vast majority of cases.
+ if (copy_required_) {
+ base::AutoLock auto_lock(copy_lock_);
+ if (!copy_audio_bus_callback_.is_null()) {
+ const int64_t frames_delayed =
+ media::AudioTimestampHelper::TimeToFrames(delay, sample_rate_);
+ std::unique_ptr<media::AudioBus> bus_copy =
+ media::AudioBus::Create(audio_bus->channels(), audio_bus->frames());
+ audio_bus->CopyTo(bus_copy.get());
+ copy_audio_bus_callback_.Run(std::move(bus_copy),
+ static_cast<uint32_t>(frames_delayed),
+ sample_rate_);
+ }
+ }
+
+ return num_rendered_frames;
+ }
+
+ void OnRenderError() override {
+ DCHECK(initialized());
+ renderer_->OnRenderError();
+ }
bool initialized() const { return !!renderer_; }
int channels() const { return channels_; }
@@ -134,7 +160,7 @@ void WebAudioSourceProviderImpl::SetClient(
// The client will now take control by calling provideInput() periodically.
client_ = client;
- set_format_cb_ = media::BindToCurrentLoop(WTF::Bind(
+ set_format_cb_ = media::BindToCurrentLoop(WTF::BindRepeating(
&WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr()));
// If |tee_filter_| is Initialize()d - then run |set_format_cb_| to send
@@ -142,13 +168,17 @@ void WebAudioSourceProviderImpl::SetClient(
// called when Initialize() is called. Note: Always using |set_format_cb_|
// ensures we have the same locking order when calling into |client_|.
if (tee_filter_->initialized())
- std::move(set_format_cb_).Run();
+ set_format_cb_.Run();
return;
}
// Drop client, but normal playback can't be restored. This is okay, the only
// way to disconnect a client is internally at time of destruction.
client_ = nullptr;
+
+ // We need to invalidate WeakPtr references on the renderer thread.
+ set_format_cb_.Reset();
+ weak_factory_.InvalidateWeakPtrs();
}
void WebAudioSourceProviderImpl::ProvideInput(
@@ -196,7 +226,7 @@ void WebAudioSourceProviderImpl::Initialize(
sink_->Initialize(params, tee_filter_.get());
if (set_format_cb_)
- std::move(set_format_cb_).Run();
+ set_format_cb_.Run();
}
void WebAudioSourceProviderImpl::Start() {
@@ -310,37 +340,4 @@ void WebAudioSourceProviderImpl::OnSetFormat() {
client_->SetFormat(tee_filter_->channels(), tee_filter_->sample_rate());
}
-int WebAudioSourceProviderImpl::TeeFilter::Render(
- base::TimeDelta delay,
- base::TimeTicks delay_timestamp,
- int prior_frames_skipped,
- media::AudioBus* audio_bus) {
- DCHECK(initialized());
-
- const int num_rendered_frames = renderer_->Render(
- delay, delay_timestamp, prior_frames_skipped, audio_bus);
-
- // Avoid taking the copy lock for the vast majority of cases.
- if (copy_required_) {
- base::AutoLock auto_lock(copy_lock_);
- if (!copy_audio_bus_callback_.is_null()) {
- const int64_t frames_delayed =
- media::AudioTimestampHelper::TimeToFrames(delay, sample_rate_);
- std::unique_ptr<media::AudioBus> bus_copy =
- media::AudioBus::Create(audio_bus->channels(), audio_bus->frames());
- audio_bus->CopyTo(bus_copy.get());
- copy_audio_bus_callback_.Run(std::move(bus_copy),
- static_cast<uint32_t>(frames_delayed),
- sample_rate_);
- }
- }
-
- return num_rendered_frames;
-}
-
-void WebAudioSourceProviderImpl::TeeFilter::OnRenderError() {
- DCHECK(initialized());
- renderer_->OnRenderError();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
index f45ebe3f666..1f0c69d7143 100644
--- a/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
@@ -14,8 +14,8 @@
#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_audio_source_provider_client.h"
#include "third_party/blink/public/platform/webaudiosourceprovider_impl.h"
+#include "third_party/blink/renderer/platform/media/web_audio_source_provider_client.h"
using ::testing::_;
@@ -253,7 +253,7 @@ TEST_F(WebAudioSourceProviderImplTest, ProvideInput) {
TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) {
testing::InSequence s;
wasp_impl_->Initialize(params_, &fake_callback_);
- wasp_impl_->SetCopyAudioCallback(base::Bind(
+ wasp_impl_->SetCopyAudioCallback(WTF::BindRepeating(
&WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this)));
const auto bus1 = media::AudioBus::Create(params_);
@@ -267,4 +267,57 @@ TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) {
testing::Mock::VerifyAndClear(mock_sink_.get());
}
+TEST_F(WebAudioSourceProviderImplTest, MultipleInitializeWithSetClient) {
+ // setClient() with a nullptr client should do nothing if no client is set.
+ wasp_impl_->SetClient(nullptr);
+
+ // When Initialize() is called after setClient(), the params should propagate
+ // to the client via setFormat() during the call.
+ EXPECT_TRUE(wasp_impl_->IsOptimizedForHardwareParameters());
+ EXPECT_CALL(*this, SetFormat(params_.channels(), params_.sample_rate()));
+ wasp_impl_->Initialize(params_, &fake_callback_);
+ base::RunLoop().RunUntilIdle();
+
+ // If |mock_sink_| is not null, it should be stopped during setClient(this).
+ if (mock_sink_)
+ EXPECT_CALL(*mock_sink_.get(), Stop());
+
+ // setClient() with the same client should do nothing.
+ wasp_impl_->SetClient(this);
+ base::RunLoop().RunUntilIdle();
+
+ // Stop allows Initialize() to be called again.
+ wasp_impl_->Stop();
+
+ // It's possible that due to media change or just the change in the return
+ // value for IsOptimizedForHardwareParameters() that different params are
+ // given. Ensure this doesn't crash.
+ EXPECT_FALSE(wasp_impl_->IsOptimizedForHardwareParameters());
+ auto stream_params = media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_MONO,
+ kTestSampleRate * 2, 64);
+
+ EXPECT_CALL(*this,
+ SetFormat(stream_params.channels(), stream_params.sample_rate()));
+ wasp_impl_->Initialize(stream_params, &fake_callback_);
+ base::RunLoop().RunUntilIdle();
+
+ wasp_impl_->Start();
+ wasp_impl_->Play();
+
+ auto bus1 = media::AudioBus::Create(stream_params);
+ auto bus2 = media::AudioBus::Create(stream_params);
+
+ // Point the WebVector into memory owned by |bus1|.
+ WebVector<float*> audio_data(static_cast<size_t>(bus1->channels()));
+ for (size_t i = 0; i < audio_data.size(); ++i)
+ audio_data[i] = bus1->channel(static_cast<int>(i));
+
+ // Verify provideInput() doesn't return silence and doesn't crash.
+ bus1->channel(0)[0] = 1;
+ bus2->Zero();
+ wasp_impl_->ProvideInput(audio_data, params_.frames_per_buffer());
+ ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/DEPS b/chromium/third_party/blink/renderer/platform/mediastream/DEPS
index 22e08dbd4d9..3298a7464b4 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/DEPS
+++ b/chromium/third_party/blink/renderer/platform/mediastream/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+third_party/blink/renderer/platform/mediastream",
# Dependencies.
+ "+base/atomicops.h",
"+media/base",
"+media/webrtc/audio_processor_controls.h",
"+third_party/blink/renderer/platform/audio",
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.cc b/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.cc
index d0254a6fdb1..13ade0a00cf 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h"
+#include "base/memory/ptr_util.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/audio_service_audio_processor_proxy.cc b/chromium/third_party/blink/renderer/platform/mediastream/audio_service_audio_processor_proxy.cc
index 771bad73b57..aa8c19862a3 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/audio_service_audio_processor_proxy.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/audio_service_audio_processor_proxy.cc
@@ -12,7 +12,6 @@
#include <utility>
#include <vector>
-#include "base/bind.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "base/timer/timer.h"
@@ -20,6 +19,7 @@
#include "third_party/blink/renderer/platform/mediastream/aec_dump_agent_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -62,8 +62,7 @@ void AudioServiceAudioProcessorProxy::OnStartDump(base::File dump_file) {
} else {
// Post the file close to avoid blocking the main thread.
worker_pool::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::TaskPriority::LOWEST, base::MayBlock()},
+ FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
CrossThreadBindOnce([](base::File) {}, std::move(dump_file)));
}
}
@@ -119,16 +118,16 @@ void AudioServiceAudioProcessorProxy::RescheduleStatsUpdateTimer(
// Unretained is safe since |this| owns |stats_update_timer_|.
stats_update_timer_.Start(
FROM_HERE, new_interval,
- base::BindRepeating(&AudioServiceAudioProcessorProxy::RequestStats,
- base::Unretained(this)));
+ WTF::BindRepeating(&AudioServiceAudioProcessorProxy::RequestStats,
+ WTF::Unretained(this)));
}
void AudioServiceAudioProcessorProxy::RequestStats() {
DCHECK(main_thread_runner_->BelongsToCurrentThread());
if (processor_controls_) {
processor_controls_->GetStats(
- base::BindOnce(&AudioServiceAudioProcessorProxy::UpdateStats,
- weak_ptr_factory_.GetWeakPtr()));
+ WTF::Bind(&AudioServiceAudioProcessorProxy::UpdateStats,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_constraints.cc
index dcad673ac67..e23da0b73e5 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_constraints.cc
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/public/platform/web_media_constraints.h"
+#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include <math.h>
#include "base/memory/scoped_refptr.h"
@@ -76,66 +76,66 @@ const char kEchoCancellationTypeBrowser[] = "browser";
const char kEchoCancellationTypeAec3[] = "aec3";
const char kEchoCancellationTypeSystem[] = "system";
-class WebMediaConstraintsPrivate final
- : public ThreadSafeRefCounted<WebMediaConstraintsPrivate> {
+class MediaConstraintsPrivate final
+ : public ThreadSafeRefCounted<MediaConstraintsPrivate> {
public:
- static scoped_refptr<WebMediaConstraintsPrivate> Create();
- static scoped_refptr<WebMediaConstraintsPrivate> Create(
- const WebMediaTrackConstraintSet& basic,
- const WebVector<WebMediaTrackConstraintSet>& advanced);
+ static scoped_refptr<MediaConstraintsPrivate> Create();
+ static scoped_refptr<MediaConstraintsPrivate> Create(
+ const MediaTrackConstraintSetPlatform& basic,
+ const Vector<MediaTrackConstraintSetPlatform>& advanced);
bool IsEmpty() const;
- const WebMediaTrackConstraintSet& Basic() const;
- const WebVector<WebMediaTrackConstraintSet>& Advanced() const;
+ const MediaTrackConstraintSetPlatform& Basic() const;
+ const Vector<MediaTrackConstraintSetPlatform>& Advanced() const;
const String ToString() const;
private:
- WebMediaConstraintsPrivate(
- const WebMediaTrackConstraintSet& basic,
- const WebVector<WebMediaTrackConstraintSet>& advanced);
+ MediaConstraintsPrivate(
+ const MediaTrackConstraintSetPlatform& basic,
+ const Vector<MediaTrackConstraintSetPlatform>& advanced);
- WebMediaTrackConstraintSet basic_;
- WebVector<WebMediaTrackConstraintSet> advanced_;
+ MediaTrackConstraintSetPlatform basic_;
+ Vector<MediaTrackConstraintSetPlatform> advanced_;
};
-scoped_refptr<WebMediaConstraintsPrivate> WebMediaConstraintsPrivate::Create() {
- WebMediaTrackConstraintSet basic;
- WebVector<WebMediaTrackConstraintSet> advanced;
- return base::AdoptRef(new WebMediaConstraintsPrivate(basic, advanced));
+scoped_refptr<MediaConstraintsPrivate> MediaConstraintsPrivate::Create() {
+ MediaTrackConstraintSetPlatform basic;
+ Vector<MediaTrackConstraintSetPlatform> advanced;
+ return base::AdoptRef(new MediaConstraintsPrivate(basic, advanced));
}
-scoped_refptr<WebMediaConstraintsPrivate> WebMediaConstraintsPrivate::Create(
- const WebMediaTrackConstraintSet& basic,
- const WebVector<WebMediaTrackConstraintSet>& advanced) {
- return base::AdoptRef(new WebMediaConstraintsPrivate(basic, advanced));
+scoped_refptr<MediaConstraintsPrivate> MediaConstraintsPrivate::Create(
+ const MediaTrackConstraintSetPlatform& basic,
+ const Vector<MediaTrackConstraintSetPlatform>& advanced) {
+ return base::AdoptRef(new MediaConstraintsPrivate(basic, advanced));
}
-WebMediaConstraintsPrivate::WebMediaConstraintsPrivate(
- const WebMediaTrackConstraintSet& basic,
- const WebVector<WebMediaTrackConstraintSet>& advanced)
+MediaConstraintsPrivate::MediaConstraintsPrivate(
+ const MediaTrackConstraintSetPlatform& basic,
+ const Vector<MediaTrackConstraintSetPlatform>& advanced)
: basic_(basic), advanced_(advanced) {}
-bool WebMediaConstraintsPrivate::IsEmpty() const {
+bool MediaConstraintsPrivate::IsEmpty() const {
// TODO(hta): When generating advanced constraints, make sure no empty
// elements can be added to the m_advanced vector.
- return basic_.IsEmpty() && advanced_.empty();
+ return basic_.IsEmpty() && advanced_.IsEmpty();
}
-const WebMediaTrackConstraintSet& WebMediaConstraintsPrivate::Basic() const {
+const MediaTrackConstraintSetPlatform& MediaConstraintsPrivate::Basic() const {
return basic_;
}
-const WebVector<WebMediaTrackConstraintSet>&
-WebMediaConstraintsPrivate::Advanced() const {
+const Vector<MediaTrackConstraintSetPlatform>&
+MediaConstraintsPrivate::Advanced() const {
return advanced_;
}
-const String WebMediaConstraintsPrivate::ToString() const {
+const String MediaConstraintsPrivate::ToString() const {
StringBuilder builder;
if (!IsEmpty()) {
builder.Append('{');
builder.Append(Basic().ToString());
- if (!Advanced().empty()) {
+ if (!Advanced().IsEmpty()) {
if (builder.length() > 1)
builder.Append(", ");
builder.Append("advanced: [");
@@ -193,7 +193,7 @@ bool LongConstraint::IsEmpty() const {
return !has_min_ && !has_max_ && !has_exact_ && !has_ideal_;
}
-WebString LongConstraint::ToString() const {
+String LongConstraint::ToString() const {
StringBuilder builder;
builder.Append('{');
MaybeEmitNamedValue(builder, has_min_, "min", min_);
@@ -235,7 +235,7 @@ bool DoubleConstraint::IsEmpty() const {
return !has_min_ && !has_max_ && !has_exact_ && !has_ideal_;
}
-WebString DoubleConstraint::ToString() const {
+String DoubleConstraint::ToString() const {
StringBuilder builder;
builder.Append('{');
MaybeEmitNamedValue(builder, has_min_, "min", min_);
@@ -249,8 +249,8 @@ WebString DoubleConstraint::ToString() const {
StringConstraint::StringConstraint(const char* name)
: BaseConstraint(name), exact_(), ideal_() {}
-bool StringConstraint::Matches(WebString value) const {
- if (exact_.empty()) {
+bool StringConstraint::Matches(String value) const {
+ if (exact_.IsEmpty()) {
return true;
}
for (const auto& choice : exact_) {
@@ -262,21 +262,21 @@ bool StringConstraint::Matches(WebString value) const {
}
bool StringConstraint::IsEmpty() const {
- return exact_.empty() && ideal_.empty();
+ return exact_.IsEmpty() && ideal_.IsEmpty();
}
-const WebVector<WebString>& StringConstraint::Exact() const {
+const Vector<String>& StringConstraint::Exact() const {
return exact_;
}
-const WebVector<WebString>& StringConstraint::Ideal() const {
+const Vector<String>& StringConstraint::Ideal() const {
return ideal_;
}
-WebString StringConstraint::ToString() const {
+String StringConstraint::ToString() const {
StringBuilder builder;
builder.Append('{');
- if (!ideal_.empty()) {
+ if (!ideal_.IsEmpty()) {
builder.Append("ideal: [");
bool first = true;
for (const auto& iter : ideal_) {
@@ -289,7 +289,7 @@ WebString StringConstraint::ToString() const {
}
builder.Append(']');
}
- if (!exact_.empty()) {
+ if (!exact_.IsEmpty()) {
if (builder.length() > 1)
builder.Append(", ");
builder.Append("exact: [");
@@ -325,7 +325,7 @@ bool BooleanConstraint::IsEmpty() const {
return !has_ideal_ && !has_exact_;
}
-WebString BooleanConstraint::ToString() const {
+String BooleanConstraint::ToString() const {
StringBuilder builder;
builder.Append('{');
MaybeEmitNamedBoolean(builder, has_exact_, "exact", Exact());
@@ -334,7 +334,7 @@ WebString BooleanConstraint::ToString() const {
return builder.ToString();
}
-WebMediaTrackConstraintSet::WebMediaTrackConstraintSet()
+MediaTrackConstraintSetPlatform::MediaTrackConstraintSetPlatform()
: width("width"),
height("height"),
aspect_ratio("aspectRatio"),
@@ -389,64 +389,62 @@ WebMediaTrackConstraintSet::WebMediaTrackConstraintSet()
goog_payload_padding("googPayloadPadding"),
goog_latency_ms("latencyMs") {}
-std::vector<const BaseConstraint*> WebMediaTrackConstraintSet::AllConstraints()
+Vector<const BaseConstraint*> MediaTrackConstraintSetPlatform::AllConstraints()
const {
- const BaseConstraint* temp[] = {&width,
- &height,
- &aspect_ratio,
- &frame_rate,
- &facing_mode,
- &resize_mode,
- &volume,
- &sample_rate,
- &sample_size,
- &echo_cancellation,
- &echo_cancellation_type,
- &latency,
- &channel_count,
- &device_id,
- &group_id,
- &video_kind,
- &media_stream_source,
- &disable_local_echo,
- &render_to_associated_sink,
- &goog_echo_cancellation,
- &goog_experimental_echo_cancellation,
- &goog_auto_gain_control,
- &goog_experimental_auto_gain_control,
- &goog_noise_suppression,
- &goog_highpass_filter,
- &goog_experimental_noise_suppression,
- &goog_audio_mirroring,
- &goog_da_echo_cancellation,
- &goog_noise_reduction,
- &offer_to_receive_audio,
- &offer_to_receive_video,
- &voice_activity_detection,
- &ice_restart,
- &goog_use_rtp_mux,
- &enable_dtls_srtp,
- &enable_rtp_data_channels,
- &enable_dscp,
- &enable_i_pv6,
- &goog_enable_video_suspend_below_min_bitrate,
- &goog_num_unsignalled_recv_streams,
- &goog_combined_audio_video_bwe,
- &goog_screencast_min_bitrate,
- &goog_cpu_overuse_detection,
- &goog_cpu_underuse_threshold,
- &goog_cpu_overuse_threshold,
- &goog_cpu_underuse_encode_rsd_threshold,
- &goog_cpu_overuse_encode_rsd_threshold,
- &goog_cpu_overuse_encode_usage,
- &goog_high_start_bitrate,
- &goog_payload_padding,
- &goog_latency_ms};
- const int element_count = sizeof(temp) / sizeof(temp[0]);
- return std::vector<const BaseConstraint*>(&temp[0], &temp[element_count]);
-}
-
-bool WebMediaTrackConstraintSet::IsEmpty() const {
+ return {&width,
+ &height,
+ &aspect_ratio,
+ &frame_rate,
+ &facing_mode,
+ &resize_mode,
+ &volume,
+ &sample_rate,
+ &sample_size,
+ &echo_cancellation,
+ &echo_cancellation_type,
+ &latency,
+ &channel_count,
+ &device_id,
+ &group_id,
+ &video_kind,
+ &media_stream_source,
+ &disable_local_echo,
+ &render_to_associated_sink,
+ &goog_echo_cancellation,
+ &goog_experimental_echo_cancellation,
+ &goog_auto_gain_control,
+ &goog_experimental_auto_gain_control,
+ &goog_noise_suppression,
+ &goog_highpass_filter,
+ &goog_experimental_noise_suppression,
+ &goog_audio_mirroring,
+ &goog_da_echo_cancellation,
+ &goog_noise_reduction,
+ &offer_to_receive_audio,
+ &offer_to_receive_video,
+ &voice_activity_detection,
+ &ice_restart,
+ &goog_use_rtp_mux,
+ &enable_dtls_srtp,
+ &enable_rtp_data_channels,
+ &enable_dscp,
+ &enable_i_pv6,
+ &goog_enable_video_suspend_below_min_bitrate,
+ &goog_num_unsignalled_recv_streams,
+ &goog_combined_audio_video_bwe,
+ &goog_screencast_min_bitrate,
+ &goog_cpu_overuse_detection,
+ &goog_cpu_underuse_threshold,
+ &goog_cpu_overuse_threshold,
+ &goog_cpu_underuse_encode_rsd_threshold,
+ &goog_cpu_overuse_encode_rsd_threshold,
+ &goog_cpu_overuse_encode_usage,
+ &goog_high_start_bitrate,
+ &goog_payload_padding,
+ &goog_latency_ms};
+}
+
+bool MediaTrackConstraintSetPlatform::IsEmpty() const {
for (auto* const constraint : AllConstraints()) {
if (!constraint->IsEmpty())
return false;
@@ -454,9 +452,9 @@ bool WebMediaTrackConstraintSet::IsEmpty() const {
return true;
}
-bool WebMediaTrackConstraintSet::HasMandatoryOutsideSet(
- const std::vector<std::string>& good_names,
- std::string& found_name) const {
+bool MediaTrackConstraintSetPlatform::HasMandatoryOutsideSet(
+ const Vector<String>& good_names,
+ String& found_name) const {
for (auto* const constraint : AllConstraints()) {
if (constraint->HasMandatory()) {
if (std::find(good_names.begin(), good_names.end(),
@@ -469,12 +467,12 @@ bool WebMediaTrackConstraintSet::HasMandatoryOutsideSet(
return false;
}
-bool WebMediaTrackConstraintSet::HasMandatory() const {
- std::string dummy_string;
- return HasMandatoryOutsideSet(std::vector<std::string>(), dummy_string);
+bool MediaTrackConstraintSetPlatform::HasMandatory() const {
+ String dummy_string;
+ return HasMandatoryOutsideSet(Vector<String>(), dummy_string);
}
-bool WebMediaTrackConstraintSet::HasMin() const {
+bool MediaTrackConstraintSetPlatform::HasMin() const {
for (auto* const constraint : AllConstraints()) {
if (constraint->HasMin())
return true;
@@ -482,7 +480,7 @@ bool WebMediaTrackConstraintSet::HasMin() const {
return false;
}
-bool WebMediaTrackConstraintSet::HasExact() const {
+bool MediaTrackConstraintSetPlatform::HasExact() const {
for (auto* const constraint : AllConstraints()) {
if (constraint->HasExact())
return true;
@@ -490,7 +488,7 @@ bool WebMediaTrackConstraintSet::HasExact() const {
return false;
}
-WebString WebMediaTrackConstraintSet::ToString() const {
+String MediaTrackConstraintSetPlatform::ToString() const {
StringBuilder builder;
bool first = true;
for (auto* const constraint : AllConstraints()) {
@@ -506,46 +504,46 @@ WebString WebMediaTrackConstraintSet::ToString() const {
return builder.ToString();
}
-// WebMediaConstraints
+// MediaConstraints
-void WebMediaConstraints::Assign(const WebMediaConstraints& other) {
+void MediaConstraints::Assign(const MediaConstraints& other) {
private_ = other.private_;
}
-void WebMediaConstraints::Reset() {
+void MediaConstraints::Reset() {
private_.Reset();
}
-bool WebMediaConstraints::IsEmpty() const {
+bool MediaConstraints::IsEmpty() const {
return private_.IsNull() || private_->IsEmpty();
}
-void WebMediaConstraints::Initialize() {
+void MediaConstraints::Initialize() {
DCHECK(IsNull());
- private_ = WebMediaConstraintsPrivate::Create();
+ private_ = MediaConstraintsPrivate::Create();
}
-void WebMediaConstraints::Initialize(
- const WebMediaTrackConstraintSet& basic,
- const WebVector<WebMediaTrackConstraintSet>& advanced) {
+void MediaConstraints::Initialize(
+ const MediaTrackConstraintSetPlatform& basic,
+ const Vector<MediaTrackConstraintSetPlatform>& advanced) {
DCHECK(IsNull());
- private_ = WebMediaConstraintsPrivate::Create(basic, advanced);
+ private_ = MediaConstraintsPrivate::Create(basic, advanced);
}
-const WebMediaTrackConstraintSet& WebMediaConstraints::Basic() const {
+const MediaTrackConstraintSetPlatform& MediaConstraints::Basic() const {
DCHECK(!IsNull());
return private_->Basic();
}
-const WebVector<WebMediaTrackConstraintSet>& WebMediaConstraints::Advanced()
+const Vector<MediaTrackConstraintSetPlatform>& MediaConstraints::Advanced()
const {
DCHECK(!IsNull());
return private_->Advanced();
}
-const WebString WebMediaConstraints::ToString() const {
+const String MediaConstraints::ToString() const {
if (IsNull())
- return WebString("");
+ return String("");
return private_->ToString();
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_constraints.h b/chromium/third_party/blink/renderer/platform/mediastream/media_constraints.h
new file mode 100644
index 00000000000..ed536a694d6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_constraints.h
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_CONSTRAINTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_CONSTRAINTS_H_
+
+#include "third_party/blink/public/platform/web_private_ptr.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+// Possible values of the echo canceller type constraint.
+PLATFORM_EXPORT extern const char kEchoCancellationTypeBrowser[];
+PLATFORM_EXPORT extern const char kEchoCancellationTypeAec3[];
+PLATFORM_EXPORT extern const char kEchoCancellationTypeSystem[];
+
+class MediaConstraintsPrivate;
+
+class PLATFORM_EXPORT BaseConstraint {
+ public:
+ explicit BaseConstraint(const char* name);
+ virtual ~BaseConstraint();
+ virtual bool IsEmpty() const = 0;
+ bool HasMandatory() const;
+ virtual bool HasMin() const { return false; }
+ virtual bool HasMax() const { return false; }
+ virtual bool HasExact() const = 0;
+ const char* GetName() const { return name_; }
+ virtual String ToString() const = 0;
+
+ private:
+ const char* name_;
+};
+
+// Note this class refers to the "long" WebIDL definition which is
+// equivalent to int32_t.
+class PLATFORM_EXPORT LongConstraint : public BaseConstraint {
+ public:
+ explicit LongConstraint(const char* name);
+
+ void SetMin(int32_t value) {
+ min_ = value;
+ has_min_ = true;
+ }
+
+ void SetMax(int32_t value) {
+ max_ = value;
+ has_max_ = true;
+ }
+
+ void SetExact(int32_t value) {
+ exact_ = value;
+ has_exact_ = true;
+ }
+
+ void SetIdeal(int32_t value) {
+ ideal_ = value;
+ has_ideal_ = true;
+ }
+
+ bool Matches(int32_t value) const;
+ bool IsEmpty() const override;
+ bool HasMin() const override { return has_min_; }
+ bool HasMax() const override { return has_max_; }
+ bool HasExact() const override { return has_exact_; }
+ String ToString() const override;
+ int32_t Min() const { return min_; }
+ int32_t Max() const { return max_; }
+ int32_t Exact() const { return exact_; }
+ bool HasIdeal() const { return has_ideal_; }
+ int32_t Ideal() const { return ideal_; }
+
+ private:
+ int32_t min_;
+ int32_t max_;
+ int32_t exact_;
+ int32_t ideal_;
+ unsigned has_min_ : 1;
+ unsigned has_max_ : 1;
+ unsigned has_exact_ : 1;
+ unsigned has_ideal_ : 1;
+};
+
+class PLATFORM_EXPORT DoubleConstraint : public BaseConstraint {
+ public:
+ // Permit a certain leeway when comparing floats. The offset of 0.00001
+ // is chosen based on observed behavior of doubles formatted with
+ // rtc::ToString.
+ static const double kConstraintEpsilon;
+
+ explicit DoubleConstraint(const char* name);
+
+ void SetMin(double value) {
+ min_ = value;
+ has_min_ = true;
+ }
+
+ void SetMax(double value) {
+ max_ = value;
+ has_max_ = true;
+ }
+
+ void SetExact(double value) {
+ exact_ = value;
+ has_exact_ = true;
+ }
+
+ void SetIdeal(double value) {
+ ideal_ = value;
+ has_ideal_ = true;
+ }
+
+ bool Matches(double value) const;
+ bool IsEmpty() const override;
+ bool HasMin() const override { return has_min_; }
+ bool HasMax() const override { return has_max_; }
+ bool HasExact() const override { return has_exact_; }
+ String ToString() const override;
+ double Min() const { return min_; }
+ double Max() const { return max_; }
+ double Exact() const { return exact_; }
+ bool HasIdeal() const { return has_ideal_; }
+ double Ideal() const { return ideal_; }
+
+ private:
+ double min_;
+ double max_;
+ double exact_;
+ double ideal_;
+ unsigned has_min_ : 1;
+ unsigned has_max_ : 1;
+ unsigned has_exact_ : 1;
+ unsigned has_ideal_ : 1;
+};
+
+class PLATFORM_EXPORT StringConstraint : public BaseConstraint {
+ public:
+ // String-valued options don't have min or max, but can have multiple
+ // values for ideal and exact.
+ explicit StringConstraint(const char* name);
+
+ void SetExact(const String& exact) { exact_ = {exact}; }
+
+ void SetExact(const Vector<String>& exact) { exact_ = exact; }
+
+ void SetIdeal(const String& ideal) { ideal_ = {ideal}; }
+
+ void SetIdeal(const Vector<String>& ideal) { ideal_ = ideal; }
+
+ bool Matches(String value) const;
+ bool IsEmpty() const override;
+ bool HasExact() const override { return !exact_.IsEmpty(); }
+ String ToString() const override;
+ bool HasIdeal() const { return !ideal_.IsEmpty(); }
+ const Vector<String>& Exact() const;
+ const Vector<String>& Ideal() const;
+
+ private:
+ Vector<String> exact_;
+ Vector<String> ideal_;
+};
+
+class PLATFORM_EXPORT BooleanConstraint : public BaseConstraint {
+ public:
+ explicit BooleanConstraint(const char* name);
+
+ bool Exact() const { return exact_; }
+ bool Ideal() const { return ideal_; }
+ void SetIdeal(bool value) {
+ ideal_ = value;
+ has_ideal_ = true;
+ }
+
+ void SetExact(bool value) {
+ exact_ = value;
+ has_exact_ = true;
+ }
+
+ bool Matches(bool value) const;
+ bool IsEmpty() const override;
+ bool HasExact() const override { return has_exact_; }
+ String ToString() const override;
+ bool HasIdeal() const { return has_ideal_; }
+
+ private:
+ unsigned ideal_ : 1;
+ unsigned exact_ : 1;
+ unsigned has_ideal_ : 1;
+ unsigned has_exact_ : 1;
+};
+
+struct MediaTrackConstraintSetPlatform {
+ public:
+ PLATFORM_EXPORT MediaTrackConstraintSetPlatform();
+
+ LongConstraint width;
+ LongConstraint height;
+ DoubleConstraint aspect_ratio;
+ DoubleConstraint frame_rate;
+ StringConstraint facing_mode;
+ StringConstraint resize_mode;
+ DoubleConstraint volume;
+ LongConstraint sample_rate;
+ LongConstraint sample_size;
+ BooleanConstraint echo_cancellation;
+ StringConstraint echo_cancellation_type;
+ DoubleConstraint latency;
+ LongConstraint channel_count;
+ StringConstraint device_id;
+ BooleanConstraint disable_local_echo;
+ StringConstraint group_id;
+ // https://w3c.github.io/mediacapture-depth/#mediatrackconstraints
+ StringConstraint video_kind;
+ // Constraints not exposed in Blink at the moment, only through
+ // the legacy name interface.
+ StringConstraint media_stream_source; // tab, screen, desktop, system
+ BooleanConstraint render_to_associated_sink;
+ BooleanConstraint goog_echo_cancellation;
+ BooleanConstraint goog_experimental_echo_cancellation;
+ BooleanConstraint goog_auto_gain_control;
+ BooleanConstraint goog_experimental_auto_gain_control;
+ BooleanConstraint goog_noise_suppression;
+ BooleanConstraint goog_highpass_filter;
+ BooleanConstraint goog_experimental_noise_suppression;
+ BooleanConstraint goog_audio_mirroring;
+ BooleanConstraint goog_da_echo_cancellation;
+ BooleanConstraint goog_noise_reduction;
+ LongConstraint offer_to_receive_audio;
+ LongConstraint offer_to_receive_video;
+ BooleanConstraint voice_activity_detection;
+ BooleanConstraint ice_restart;
+ BooleanConstraint goog_use_rtp_mux;
+ BooleanConstraint enable_dtls_srtp;
+ BooleanConstraint enable_rtp_data_channels;
+ BooleanConstraint enable_dscp;
+ BooleanConstraint enable_i_pv6;
+ BooleanConstraint goog_enable_video_suspend_below_min_bitrate;
+ LongConstraint goog_num_unsignalled_recv_streams;
+ BooleanConstraint goog_combined_audio_video_bwe;
+ LongConstraint goog_screencast_min_bitrate;
+ BooleanConstraint goog_cpu_overuse_detection;
+ LongConstraint goog_cpu_underuse_threshold;
+ LongConstraint goog_cpu_overuse_threshold;
+ LongConstraint goog_cpu_underuse_encode_rsd_threshold;
+ LongConstraint goog_cpu_overuse_encode_rsd_threshold;
+ BooleanConstraint goog_cpu_overuse_encode_usage;
+ LongConstraint goog_high_start_bitrate;
+ BooleanConstraint goog_payload_padding;
+ LongConstraint goog_latency_ms;
+
+ PLATFORM_EXPORT bool IsEmpty() const;
+ PLATFORM_EXPORT bool HasMandatory() const;
+ PLATFORM_EXPORT bool HasMandatoryOutsideSet(const Vector<String>&,
+ String&) const;
+ PLATFORM_EXPORT bool HasMin() const;
+ PLATFORM_EXPORT bool HasExact() const;
+ PLATFORM_EXPORT String ToString() const;
+
+ private:
+ Vector<const BaseConstraint*> AllConstraints() const;
+};
+
+class MediaConstraints {
+ public:
+ MediaConstraints() = default;
+ MediaConstraints(const MediaConstraints& other) { Assign(other); }
+ ~MediaConstraints() { Reset(); }
+
+ MediaConstraints& operator=(const MediaConstraints& other) {
+ Assign(other);
+ return *this;
+ }
+
+ PLATFORM_EXPORT void Assign(const MediaConstraints&);
+
+ PLATFORM_EXPORT void Reset();
+ bool IsNull() const { return private_.IsNull(); }
+ PLATFORM_EXPORT bool IsEmpty() const;
+
+ PLATFORM_EXPORT void Initialize();
+ PLATFORM_EXPORT void Initialize(
+ const MediaTrackConstraintSetPlatform& basic,
+ const Vector<MediaTrackConstraintSetPlatform>& advanced);
+
+ PLATFORM_EXPORT const MediaTrackConstraintSetPlatform& Basic() const;
+ PLATFORM_EXPORT const Vector<MediaTrackConstraintSetPlatform>& Advanced()
+ const;
+
+ PLATFORM_EXPORT const String ToString() const;
+
+ private:
+ WebPrivatePtr<MediaConstraintsPrivate> private_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_CONSTRAINTS_H_
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h
new file mode 100644
index 00000000000..9ff7615bb73
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h
@@ -0,0 +1,158 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_AUDIO_DELIVERER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_AUDIO_DELIVERER_H_
+
+#include <algorithm>
+
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "base/trace_event/trace_event.h"
+#include "media/base/audio_parameters.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+// Template containing functionality common to both MediaStreamAudioSource and
+// MediaStreamAudioTrack. This is used for managing the connections between
+// objects through which audio data flows, and doing so in a thread-safe manner.
+//
+// The Consumer parameter of the template is the type of the objects to which
+// audio data is delivered: MediaStreamAudioTrack or MediaStreamAudioSink. It's
+// assumed the Consumer class defines methods named OnSetFormat() and OnData()
+// that have the same signature as the ones defined in this template.
+// MediaStreamAudioDeliverer will always guarantee the Consumer's OnSetFormat()
+// and OnData() methods are called sequentially.
+template <typename Consumer>
+class MediaStreamAudioDeliverer {
+ public:
+ MediaStreamAudioDeliverer() {}
+ ~MediaStreamAudioDeliverer() {}
+
+ // Returns the current audio parameters. These will be invalid before the
+ // first call to OnSetFormat(). This method is thread-safe.
+ media::AudioParameters GetAudioParameters() const {
+ base::AutoLock auto_lock(params_lock_);
+ return params_;
+ }
+
+ // Begin delivering audio to |consumer|. The caller must guarantee |consumer|
+ // is not destroyed until after calling RemoveConsumer(consumer). This method
+ // must be called on the main thread.
+ void AddConsumer(Consumer* consumer) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(consumer);
+ base::AutoLock auto_lock(consumers_lock_);
+ DCHECK(!base::Contains(consumers_, consumer));
+ DCHECK(!base::Contains(pending_consumers_, consumer));
+ pending_consumers_.push_back(consumer);
+ }
+
+ // Stop delivering audio to |consumer|. Returns true if |consumer| was the
+ // last consumer removed, false otherwise. When this method returns, no
+ // further calls will be made to OnSetFormat() or OnData() on any thread.
+ // This method must be called on the main thread.
+ bool RemoveConsumer(Consumer* consumer) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ base::AutoLock auto_lock(consumers_lock_);
+ const bool had_consumers =
+ !consumers_.IsEmpty() || !pending_consumers_.IsEmpty();
+ auto it = std::find(consumers_.begin(), consumers_.end(), consumer);
+ if (it != consumers_.end()) {
+ consumers_.erase(it);
+ } else {
+ it = std::find(pending_consumers_.begin(), pending_consumers_.end(),
+ consumer);
+ if (it != pending_consumers_.end())
+ pending_consumers_.erase(it);
+ }
+ return had_consumers && consumers_.IsEmpty() &&
+ pending_consumers_.IsEmpty();
+ }
+
+ // Returns the current list of connected Consumers. This is normally used to
+ // send a notification to all consumers. This method must be called on the
+ // main thread.
+ void GetConsumerList(Vector<Consumer*>* consumer_list) const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ base::AutoLock auto_lock(consumers_lock_);
+ *consumer_list = consumers_;
+ consumer_list->AppendRange(pending_consumers_.begin(),
+ pending_consumers_.end());
+ }
+
+ // Change the format of the audio passed in the next call to OnData(). This
+ // method may be called on any thread but, logically, should only be called
+ // between calls to OnData().
+ void OnSetFormat(const media::AudioParameters& params) {
+ DCHECK(params.IsValid());
+ base::AutoLock auto_lock(consumers_lock_);
+ {
+ base::AutoLock auto_params_lock(params_lock_);
+ if (params_.Equals(params))
+ return;
+ params_ = params;
+ }
+ pending_consumers_.AppendRange(consumers_.begin(), consumers_.end());
+ consumers_.clear();
+ }
+
+ // Deliver data to all consumers. This method may be called on any thread.
+ void OnData(const media::AudioBus& audio_bus,
+ base::TimeTicks reference_time) {
+ TRACE_EVENT1("audio", "MediaStreamAudioDeliverer::OnData",
+ "reference time (ms)",
+ (reference_time - base::TimeTicks()).InMillisecondsF());
+ base::AutoLock auto_lock(consumers_lock_);
+
+ // Call OnSetFormat() for all pending consumers and move them to the
+ // active-delivery list.
+ if (!pending_consumers_.IsEmpty()) {
+ const media::AudioParameters params = GetAudioParameters();
+ DCHECK(params.IsValid());
+ for (Consumer* consumer : pending_consumers_)
+ consumer->OnSetFormat(params);
+ consumers_.AppendRange(pending_consumers_.begin(),
+ pending_consumers_.end());
+ pending_consumers_.clear();
+ }
+
+ // Deliver the audio data to each consumer.
+ for (Consumer* consumer : consumers_)
+ consumer->OnData(audio_bus, reference_time);
+ }
+
+ private:
+ // In debug builds, check that all methods that could cause object graph or
+ // data flow changes are being called on the main thread.
+ THREAD_CHECKER(thread_checker_);
+
+ // Protects concurrent access to |pending_consumers_| and |consumers_|.
+ mutable base::Lock consumers_lock_;
+
+ // Any consumers needing a call to OnSetFormat(), to be notified of the
+ // changed audio format, are placed in this list. This includes consumers
+ // added via AddConsumer() that need to have an initial OnSetFormat() call
+ // before audio data is first delivered. Consumers are moved from this list to
+ // |consumers_| on the audio thread.
+ Vector<Consumer*> pending_consumers_;
+
+ // Consumers that are up to date on the current audio format and are receiving
+ // audio data are placed in this list.
+ Vector<Consumer*> consumers_;
+
+ // Protects concurrent access to |params_|.
+ mutable base::Lock params_lock_;
+
+ // Specifies the current format of the audio passing through this
+ // MediaStreamAudioDeliverer.
+ media::AudioParameters params_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioDeliverer);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_AUDIO_DELIVERER_H_
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
index 923bc2a2a47..f25d1e2abbe 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
@@ -15,7 +15,7 @@
#include "media/base/audio_point.h"
#include "media/base/audio_processing.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
-#include "third_party/blink/public/platform/web_media_constraints.h"
+#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/media_stream_interface.h"
#include "third_party/webrtc/media/base/media_channel.h"
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
index 783587fdaee..4c60ce0cff0 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.cc
@@ -6,17 +6,27 @@
#include "base/bind.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
+namespace {
+
+void SendLogMessage(const std::string& message) {
+ blink::WebRtcLogMessage("MSAS::" + message);
+}
+
+} // namespace
+
const int kMaxAudioLatencyMs = 5000;
static_assert(std::numeric_limits<int>::max() / media::limits::kMaxSampleRate >
kMaxAudioLatencyMs,
@@ -45,8 +55,9 @@ MediaStreamAudioSource::MediaStreamAudioSource(
disable_local_echo_(disable_local_echo),
is_stopped_(false),
task_runner_(std::move(task_runner)) {
- DVLOG(1) << "MediaStreamAudioSource@" << this << "::MediaStreamAudioSource("
- << (is_local_source_ ? "local" : "remote") << " source)";
+ SendLogMessage(base::StringPrintf(
+ "MediaStreamAudioSource([this=%p] {is_local_source=%s})", this,
+ (is_local_source ? "local" : "remote")));
}
MediaStreamAudioSource::MediaStreamAudioSource(
@@ -58,7 +69,8 @@ MediaStreamAudioSource::MediaStreamAudioSource(
MediaStreamAudioSource::~MediaStreamAudioSource() {
DCHECK(task_runner_->BelongsToCurrentThread());
- DVLOG(1) << "MediaStreamAudioSource@" << this << " is being destroyed.";
+ SendLogMessage(
+ base::StringPrintf("~MediaStreamAudioSource([this=%p])", this));
}
// static
@@ -74,6 +86,8 @@ bool MediaStreamAudioSource::ConnectToTrack(
const WebMediaStreamTrack& blink_track) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!blink_track.IsNull());
+ SendLogMessage(base::StringPrintf("ConnectToTrack({track_id=%s})",
+ blink_track.Id().Utf8().c_str()));
// Sanity-check that there is not already a MediaStreamAudioTrack instance
// associated with |blink_track|.
@@ -167,6 +181,8 @@ void MediaStreamAudioSource::DoChangeSource(
std::unique_ptr<MediaStreamAudioTrack>
MediaStreamAudioSource::CreateMediaStreamAudioTrack(const std::string& id) {
DCHECK(task_runner_->BelongsToCurrentThread());
+ SendLogMessage(
+ base::StringPrintf("CreateMediaStreamAudioTrack({id=%s})", id.c_str()));
return std::unique_ptr<MediaStreamAudioTrack>(
new MediaStreamAudioTrack(is_local_source()));
}
@@ -190,9 +206,10 @@ void MediaStreamAudioSource::ChangeSourceImpl(
}
void MediaStreamAudioSource::SetFormat(const media::AudioParameters& params) {
- DVLOG(1) << "MediaStreamAudioSource@" << this << "::SetFormat("
- << params.AsHumanReadableString() << "), was previously set to {"
- << deliverer_.GetAudioParameters().AsHumanReadableString() << "}.";
+ SendLogMessage(base::StringPrintf(
+ "SetFormat([this=%p] {params=[%s]}, {old_params=[%s]})", this,
+ params.AsHumanReadableString().c_str(),
+ deliverer_.GetAudioParameters().AsHumanReadableString().c_str()));
deliverer_.OnSetFormat(params);
}
@@ -210,6 +227,7 @@ void MediaStreamAudioSource::DoStopSource() {
void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) {
DCHECK(task_runner_->BelongsToCurrentThread());
+ SendLogMessage(base::StringPrintf("StopAudioDeliveryTo([this=%p])", this));
const bool did_remove_last_track = deliverer_.RemoveConsumer(track);
DVLOG(1) << "Removed MediaStreamAudioTrack@" << track
@@ -222,8 +240,8 @@ void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) {
}
void MediaStreamAudioSource::StopSourceOnError(const std::string& why) {
- VLOG(1) << why;
-
+ SendLogMessage(base::StringPrintf("StopSourceOnError([this=%p] {why=%s})",
+ this, why.c_str()));
// Stop source when error occurs.
PostCrossThreadTask(
*task_runner_, FROM_HERE,
@@ -232,7 +250,8 @@ void MediaStreamAudioSource::StopSourceOnError(const std::string& why) {
}
void MediaStreamAudioSource::SetMutedState(bool muted_state) {
- DVLOG(3) << "MediaStreamAudioSource::SetMutedState state=" << muted_state;
+ SendLogMessage(base::StringPrintf("SetMutedState([this=%p] {muted_state=%s})",
+ this, (muted_state ? "true" : "false")));
PostCrossThreadTask(
*task_runner_, FROM_HERE,
WTF::CrossThreadBindOnce(&WebPlatformMediaStreamSource::SetSourceMuted,
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
index 24a2227e573..1dfc87329a2 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h
@@ -12,10 +12,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "media/base/limits.h"
-#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_deliverer.h"
#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_track.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
index 1b6c6e1578f..24f05b8fc4e 100644
--- a/chromium/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_track.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
@@ -2,27 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
#include <utility>
-#include <vector>
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "media/base/audio_bus.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
namespace blink {
+namespace {
+
+void SendLogMessage(const std::string& message) {
+ blink::WebRtcLogMessage("MSAT::" + message);
+}
+
+} // namespace
+
MediaStreamAudioTrack::MediaStreamAudioTrack(bool is_local_track)
: WebPlatformMediaStreamTrack(is_local_track), is_enabled_(1) {
- DVLOG(1) << "MediaStreamAudioTrack@" << this << "::MediaStreamAudioTrack("
- << (is_local_track ? "local" : "remote") << " track)";
+ SendLogMessage(
+ base::StringPrintf("MediaStreamAudioTrack([this=%p] {is_local_track=%s})",
+ this, (is_local_track ? "true" : "false")));
}
MediaStreamAudioTrack::~MediaStreamAudioTrack() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DVLOG(1) << "MediaStreamAudioTrack@" << this << " is being destroyed.";
+ SendLogMessage(base::StringPrintf("~MediaStreamAudioTrack([this=%p])", this));
Stop();
}
@@ -38,9 +48,7 @@ MediaStreamAudioTrack* MediaStreamAudioTrack::From(
void MediaStreamAudioTrack::AddSink(WebMediaStreamAudioSink* sink) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- DVLOG(1) << "Adding WebMediaStreamAudioSink@" << sink
- << " to MediaStreamAudioTrack@" << this << '.';
+ SendLogMessage(base::StringPrintf("AddSink([this=%p])", this));
// If the track has already stopped, just notify the sink of this fact without
// adding it.
@@ -55,9 +63,8 @@ void MediaStreamAudioTrack::AddSink(WebMediaStreamAudioSink* sink) {
void MediaStreamAudioTrack::RemoveSink(WebMediaStreamAudioSink* sink) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ SendLogMessage(base::StringPrintf("RemoveSink([this=%p])", this));
deliverer_.RemoveConsumer(sink);
- DVLOG(1) << "Removed WebMediaStreamAudioSink@" << sink
- << " from MediaStreamAudioTrack@" << this << '.';
}
media::AudioParameters MediaStreamAudioTrack::GetOutputFormat() const {
@@ -66,15 +73,15 @@ media::AudioParameters MediaStreamAudioTrack::GetOutputFormat() const {
void MediaStreamAudioTrack::SetEnabled(bool enabled) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DVLOG(1) << "MediaStreamAudioTrack@" << this << "::SetEnabled("
- << (enabled ? 'Y' : 'N') << ')';
+ SendLogMessage(base::StringPrintf("SetEnabled([this=%p] {enabled=%s})", this,
+ (enabled ? "true" : "false")));
const bool previously_enabled =
!!base::subtle::NoBarrier_AtomicExchange(&is_enabled_, enabled ? 1 : 0);
if (enabled == previously_enabled)
return;
- std::vector<WebMediaStreamAudioSink*> sinks_to_notify;
+ Vector<WebMediaStreamAudioSink*> sinks_to_notify;
deliverer_.GetConsumerList(&sinks_to_notify);
for (WebMediaStreamAudioSink* sink : sinks_to_notify)
sink->OnEnabledChanged(enabled);
@@ -84,7 +91,7 @@ void MediaStreamAudioTrack::SetContentHint(
WebMediaStreamTrack::ContentHintType content_hint) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- std::vector<WebMediaStreamAudioSink*> sinks_to_notify;
+ Vector<WebMediaStreamAudioSink*> sinks_to_notify;
deliverer_.GetConsumerList(&sinks_to_notify);
for (WebMediaStreamAudioSink* sink : sinks_to_notify)
sink->OnContentHintChanged(content_hint);
@@ -98,18 +105,18 @@ void MediaStreamAudioTrack::Start(base::OnceClosure stop_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!stop_callback.is_null());
DCHECK(stop_callback_.is_null());
- DVLOG(1) << "Starting MediaStreamAudioTrack@" << this << '.';
+ SendLogMessage(base::StringPrintf("Start([this=%p])", this));
stop_callback_ = std::move(stop_callback);
}
void MediaStreamAudioTrack::StopAndNotify(base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DVLOG(1) << "Stopping MediaStreamAudioTrack@" << this << '.';
+ SendLogMessage(base::StringPrintf("StopAndNotify([this=%p])", this));
if (!stop_callback_.is_null())
std::move(stop_callback_).Run();
- std::vector<WebMediaStreamAudioSink*> sinks_to_end;
+ Vector<WebMediaStreamAudioSink*> sinks_to_end;
deliverer_.GetConsumerList(&sinks_to_end);
for (WebMediaStreamAudioSink* sink : sinks_to_end) {
deliverer_.RemoveConsumer(sink);
@@ -122,11 +129,22 @@ void MediaStreamAudioTrack::StopAndNotify(base::OnceClosure callback) {
}
void MediaStreamAudioTrack::OnSetFormat(const media::AudioParameters& params) {
+ SendLogMessage(base::StringPrintf("OnSetFormat([this=%p] {params: [%s]})",
+ this,
+ params.AsHumanReadableString().c_str()));
deliverer_.OnSetFormat(params);
}
void MediaStreamAudioTrack::OnData(const media::AudioBus& audio_bus,
base::TimeTicks reference_time) {
+ if (!received_audio_callback_) {
+ // Add log message with unique this pointer id to mark the audio track as
+ // alive at the first data callback.
+ SendLogMessage(base::StringPrintf(
+ "OnData([this=%p] => (audio track is alive))", this));
+ received_audio_callback_ = true;
+ }
+
// Note: Using NoBarrier_Load because the timing of when the audio thread sees
// a changed |is_enabled_| value can be relaxed.
const bool deliver_data = !!base::subtle::NoBarrier_Load(&is_enabled_);
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
new file mode 100644
index 00000000000..5981a2aa271
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
@@ -0,0 +1,126 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_AUDIO_TRACK_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_AUDIO_TRACK_H_
+
+#include <memory>
+
+#include "base/atomicops.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_track.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_deliverer.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+class WebMediaStreamAudioSink;
+class MediaStreamAudioSource;
+
+// Provides the part of the audio pipeline delivering audio from a
+// MediaStreamAudioSource to one or more WebMediaStreamAudioSinks. An instance
+// of this class is owned by WebMediaStreamTrack, and clients should use
+// From() to gain access to a MediaStreamAudioTrack.
+class PLATFORM_EXPORT MediaStreamAudioTrack
+ : public WebPlatformMediaStreamTrack {
+ public:
+ explicit MediaStreamAudioTrack(bool is_local_track);
+
+ ~MediaStreamAudioTrack() override;
+
+ // Returns the MediaStreamAudioTrack instance owned by the given blink |track|
+ // or null.
+ static MediaStreamAudioTrack* From(const WebMediaStreamTrack& track);
+
+ // Provides a weak reference to this MediaStreamAudioTrack which is
+ // invalidated when Stop() is called. The weak pointer may only be
+ // dereferenced on the main thread.
+ base::WeakPtr<MediaStreamAudioTrack> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ // Add a sink to the track. This function will trigger a OnSetFormat()
+ // call on the |sink| before the first chunk of audio is delivered.
+ void AddSink(WebMediaStreamAudioSink* sink);
+
+ // Remove a sink from the track. When this method returns, the sink's
+ // OnSetFormat() and OnData() methods will not be called again on any thread.
+ void RemoveSink(WebMediaStreamAudioSink* sink);
+
+ // Returns the output format of the capture source. May return an invalid
+ // AudioParameters if the format is not yet available.
+ // Called on the main render thread.
+ // TODO(tommi): This method appears to only be used by Pepper and in fact
+ // does not appear to be necessary there. We should remove it since it adds
+ // to the complexity of all types of audio tracks+source implementations.
+ // https://crbug.com/577874
+ media::AudioParameters GetOutputFormat() const;
+
+ // Halts the flow of audio data from the source (and to the sinks), and then
+ // notifies all sinks of the "ended" state.
+ void StopAndNotify(base::OnceClosure callback) final;
+
+ // MediaStreamTrack override.
+ void SetEnabled(bool enabled) override;
+ void SetContentHint(
+ WebMediaStreamTrack::ContentHintType content_hint) override;
+
+ // Returns a unique class identifier. Some subclasses override and use this
+ // method to provide safe down-casting to their type.
+ virtual void* GetClassIdentifier() const;
+
+ private:
+ friend class MediaStreamAudioSource;
+ friend class MediaStreamAudioDeliverer<MediaStreamAudioTrack>;
+
+ // Called by MediaStreamAudioSource to notify this track that the flow of
+ // audio data has started from the source. |stop_callback| is run by Stop()
+ // when the source must halt the flow of audio data to this track.
+ void Start(base::OnceClosure stop_callback);
+
+ // Called by the MediaStreamAudioDeliverer to notify this track of an audio
+ // format change. In turn, all WebMediaStreamAudioSinks will be notified
+ // before the next chunk of audio is delivered to them.
+ void OnSetFormat(const media::AudioParameters& params);
+
+ // Called by the MediaStreamAudioDeliverer to deliver audio data to this
+ // track, which in turn delivers the audio to one or more
+ // WebMediaStreamAudioSinks. While this track is disabled, silent audio will
+ // be delivered to the sinks instead of the content of |audio_bus|.
+ void OnData(const media::AudioBus& audio_bus, base::TimeTicks reference_time);
+
+ private:
+ // In debug builds, check that all methods that could cause object graph
+ // or data flow changes are being called on the main thread.
+ THREAD_CHECKER(thread_checker_);
+
+ // Callback provided to Start() which is run when the audio flow must halt.
+ base::OnceClosure stop_callback_;
+
+ // Manages sinks connected to this track and the audio format and data flow.
+ MediaStreamAudioDeliverer<WebMediaStreamAudioSink> deliverer_;
+
+ // While false (0), silent audio is delivered to the sinks.
+ base::subtle::Atomic32 is_enabled_;
+
+ // Buffer used to deliver silent audio data while this track is disabled.
+ std::unique_ptr<media::AudioBus> silent_bus_;
+
+ // Set to true once at first audio callback after calling Start().
+ // Only used for logging purposes.
+ bool received_audio_callback_ = false;
+
+ // Provides weak pointers that are valid until Stop() is called.
+ base::WeakPtrFactory<MediaStreamAudioTrack> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioTrack);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_MEDIA_STREAM_AUDIO_TRACK_H_
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
index 0e48a233069..bec6546fb21 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
@@ -132,7 +132,7 @@ void MediaStreamComponent::AudioSourceProviderImpl::ProvideInput(
web_audio_source_provider_->ProvideInput(web_audio_data, frames_to_process);
}
-void MediaStreamComponent::Trace(blink::Visitor* visitor) {
+void MediaStreamComponent::Trace(Visitor* visitor) {
visitor->Trace(source_);
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h
index b4643ea7cb6..6515d8bb8df 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h
@@ -35,10 +35,10 @@
#include <memory>
#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_track.h"
-#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
@@ -84,8 +84,8 @@ class PLATFORM_EXPORT MediaStreamComponent final
void SetMuted(bool muted) { muted_ = muted; }
WebMediaStreamTrack::ContentHintType ContentHint() { return content_hint_; }
void SetContentHint(WebMediaStreamTrack::ContentHintType);
- const WebMediaConstraints& Constraints() const { return constraints_; }
- void SetConstraints(const WebMediaConstraints& constraints) {
+ const MediaConstraints& Constraints() const { return constraints_; }
+ void SetConstraints(const MediaConstraints& constraints) {
constraints_ = constraints;
}
AudioSourceProvider* GetAudioSourceProvider() { return &source_provider_; }
@@ -102,7 +102,7 @@ class PLATFORM_EXPORT MediaStreamComponent final
}
void GetSettings(WebMediaStreamTrack::Settings&);
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
private:
// AudioSourceProviderImpl wraps a WebAudioSourceProvider::provideInput()
@@ -135,7 +135,7 @@ class PLATFORM_EXPORT MediaStreamComponent final
bool muted_ = false;
WebMediaStreamTrack::ContentHintType content_hint_ =
WebMediaStreamTrack::ContentHintType::kNone;
- WebMediaConstraints constraints_;
+ MediaConstraints constraints_;
std::unique_ptr<WebPlatformMediaStreamTrack> platform_track_;
};
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
index 0f3c348d4aa..970dd08e6f6 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
@@ -170,7 +170,7 @@ MediaStreamDescriptor::MediaStreamDescriptor(
video_components_.push_back((*iter));
}
-void MediaStreamDescriptor::Trace(blink::Visitor* visitor) {
+void MediaStreamDescriptor::Trace(Visitor* visitor) {
visitor->Trace(audio_components_);
visitor->Trace(video_components_);
visitor->Trace(client_);
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
index ea3e04c6d18..80141ceea79 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
@@ -51,7 +51,7 @@ class PLATFORM_EXPORT MediaStreamDescriptorClient
virtual void StreamEnded() = 0;
virtual void AddTrackByComponentAndFireEvents(MediaStreamComponent*) = 0;
virtual void RemoveTrackByComponentAndFireEvents(MediaStreamComponent*) = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
class PLATFORM_EXPORT MediaStreamDescriptor final
@@ -111,7 +111,7 @@ class PLATFORM_EXPORT MediaStreamDescriptor final
void AddObserver(WebMediaStreamObserver*);
void RemoveObserver(WebMediaStreamObserver*);
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
private:
Member<MediaStreamDescriptorClient> client_;
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
index df7371c24a7..a80d97c398f 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -37,6 +38,36 @@ namespace blink {
namespace {
+void SendLogMessage(const std::string& message) {
+ blink::WebRtcLogMessage("MSS::" + message);
+}
+
+const char* StreamTypeToString(MediaStreamSource::StreamType type) {
+ switch (type) {
+ case MediaStreamSource::kTypeAudio:
+ return "Audio";
+ case MediaStreamSource::kTypeVideo:
+ return "Video";
+ default:
+ NOTREACHED();
+ }
+ return "Invalid";
+}
+
+const char* ReadyStateToString(MediaStreamSource::ReadyState state) {
+ switch (state) {
+ case MediaStreamSource::kReadyStateLive:
+ return "Live";
+ case MediaStreamSource::kReadyStateMuted:
+ return "Muted";
+ case MediaStreamSource::kReadyStateEnded:
+ return "Ended";
+ default:
+ NOTREACHED();
+ }
+ return "Invalid";
+}
+
void GetSourceSettings(const blink::WebMediaStreamSource& web_source,
blink::WebMediaStreamTrack::Settings& settings) {
blink::MediaStreamAudioSource* const source =
@@ -68,13 +99,28 @@ MediaStreamSource::MediaStreamSource(const String& id,
name_(name),
remote_(remote),
ready_state_(ready_state),
- requires_consumer_(requires_consumer) {}
+ requires_consumer_(requires_consumer) {
+ SendLogMessage(
+ String::Format(
+ "MediaStreamSource({id=%s}, {type=%s}, {name=%s}, {remote=%d}, "
+ "{ready_state=%s}",
+ id.Utf8().c_str(), StreamTypeToString(type), name.Utf8().c_str(),
+ remote, ReadyStateToString(ready_state))
+ .Utf8());
+}
void MediaStreamSource::SetGroupId(const String& group_id) {
+ SendLogMessage(
+ String::Format("SetGroupId({group_id=%s})", group_id.Utf8().c_str())
+ .Utf8());
group_id_ = group_id;
}
void MediaStreamSource::SetReadyState(ReadyState ready_state) {
+ SendLogMessage(String::Format("SetReadyState({id=%s}, {ready_state=%s})",
+ Id().Utf8().c_str(),
+ ReadyStateToString(ready_state))
+ .Utf8());
if (ready_state_ != kReadyStateEnded && ready_state_ != ready_state) {
ready_state_ = ready_state;
@@ -171,6 +217,12 @@ void MediaStreamSource::GetSettings(WebMediaStreamTrack::Settings& settings) {
void MediaStreamSource::SetAudioFormat(size_t number_of_channels,
float sample_rate) {
+ SendLogMessage(
+ String::Format(
+ "SetAudioFormat({id=%s}, {number_of_channels=%d}, {sample_rate=%f})",
+ Id().Utf8().c_str(), static_cast<int>(number_of_channels),
+ sample_rate)
+ .Utf8());
DCHECK(requires_consumer_);
MutexLocker locker(audio_consumers_lock_);
for (AudioDestinationConsumer* consumer : audio_consumers_)
@@ -184,7 +236,7 @@ void MediaStreamSource::ConsumeAudio(AudioBus* bus, size_t number_of_frames) {
consumer->ConsumeAudio(bus, number_of_frames);
}
-void MediaStreamSource::Trace(blink::Visitor* visitor) {
+void MediaStreamSource::Trace(Visitor* visitor) {
visitor->Trace(observers_);
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h
index 2e4edff6f0b..2cc1f159f49 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h
@@ -37,10 +37,10 @@
#include "base/optional.h"
#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h"
-#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/renderer/platform/audio/audio_destination_consumer.h"
+#include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -121,7 +121,7 @@ class PLATFORM_EXPORT MediaStreamSource final
return audio_consumers_;
}
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
void Dispose();
@@ -138,7 +138,7 @@ class PLATFORM_EXPORT MediaStreamSource final
HashSet<AudioDestinationConsumer*> audio_consumers_
GUARDED_BY(audio_consumers_lock_);
std::unique_ptr<WebPlatformMediaStreamSource> platform_source_;
- WebMediaConstraints constraints_;
+ MediaConstraints constraints_;
WebMediaStreamSource::Capabilities capabilities_;
base::Optional<EchoCancellationMode> echo_cancellation_mode_;
base::Optional<bool> auto_gain_control_;
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h
new file mode 100644
index 00000000000..d6184f918fb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_WEBAUDIO_DESTINATION_CONSUMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_WEBAUDIO_DESTINATION_CONSUMER_H_
+
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class WebAudioDestinationConsumer {
+ public:
+ virtual ~WebAudioDestinationConsumer() = default;
+
+ virtual void SetFormat(size_t number_of_channels, float sample_rate) = 0;
+
+ // The size of the vector is the number of audio channels, and
+ // |number_of_frames| is the number of audio frames in the (possibly
+ // multi-channel) buffer in a planar format.
+ virtual void ConsumeAudio(const Vector<const float*>&,
+ size_t number_of_frames) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIASTREAM_WEBAUDIO_DESTINATION_CONSUMER_H_
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc
index 8d294a3c5ed..7ae4e9ea83b 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.cc
@@ -6,9 +6,9 @@
#include <utility>
-#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -17,8 +17,9 @@ WebAudioMediaStreamSource::WebAudioMediaStreamSource(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: MediaStreamAudioSource(std::move(task_runner), false /* is_remote */),
is_registered_consumer_(false),
- fifo_(base::Bind(&WebAudioMediaStreamSource::DeliverRebufferedAudio,
- base::Unretained(this))),
+ fifo_(ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+ &WebAudioMediaStreamSource::DeliverRebufferedAudio,
+ WTF::CrossThreadUnretained(this)))),
blink_source_(*blink_source) {
DVLOG(1) << "WebAudioMediaStreamSource::WebAudioMediaStreamSource()";
}
@@ -83,7 +84,7 @@ void WebAudioMediaStreamSource::EnsureSourceIsStopped() {
}
void WebAudioMediaStreamSource::ConsumeAudio(
- const WebVector<const float*>& audio_data,
+ const Vector<const float*>& audio_data,
size_t number_of_frames) {
// TODO(miu): Plumbing is needed to determine the actual capture timestamp
// of the audio, instead of just snapshotting base::TimeTicks::Now(), for
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h
index e5de09a72b2..afdfc6e7c58 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/webaudio_media_stream_source.h
@@ -10,10 +10,10 @@
#include "base/time/time.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_push_fifo.h"
-#include "third_party/blink/public/platform/web_audio_destination_consumer.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
@@ -39,7 +39,7 @@ class PLATFORM_EXPORT WebAudioMediaStreamSource final
// concurrently across threads, but these methods could be called on any
// thread.
void SetFormat(size_t number_of_channels, float sample_rate) override;
- void ConsumeAudio(const WebVector<const float*>& audio_data,
+ void ConsumeAudio(const Vector<const float*>& audio_data,
size_t number_of_frames) override;
// Called by AudioPushFifo zero or more times during the call to
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h b/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h
index 10b339edd88..fde61b92783 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h
+++ b/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h
@@ -53,7 +53,7 @@ class PLATFORM_EXPORT ArchiveResource final
const AtomicString& MimeType() const { return mime_type_; }
const AtomicString& TextEncoding() const { return text_encoding_; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
KURL url_;
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
index 94d98b13a53..9021739bd00 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
@@ -440,7 +440,7 @@ ArchiveResource* MHTMLArchive::SubresourceForURL(const KURL& url) const {
return subresources_.at(url.GetString());
}
-void MHTMLArchive::Trace(blink::Visitor* visitor) {
+void MHTMLArchive::Trace(Visitor* visitor) {
visitor->Trace(main_resource_);
visitor->Trace(subresources_);
}
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h
index 985d346276c..c1edc8d5764 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h
@@ -105,7 +105,7 @@ class PLATFORM_EXPORT MHTMLArchive final
// The purported creation date (as expressed by the Date: header).
base::Time Date() const { return date_; }
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
blink::mojom::MHTMLLoadResult LoadResult() const { return load_result_; }
private:
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
index f08d30dab9c..c055297ed18 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
@@ -124,7 +124,7 @@ class MIMEHeader final : public GarbageCollected<MIMEHeader> {
String EndOfPartBoundary() const { return end_of_part_boundary_; }
String EndOfDocumentBoundary() const { return end_of_document_boundary_; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
static Encoding ParseContentTransferEncoding(const String&);
@@ -234,7 +234,7 @@ MIMEHeader* MIMEHeader::ParseHeader(SharedBufferChunkReader* buffer) {
MIMEHeader::Encoding MIMEHeader::ParseContentTransferEncoding(
const String& text) {
- String encoding = text.StripWhiteSpace().DeprecatedLower();
+ String encoding = text.StripWhiteSpace().LowerASCII();
if (encoding == "base64")
return Encoding::kBase64;
if (encoding == "quoted-printable")
diff --git a/chromium/third_party/blink/renderer/platform/mojo/DEPS b/chromium/third_party/blink/renderer/platform/mojo/DEPS
index ee6991fbfd1..0520c841e8c 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/DEPS
+++ b/chromium/third_party/blink/renderer/platform/mojo/DEPS
@@ -13,7 +13,6 @@ include_rules = [
"+base/strings/latin1_string_conversions.h",
"+base/strings/string16.h",
"+mojo/public/cpp/base/time_mojom_traits.h",
- "+mojo/public/cpp/bindings/binding.h",
"+mojo/public/mojom/base/string16.mojom-blink.h",
"+skia/public/mojom/bitmap_skbitmap_mojom_traits.h",
@@ -22,6 +21,10 @@ include_rules = [
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/weborigin",
"+third_party/blink/renderer/platform/wtf",
+ "+third_party/blink/renderer/platform/context_lifecycle_observer.h",
+ "+third_party/blink/renderer/platform/context_lifecycle_notifier.h",
+ "+third_party/blink/renderer/platform/heap_observer_list.h",
+ "+third_party/blink/renderer/platform/heap",
]
specific_include_rules = {
diff --git a/chromium/third_party/blink/renderer/platform/mojo/big_string.typemap b/chromium/third_party/blink/renderer/platform/mojo/big_string.typemap
deleted file mode 100644
index bd4bac7b3f7..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/big_string.typemap
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//mojo/public/mojom/base/big_string.mojom"
-public_headers =
- [ "//third_party/blink/renderer/platform/wtf/text/wtf_string.h" ]
-traits_headers =
- [ "//third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h" ]
-type_mappings =
- [ "mojo_base.mojom.BigString=::WTF::String[nullable_is_same_type]" ]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h
index dda183cb6c9..2b0f1388aaa 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_BIG_STRING_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_BIG_STRING_MOJOM_TRAITS_H_
+#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "mojo/public/mojom/base/big_string.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index 176545f7ecb..8af90056cf9 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -3,33 +3,27 @@
# found in the LICENSE file.
typemaps = [
- "//media/capture/mojom/video_capture_types_for_blink.typemap",
+ "//media/capture/mojom/video_capture_types.typemap",
"//media/mojo/mojom/audio_parameters.typemap",
- "//mojo/public/cpp/base/values.typemap",
- "//services/network/public/cpp/http_request_headers.typemap",
- "//services/network/public/cpp/ip_address_for_blink.typemap",
- "//services/network/public/cpp/ip_endpoint_for_blink.typemap",
- "//services/network/public/cpp/network_interface_for_blink.typemap",
- "//services/network/public/cpp/mutable_network_traffic_annotation_tag.typemap",
- "//services/network/public/cpp/p2p.typemap",
+ "//third_party/blink/common/feature_policy/feature_policy.typemap",
+ "//third_party/blink/common/frame/frame_policy.typemap",
+ "//third_party/blink/public/common/loader/url_loader_factory_bundle.typemap",
+ "//third_party/blink/public/common/messaging/message_port_descriptor.typemap",
"//third_party/blink/renderer/core/messaging/blink_cloneable_message.typemap",
"//third_party/blink/renderer/core/messaging/blink_transferable_message.typemap",
"//third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap",
"//third_party/blink/renderer/platform/blob/serialized_blob.typemap",
"//third_party/blink/renderer/platform/cookie/canonical_cookie.typemap",
- "//third_party/blink/renderer/platform/mojo/big_string.typemap",
"//third_party/blink/renderer/platform/mojo/fetch_api_request_headers.typemap",
- "//third_party/blink/renderer/platform/mojo/geometry.typemap",
- "//third_party/blink/renderer/platform/mojo/kurl.typemap",
- "//third_party/blink/renderer/platform/mojo/security_origin.typemap",
"//third_party/blink/renderer/platform/mojo/string.typemap",
"//third_party/blink/renderer/platform/mojo/time.typemap",
"//third_party/blink/renderer/platform/network/encoded_form_data_element.typemap",
"//third_party/blink/renderer/platform/network/encoded_form_data.typemap",
+ "//third_party/blink/public/common/mediastream/media_devices.typemap",
"//third_party/blink/public/common/mediastream/media_stream.typemap",
"//third_party/blink/public/common/screen_orientation/screen_orientation_lock_types.typemap",
"//third_party/blink/public/mojom/bluetooth/bluetooth.typemap",
- "//ui/gfx/mojom/buffer_types_for_blink.typemap",
- "//ui/gfx/mojom/color_space_for_blink.typemap",
+ "//ui/gfx/geometry/mojom/geometry.typemap",
+ "//ui/gfx/mojom/color_space.typemap",
"//ui/gfx/mojom/transform.typemap",
]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/geometry.typemap b/chromium/third_party/blink/renderer/platform/mojo/geometry.typemap
deleted file mode 100644
index 8029163748a..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/geometry.typemap
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//ui/gfx/geometry/mojom/geometry.mojom"
-public_headers = [
- "//ui/gfx/geometry/quaternion.h",
- "//ui/gfx/geometry/vector3d_f.h",
- "//third_party/blink/public/platform/web_float_rect.h",
- "//third_party/blink/public/platform/web_float_point.h",
- "//third_party/blink/public/platform/web_point.h",
- "//third_party/blink/public/platform/web_rect.h",
- "//third_party/blink/public/platform/web_size.h",
- "//third_party/blink/renderer/platform/geometry/float_point_3d.h",
-]
-traits_headers = [
- "//third_party/blink/renderer/platform/mojo/geometry_mojom_traits.h",
- "//ui/gfx/geometry/mojom/geometry_mojom_traits.h",
-]
-
-# Note: consumers of this typemap must themselves depend on platform.
-deps = [
- "//mojo/public/cpp/bindings",
-]
-
-public_deps = [
- "//third_party/blink/public:blink_headers",
- "//third_party/blink/renderer/platform:geometry_mojom_traits",
- "//ui/gfx/geometry",
- "//ui/gfx/geometry/mojom:mojom_traits",
-]
-
-# TODO(zqzhang): ideally, gfx.mojom.Size should be mapped into ::blink::IntSize.
-# However that introduces an link issue on Windows. See https://crbug.com/653323
-type_mappings = [
- "gfx.mojom.Point=::blink::WebPoint",
- "gfx.mojom.PointF=::blink::WebFloatPoint",
- "gfx.mojom.Point3F=::blink::FloatPoint3D",
- "gfx.mojom.Quaternion=::gfx::Quaternion",
- "gfx.mojom.RectF=::blink::WebFloatRect",
- "gfx.mojom.Rect=::blink::WebRect",
- "gfx.mojom.Size=::blink::WebSize",
- "gfx.mojom.Vector3dF=::gfx::Vector3dF",
-]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.cc
deleted file mode 100644
index 29128e0055d..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/mojo/geometry_mojom_traits.h"
-
-namespace mojo {
-
-// static
-bool StructTraits<gfx::mojom::RectFDataView, ::blink::WebFloatRect>::Read(
- gfx::mojom::RectFDataView data,
- ::blink::WebFloatRect* out) {
- if (data.width() < 0 || data.height() < 0)
- return false;
- out->x = data.x();
- out->y = data.y();
- out->width = data.width();
- out->height = data.height();
- return true;
-}
-
-// static
-bool StructTraits<gfx::mojom::RectDataView, ::blink::WebRect>::Read(
- gfx::mojom::RectDataView data,
- ::blink::WebRect* out) {
- if (data.width() < 0 || data.height() < 0)
- return false;
- out->x = data.x();
- out->y = data.y();
- out->width = data.width();
- out->height = data.height();
- return true;
-}
-
-// static
-bool StructTraits<gfx::mojom::PointDataView, ::blink::WebPoint>::Read(
- gfx::mojom::PointDataView data,
- ::blink::WebPoint* out) {
- out->x = data.x();
- out->y = data.y();
- return true;
-}
-
-// static
-bool StructTraits<gfx::mojom::PointFDataView, ::blink::WebFloatPoint>::Read(
- gfx::mojom::PointFDataView data,
- ::blink::WebFloatPoint* out) {
- out->x = data.x();
- out->y = data.y();
- return true;
-}
-
-bool StructTraits<gfx::mojom::Point3FDataView, ::blink::FloatPoint3D>::Read(
- gfx::mojom::Point3FDataView data,
- ::blink::FloatPoint3D* out) {
- out->SetX(data.x());
- out->SetY(data.y());
- out->SetZ(data.z());
- return true;
-}
-
-// static
-bool StructTraits<gfx::mojom::SizeDataView, ::blink::WebSize>::Read(
- gfx::mojom::SizeDataView data,
- ::blink::WebSize* out) {
- if (data.width() < 0 || data.height() < 0)
- return false;
- out->width = data.width();
- out->height = data.height();
- return true;
-}
-
-} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.h
deleted file mode 100644
index eb16fc06bb1..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_GEOMETRY_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_GEOMETRY_MOJOM_TRAITS_H_
-
-#include "third_party/blink/public/platform/web_float_point.h"
-#include "third_party/blink/public/platform/web_float_rect.h"
-#include "third_party/blink/public/platform/web_point.h"
-#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
-#include "ui/gfx/geometry/mojom/geometry.mojom-shared.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<gfx::mojom::PointDataView, ::blink::WebPoint> {
- static int x(const ::blink::WebPoint& point) { return point.x; }
- static int y(const ::blink::WebPoint& point) { return point.y; }
- static bool Read(gfx::mojom::PointDataView, ::blink::WebPoint* out);
-};
-
-template <>
-struct StructTraits<gfx::mojom::PointFDataView, ::blink::WebFloatPoint> {
- static float x(const ::blink::WebFloatPoint& point) { return point.x; }
- static float y(const ::blink::WebFloatPoint& point) { return point.y; }
- static bool Read(gfx::mojom::PointFDataView, ::blink::WebFloatPoint* out);
-};
-
-template <>
-struct StructTraits<gfx::mojom::Point3FDataView, ::blink::FloatPoint3D> {
- static float x(const gfx::Point3F& p) { return p.x(); }
- static float y(const gfx::Point3F& p) { return p.y(); }
- static float z(const gfx::Point3F& p) { return p.z(); }
- static bool Read(gfx::mojom::Point3FDataView data,
- ::blink::FloatPoint3D* out);
-};
-
-template <>
-struct StructTraits<gfx::mojom::RectFDataView, ::blink::WebFloatRect> {
- static float x(const ::blink::WebFloatRect& rect) { return rect.x; }
- static float y(const ::blink::WebFloatRect& rect) { return rect.y; }
- static float width(const ::blink::WebFloatRect& rect) { return rect.width; }
- static float height(const ::blink::WebFloatRect& rect) { return rect.height; }
- static bool Read(gfx::mojom::RectFDataView, ::blink::WebFloatRect* out);
-};
-
-template <>
-struct StructTraits<gfx::mojom::RectDataView, ::blink::WebRect> {
- static int x(const ::blink::WebRect& rect) { return rect.x; }
- static int y(const ::blink::WebRect& rect) { return rect.y; }
- static int width(const ::blink::WebRect& rect) { return rect.width; }
- static int height(const ::blink::WebRect& rect) { return rect.height; }
- static bool Read(gfx::mojom::RectDataView, ::blink::WebRect* out);
-};
-
-template <>
-struct StructTraits<gfx::mojom::SizeDataView, ::blink::WebSize> {
- static int width(const ::blink::WebSize& size) { return size.width; }
- static int height(const ::blink::WebSize& size) { return size.height; }
- static bool Read(gfx::mojom::SizeDataView, ::blink::WebSize* out);
-};
-
-} // namespace mojo
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_GEOMETRY_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
deleted file mode 100644
index 0c1d8a69650..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <utility>
-
-#include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
-#include "ui/gfx/geometry/mojom/geometry.mojom-blink.h"
-#include "ui/gfx/geometry/mojom/geometry_traits_test_service.mojom-blink.h"
-
-namespace blink {
-
-namespace {
-
-class GeometryStructTraitsTest
- : public testing::Test,
- public gfx::mojom::blink::GeometryTraitsTestService {
- public:
- GeometryStructTraitsTest() {}
-
- protected:
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService>
- GetTraitsTestProxy() {
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy;
- traits_test_receivers_.Add(this, proxy.BindNewPipeAndPassReceiver());
- return proxy;
- }
-
- private:
- // GeometryTraitsTestService:
- void EchoPoint(const WebPoint& p, EchoPointCallback callback) override {
- std::move(callback).Run(p);
- }
-
- void EchoPointF(const WebFloatPoint& p,
- EchoPointFCallback callback) override {
- std::move(callback).Run(p);
- }
-
- void EchoPoint3F(const FloatPoint3D& p,
- EchoPoint3FCallback callback) override {
- std::move(callback).Run(p);
- }
-
- void EchoSize(const WebSize& s, EchoSizeCallback callback) override {
- std::move(callback).Run(s);
- }
-
- void EchoSizeF(gfx::mojom::blink::SizeFPtr, EchoSizeFCallback) override {
- // The type map is not specified.
- NOTREACHED();
- }
-
- void EchoRect(const WebRect& r, EchoRectCallback callback) override {
- std::move(callback).Run(r);
- }
-
- void EchoRectF(const WebFloatRect& r, EchoRectFCallback callback) override {
- std::move(callback).Run(r);
- }
-
- void EchoInsets(gfx::mojom::blink::InsetsPtr, EchoInsetsCallback) override {
- // The type map is not specified.
- NOTREACHED();
- }
-
- void EchoInsetsF(gfx::mojom::blink::InsetsFPtr,
- EchoInsetsFCallback) override {
- // The type map is not specified.
- NOTREACHED();
- }
-
- void EchoVector2d(gfx::mojom::blink::Vector2dPtr,
- EchoVector2dCallback) override {
- // The type map is not specified.
- NOTREACHED();
- }
-
- void EchoVector2dF(gfx::mojom::blink::Vector2dFPtr,
- EchoVector2dFCallback) override {
- // The type map is not specified.
- NOTREACHED();
- }
-
- void EchoVector3dF(const gfx::Vector3dF& v,
- EchoVector3dFCallback callback) override {
- std::move(callback).Run(v);
- }
-
- void EchoQuaternion(const gfx::Quaternion& q,
- EchoQuaternionCallback callback) override {
- std::move(callback).Run(q);
- }
-
- mojo::ReceiverSet<gfx::mojom::blink::GeometryTraitsTestService>
- traits_test_receivers_;
-
- base::test::TaskEnvironment task_environment_;
-
- DISALLOW_COPY_AND_ASSIGN(GeometryStructTraitsTest);
-};
-
-} // namespace
-
-TEST_F(GeometryStructTraitsTest, Size) {
- const int32_t kWidth = 1234;
- const int32_t kHeight = 5678;
- WebSize input(kWidth, kHeight);
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
- GetTraitsTestProxy();
- WebSize output;
- proxy->EchoSize(input, &output);
- EXPECT_EQ(input, output);
-}
-
-TEST_F(GeometryStructTraitsTest, Point) {
- const float kX = 1234;
- const float kY = 5678;
- WebPoint input(kX, kY);
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
- GetTraitsTestProxy();
- WebPoint output;
- proxy->EchoPoint(input, &output);
- EXPECT_EQ(input, output);
-}
-
-TEST_F(GeometryStructTraitsTest, PointF) {
- const float kX = 1.234;
- const float kY = 5.678;
- WebFloatPoint input(kX, kY);
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
- GetTraitsTestProxy();
- WebFloatPoint output;
- proxy->EchoPointF(input, &output);
- EXPECT_EQ(input, output);
-}
-
-TEST_F(GeometryStructTraitsTest, Point3D) {
- const float kX = 1.234;
- const float kY = 5.678;
- const float kZ = 9.098;
- FloatPoint3D input(kX, kY, kZ);
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
- GetTraitsTestProxy();
- FloatPoint3D output;
- proxy->EchoPoint3F(input, &output);
- EXPECT_EQ(input, output);
-}
-
-TEST_F(GeometryStructTraitsTest, Rect) {
- const float kX = 1;
- const float kY = 2;
- const float kWidth = 3;
- const float kHeight = 4;
- WebRect input(kX, kY, kWidth, kHeight);
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
- GetTraitsTestProxy();
- WebRect output;
- proxy->EchoRect(input, &output);
- EXPECT_EQ(input, output);
-}
-
-TEST_F(GeometryStructTraitsTest, RectF) {
- const float kX = 1.234;
- const float kY = 2.345;
- const float kWidth = 3.456;
- const float kHeight = 4.567;
- WebFloatRect input(kX, kY, kWidth, kHeight);
- mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
- GetTraitsTestProxy();
- WebFloatRect output;
- proxy->EchoRectF(input, &output);
- EXPECT_EQ(input, output);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h
new file mode 100644
index 00000000000..bfc774c962b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h
@@ -0,0 +1,94 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_RECEIVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_RECEIVER_H_
+
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+// HeapMojoReceiver is a wrapper for mojo::Receiver to be owned by a
+// garbage-collected object. Blink is expected to use HeapMojoReceiver by
+// default. HeapMojoReceiver must be associated with context.
+// HeapMojoReceiver's constructor takes context as a mandatory parameter.
+// HeapMojoReceiver resets the mojo connection when 1) the owner object is
+// garbage-collected and 2) the associated ExecutionContext is detached.
+
+// TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
+// that the interface is not used after ContextDestroyed().
+template <typename Interface,
+ HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
+class HeapMojoReceiver {
+ DISALLOW_NEW();
+
+ public:
+ using ImplPointerType = typename mojo::Receiver<Interface>::ImplPointerType;
+
+ HeapMojoReceiver(ImplPointerType impl, ContextLifecycleNotifier* context)
+ : wrapper_(MakeGarbageCollected<Wrapper>(std::move(impl), context)) {}
+
+ // Methods to redirect to mojo::Receiver:
+ ImplPointerType operator->() const { return get(); }
+ ImplPointerType get() { return wrapper_->receiver().get(); }
+ bool is_bound() const { return wrapper_->receiver().is_bound(); }
+ void reset() { wrapper_->receiver().reset(); }
+ void set_disconnect_handler(base::OnceClosure handler) {
+ wrapper_->receiver().set_disconnect_handler(std::move(handler));
+ }
+ mojo::PendingRemote<Interface> BindNewPipeAndPassRemote(
+ scoped_refptr<base::SequencedTaskRunner> task_runner) WARN_UNUSED_RESULT {
+ DCHECK(task_runner);
+ return wrapper_->receiver().BindNewPipeAndPassRemote(
+ std::move(task_runner));
+ }
+ void Bind(mojo::PendingReceiver<Interface> pending_receiver,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ DCHECK(task_runner);
+ wrapper_->receiver().Bind(std::move(pending_receiver),
+ std::move(task_runner));
+ }
+
+ void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
+
+ private:
+ // Garbage collected wrapper class to add a prefinalizer.
+ class Wrapper final : public GarbageCollected<Wrapper>,
+ public ContextLifecycleObserver {
+ USING_PRE_FINALIZER(Wrapper, Dispose);
+ USING_GARBAGE_COLLECTED_MIXIN(Wrapper);
+
+ public:
+ Wrapper(ImplPointerType impl, ContextLifecycleNotifier* notifier)
+ : receiver_(std::move(impl)) {
+ SetContextLifecycleNotifier(notifier);
+ }
+
+ void Trace(Visitor* visitor) override {
+ ContextLifecycleObserver::Trace(visitor);
+ }
+
+ void Dispose() { receiver_.reset(); }
+
+ mojo::Receiver<Interface>& receiver() { return receiver_; }
+
+ // ContextLifecycleObserver methods
+ void ContextDestroyed() override {
+ if (Mode == HeapMojoWrapperMode::kWithContextObserver)
+ receiver_.reset();
+ }
+
+ private:
+ mojo::Receiver<Interface> receiver_;
+ };
+
+ Member<Wrapper> wrapper_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_RECEIVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h
new file mode 100644
index 00000000000..36b7a74aa76
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h
@@ -0,0 +1,94 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_RECEIVER_SET_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_RECEIVER_SET_H_
+
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+// HeapMojoReceiverSet is a wrapper for mojo::ReceiverSet to be owned by a
+// garbage-collected object. Blink is expected to use HeapMojoReceiverSet by
+// default. HeapMojoReceiverSet must be associated with context.
+// HeapMojoReceiverSet's constructor takes context as a mandatory parameter.
+// HeapMojoReceiverSet resets the mojo connection when 1) the owner object is
+// garbage-collected or 2) the associated ExecutionContext is detached.
+
+// TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
+// that the interface is not used after ContextDestroyed().
+template <typename Interface,
+ HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
+class HeapMojoReceiverSet {
+ DISALLOW_NEW();
+
+ public:
+ using ImplPointerType = typename mojo::Receiver<Interface>::ImplPointerType;
+
+ explicit HeapMojoReceiverSet(ContextLifecycleNotifier* context)
+ : wrapper_(MakeGarbageCollected<Wrapper>(context)) {
+ DCHECK(context);
+ }
+
+ // Methods to redirect to mojo::ReceiverSet:
+ mojo::ReceiverId Add(ImplPointerType impl,
+ mojo::PendingReceiver<Interface> receiver,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ DCHECK(task_runner);
+ return wrapper_->receiver_set().Add(std::move(impl), std::move(receiver),
+ task_runner);
+ }
+
+ bool Remove(mojo::ReceiverId id) {
+ return wrapper_->receiver_set().Remove(id);
+ }
+
+ void Clear() { wrapper_->receiver_set().Clear(); }
+
+ bool HasReceiver(mojo::ReceiverId id) {
+ return wrapper_->receiver_set().HasReceiver(id);
+ }
+
+ void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
+
+ private:
+ // Garbage collected wrapper class to add a prefinalizer.
+ class Wrapper final : public GarbageCollected<Wrapper>,
+ public ContextLifecycleObserver {
+ USING_PRE_FINALIZER(Wrapper, Dispose);
+ USING_GARBAGE_COLLECTED_MIXIN(Wrapper);
+
+ public:
+ explicit Wrapper(ContextLifecycleNotifier* notifier) {
+ SetContextLifecycleNotifier(notifier);
+ }
+
+ void Trace(Visitor* visitor) override {
+ ContextLifecycleObserver::Trace(visitor);
+ }
+
+ void Dispose() { receiver_set_.Clear(); }
+
+ mojo::ReceiverSet<Interface>& receiver_set() { return receiver_set_; }
+
+ // ContextLifecycleObserver methods
+ void ContextDestroyed() override {
+ if (Mode == HeapMojoWrapperMode::kWithContextObserver)
+ receiver_set_.Clear();
+ }
+
+ private:
+ mojo::ReceiverSet<Interface> receiver_set_;
+ };
+
+ Member<Wrapper> wrapper_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_RECEIVER_SET_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc
new file mode 100644
index 00000000000..aa13bc2b39b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set_test.cc
@@ -0,0 +1,179 @@
+// 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 "third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h"
+
+#include "base/test/null_task_runner.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/interfaces/bindings/tests/sample_service.mojom-blink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/heap_observer_list.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+namespace {
+
+class FakeContextNotifier final : public GarbageCollected<FakeContextNotifier>,
+ public ContextLifecycleNotifier {
+ USING_GARBAGE_COLLECTED_MIXIN(FakeContextNotifier);
+
+ public:
+ FakeContextNotifier() = default;
+
+ void AddContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.AddObserver(observer);
+ }
+ void RemoveContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.RemoveObserver(observer);
+ }
+
+ void NotifyContextDestroyed() {
+ observers_.ForEachObserver([](ContextLifecycleObserver* observer) {
+ observer->ContextDestroyed();
+ });
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(observers_);
+ ContextLifecycleNotifier::Trace(visitor);
+ }
+
+ private:
+ HeapObserverList<ContextLifecycleObserver> observers_;
+};
+
+class MockService : public sample::blink::Service {
+ public:
+ MockService() = default;
+
+ void Frobinate(sample::blink::FooPtr foo,
+ Service::BazOptions baz,
+ mojo::PendingRemote<sample::blink::Port> port,
+ FrobinateCallback callback) override {}
+ void GetPort(mojo::PendingReceiver<sample::blink::Port> receiver) override {}
+};
+
+template <HeapMojoWrapperMode Mode>
+class GCOwner : public GarbageCollected<GCOwner<Mode>> {
+ public:
+ explicit GCOwner(FakeContextNotifier* context) : receiver_set_(context) {}
+ void Trace(Visitor* visitor) { visitor->Trace(receiver_set_); }
+
+ HeapMojoReceiverSet<sample::blink::Service, Mode>& receiver_set() {
+ return receiver_set_;
+ }
+
+ private:
+ HeapMojoReceiverSet<sample::blink::Service, Mode> receiver_set_;
+};
+
+template <HeapMojoWrapperMode Mode>
+class HeapMojoReceiverSetGCBaseTest : public TestSupportingGC {
+ public:
+ FakeContextNotifier* context() { return context_; }
+ scoped_refptr<base::NullTaskRunner> task_runner() {
+ return null_task_runner_;
+ }
+ GCOwner<Mode>* owner() { return owner_; }
+
+ void ClearOwner() { owner_ = nullptr; }
+
+ protected:
+ void SetUp() override {
+ context_ = MakeGarbageCollected<FakeContextNotifier>();
+ owner_ = MakeGarbageCollected<GCOwner<Mode>>(context());
+ }
+ void TearDown() override {}
+
+ Persistent<FakeContextNotifier> context_;
+ Persistent<GCOwner<Mode>> owner_;
+ scoped_refptr<base::NullTaskRunner> null_task_runner_ =
+ base::MakeRefCounted<base::NullTaskRunner>();
+};
+
+} // namespace
+
+class HeapMojoReceiverSetGCWithContextObserverTest
+ : public HeapMojoReceiverSetGCBaseTest<
+ HeapMojoWrapperMode::kWithContextObserver> {};
+class HeapMojoReceiverSetGCWithoutContextObserverTest
+ : public HeapMojoReceiverSetGCBaseTest<
+ HeapMojoWrapperMode::kWithoutContextObserver> {};
+
+// GC the HeapMojoReceiverSet with context observer and verify that the receiver
+// is no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoReceiverSetGCWithContextObserverTest, RemovesReceiver) {
+ auto receiver_set = owner()->receiver_set();
+ MockService service;
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(&service, std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+
+ receiver_set.Remove(rid);
+
+ EXPECT_FALSE(receiver_set.HasReceiver(rid));
+}
+
+// GC the HeapMojoReceiverSet without context observer and verify that the
+// receiver is no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoReceiverSetGCWithoutContextObserverTest, RemovesReceiver) {
+ auto receiver_set = owner()->receiver_set();
+ MockService service;
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(&service, std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+
+ receiver_set.Remove(rid);
+
+ EXPECT_FALSE(receiver_set.HasReceiver(rid));
+}
+
+// GC the HeapMojoReceiverSet with context observer and verify that the receiver
+// is no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoReceiverSetGCWithContextObserverTest, ClearLeavesSetEmpty) {
+ auto receiver_set = owner()->receiver_set();
+ MockService service;
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(&service, std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+
+ receiver_set.Clear();
+
+ EXPECT_FALSE(receiver_set.HasReceiver(rid));
+}
+
+// GC the HeapMojoReceiverSet without context observer and verify that the
+// receiver is no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoReceiverSetGCWithoutContextObserverTest, ClearLeavesSetEmpty) {
+ auto receiver_set = owner()->receiver_set();
+ MockService service;
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(&service, std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+
+ receiver_set.Clear();
+
+ EXPECT_FALSE(receiver_set.HasReceiver(rid));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc
new file mode 100644
index 00000000000..2f348ab5b4f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc
@@ -0,0 +1,176 @@
+
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "base/test/null_task_runner.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/interfaces/bindings/tests/sample_service.mojom-blink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/heap_observer_list.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+namespace {
+
+class MockContext final : public GarbageCollected<MockContext>,
+ public ContextLifecycleNotifier {
+ USING_GARBAGE_COLLECTED_MIXIN(MockContext);
+
+ public:
+ MockContext() = default;
+
+ void AddContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.AddObserver(observer);
+ }
+ void RemoveContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.RemoveObserver(observer);
+ }
+
+ void NotifyContextDestroyed() {
+ observers_.ForEachObserver([](ContextLifecycleObserver* observer) {
+ observer->ContextDestroyed();
+ });
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(observers_);
+ ContextLifecycleNotifier::Trace(visitor);
+ }
+
+ private:
+ HeapObserverList<ContextLifecycleObserver> observers_;
+};
+
+template <HeapMojoWrapperMode Mode>
+class ReceiverOwner : public GarbageCollected<ReceiverOwner<Mode>>,
+ public sample::blink::Service {
+ public:
+ explicit ReceiverOwner(MockContext* context) : receiver_(this, context) {}
+
+ HeapMojoReceiver<sample::blink::Service, Mode>& receiver() {
+ return receiver_;
+ }
+
+ void Trace(Visitor* visitor) { visitor->Trace(receiver_); }
+
+ private:
+ // sample::blink::Service implementation
+ void Frobinate(sample::blink::FooPtr foo,
+ sample::blink::Service::BazOptions options,
+ mojo::PendingRemote<sample::blink::Port> port,
+ sample::blink::Service::FrobinateCallback callback) override {}
+ void GetPort(mojo::PendingReceiver<sample::blink::Port> port) override {}
+
+ HeapMojoReceiver<sample::blink::Service, Mode> receiver_;
+};
+
+template <HeapMojoWrapperMode Mode>
+class HeapMojoReceiverGCBaseTest : public TestSupportingGC {
+ public:
+ base::RunLoop& run_loop() { return run_loop_; }
+ bool& disconnected() { return disconnected_; }
+
+ void ClearOwner() { owner_ = nullptr; }
+
+ protected:
+ void SetUp() override {
+ CHECK(!disconnected_);
+ context_ = MakeGarbageCollected<MockContext>();
+ owner_ = MakeGarbageCollected<ReceiverOwner<Mode>>(context_);
+ scoped_refptr<base::NullTaskRunner> null_task_runner =
+ base::MakeRefCounted<base::NullTaskRunner>();
+ remote_ = mojo::Remote<sample::blink::Service>(
+ owner_->receiver().BindNewPipeAndPassRemote(null_task_runner));
+ remote_.set_disconnect_handler(WTF::Bind(
+ [](HeapMojoReceiverGCBaseTest* receiver_test) {
+ receiver_test->run_loop().Quit();
+ receiver_test->disconnected() = true;
+ },
+ WTF::Unretained(this)));
+ }
+ void TearDown() override { CHECK(disconnected_); }
+
+ Persistent<MockContext> context_;
+ Persistent<ReceiverOwner<Mode>> owner_;
+ base::RunLoop run_loop_;
+ mojo::Remote<sample::blink::Service> remote_;
+ bool disconnected_ = false;
+};
+
+template <HeapMojoWrapperMode Mode>
+class HeapMojoReceiverDestroyContextBaseTest : public TestSupportingGC {
+ protected:
+ void SetUp() override {
+ context_ = MakeGarbageCollected<MockContext>();
+ owner_ = MakeGarbageCollected<ReceiverOwner<Mode>>(context_);
+ scoped_refptr<base::NullTaskRunner> null_task_runner =
+ base::MakeRefCounted<base::NullTaskRunner>();
+ remote_ = mojo::Remote<sample::blink::Service>(
+ owner_->receiver().BindNewPipeAndPassRemote(null_task_runner));
+ }
+
+ Persistent<MockContext> context_;
+ Persistent<ReceiverOwner<Mode>> owner_;
+ mojo::Remote<sample::blink::Service> remote_;
+};
+
+} // namespace
+
+class HeapMojoReceiverGCWithContextObserverTest
+ : public HeapMojoReceiverGCBaseTest<
+ HeapMojoWrapperMode::kWithContextObserver> {};
+class HeapMojoReceiverGCWithoutContextObserverTest
+ : public HeapMojoReceiverGCBaseTest<
+ HeapMojoWrapperMode::kWithoutContextObserver> {};
+class HeapMojoReceiverDestroyContextWithContextObserverTest
+ : public HeapMojoReceiverDestroyContextBaseTest<
+ HeapMojoWrapperMode::kWithContextObserver> {};
+class HeapMojoReceiverDestroyContextWithoutContextObserverTest
+ : public HeapMojoReceiverDestroyContextBaseTest<
+ HeapMojoWrapperMode::kWithoutContextObserver> {};
+
+// Make HeapMojoReceiver with context observer garbage collected and check that
+// the connection is disconnected right after the marking phase.
+TEST_F(HeapMojoReceiverGCWithContextObserverTest, ResetsOnGC) {
+ ClearOwner();
+ EXPECT_FALSE(disconnected());
+ PreciselyCollectGarbage();
+ run_loop().Run();
+ EXPECT_TRUE(disconnected());
+ CompleteSweepingIfNeeded();
+}
+
+// Make HeapMojoReceiver without context observer garbage collected and check
+// that the connection is disconnected right after the marking phase.
+TEST_F(HeapMojoReceiverGCWithoutContextObserverTest, ResetsOnGC) {
+ ClearOwner();
+ EXPECT_FALSE(disconnected());
+ PreciselyCollectGarbage();
+ run_loop().Run();
+ EXPECT_TRUE(disconnected());
+ CompleteSweepingIfNeeded();
+}
+
+// Destroy the context with context observer and check that the connection is
+// disconnected.
+TEST_F(HeapMojoReceiverDestroyContextWithContextObserverTest,
+ ResetsOnContextDestroyed) {
+ EXPECT_TRUE(owner_->receiver().is_bound());
+ context_->NotifyContextDestroyed();
+ EXPECT_FALSE(owner_->receiver().is_bound());
+}
+
+// Destroy the context without context observer and check that the connection is
+// still connected.
+TEST_F(HeapMojoReceiverDestroyContextWithoutContextObserverTest,
+ ResetsOnContextDestroyed) {
+ EXPECT_TRUE(owner_->receiver().is_bound());
+ context_->NotifyContextDestroyed();
+ EXPECT_TRUE(owner_->receiver().is_bound());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h
new file mode 100644
index 00000000000..dd5da3c5d23
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h
@@ -0,0 +1,95 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_REMOTE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_REMOTE_H_
+
+#include <utility>
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+// HeapMojoRemote is a wrapper for mojo::Remote to be owned by a
+// garbage-collected object. Blink is expected to use HeapMojoRemote by
+// default. HeapMojoRemote must be associated with context.
+// HeapMojoRemote's constructor takes context as a mandatory parameter.
+// HeapMojoRemote resets the mojo connection when 1) the owner object is
+// garbage-collected and 2) the associated ExecutionContext is detached.
+
+// TODO(crbug.com/1058076) HeapMojoWrapperMode should be removed once we ensure
+// that the interface is not used after ContextDestroyed().
+template <typename Interface,
+ HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
+class HeapMojoRemote {
+ DISALLOW_NEW();
+
+ public:
+ explicit HeapMojoRemote(ContextLifecycleNotifier* notifier)
+ : wrapper_(MakeGarbageCollected<Wrapper>(notifier)) {}
+
+ // Methods to redirect to mojo::Remote.
+ using Proxy = typename Interface::Proxy_;
+ Proxy* operator->() const { return get(); }
+ Proxy* get() const { return wrapper_->remote().get(); }
+ bool is_bound() const { return wrapper_->remote().is_bound(); }
+ bool is_connected() const { return wrapper_->remote().is_connected(); }
+ void reset() { wrapper_->remote().reset(); }
+ void set_disconnect_handler(base::OnceClosure handler) {
+ wrapper_->remote().set_disconnect_handler(std::move(handler));
+ }
+ mojo::PendingReceiver<Interface> BindNewPipeAndPassReceiver(
+ scoped_refptr<base::SequencedTaskRunner> task_runner) WARN_UNUSED_RESULT {
+ DCHECK(task_runner);
+ return wrapper_->remote().BindNewPipeAndPassReceiver(
+ std::move(task_runner));
+ }
+ void Bind(mojo::PendingRemote<Interface> pending_remote,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ DCHECK(task_runner);
+ wrapper_->remote().Bind(std::move(pending_remote), std::move(task_runner));
+ }
+ void FlushForTesting() { return wrapper_->remote().FlushForTesting(); }
+
+ void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
+
+ private:
+ // Garbage collected wrapper class to add a prefinalizer.
+ class Wrapper final : public GarbageCollected<Wrapper>,
+ public ContextLifecycleObserver {
+ USING_PRE_FINALIZER(Wrapper, Dispose);
+ USING_GARBAGE_COLLECTED_MIXIN(Wrapper);
+
+ public:
+ explicit Wrapper(ContextLifecycleNotifier* notifier) {
+ SetContextLifecycleNotifier(notifier);
+ }
+
+ void Trace(Visitor* visitor) override {
+ ContextLifecycleObserver::Trace(visitor);
+ }
+
+ void Dispose() { remote_.reset(); }
+
+ mojo::Remote<Interface>& remote() { return remote_; }
+
+ // ContextLifecycleObserver methods
+ void ContextDestroyed() override {
+ if (Mode == HeapMojoWrapperMode::kWithContextObserver)
+ remote_.reset();
+ }
+
+ private:
+ mojo::Remote<Interface> remote_;
+ };
+
+ Member<Wrapper> wrapper_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_REMOTE_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_test.cc
new file mode 100644
index 00000000000..5af34d07ac9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_remote_test.cc
@@ -0,0 +1,181 @@
+
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "base/test/null_task_runner.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/interfaces/bindings/tests/sample_service.mojom-blink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/heap_observer_list.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+namespace {
+
+class MockContext final : public GarbageCollected<MockContext>,
+ public ContextLifecycleNotifier {
+ USING_GARBAGE_COLLECTED_MIXIN(MockContext);
+
+ public:
+ MockContext() = default;
+
+ void AddContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.AddObserver(observer);
+ }
+ void RemoveContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.RemoveObserver(observer);
+ }
+
+ void NotifyContextDestroyed() {
+ observers_.ForEachObserver([](ContextLifecycleObserver* observer) {
+ observer->ContextDestroyed();
+ });
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(observers_);
+ ContextLifecycleNotifier::Trace(visitor);
+ }
+
+ private:
+ HeapObserverList<ContextLifecycleObserver> observers_;
+};
+
+class ServiceImpl : public sample::blink::Service {
+ public:
+ explicit ServiceImpl() = default;
+
+ mojo::Receiver<sample::blink::Service>& receiver() { return receiver_; }
+
+ private:
+ // sample::blink::Service implementation
+ void Frobinate(sample::blink::FooPtr foo,
+ sample::blink::Service::BazOptions options,
+ mojo::PendingRemote<sample::blink::Port> port,
+ sample::blink::Service::FrobinateCallback callback) override {}
+ void GetPort(mojo::PendingReceiver<sample::blink::Port> port) override {}
+
+ mojo::Receiver<sample::blink::Service> receiver_{this};
+};
+
+template <HeapMojoWrapperMode Mode>
+class RemoteOwner : public GarbageCollected<RemoteOwner<Mode>> {
+ public:
+ explicit RemoteOwner(MockContext* context) : remote_(context) {}
+
+ HeapMojoRemote<sample::blink::Service, Mode>& remote() { return remote_; }
+
+ void Trace(Visitor* visitor) { visitor->Trace(remote_); }
+
+ HeapMojoRemote<sample::blink::Service, Mode> remote_;
+};
+
+template <HeapMojoWrapperMode Mode>
+class HeapMojoRemoteGCBaseTest : public TestSupportingGC {
+ public:
+ base::RunLoop& run_loop() { return run_loop_; }
+ bool& disconnected() { return disconnected_; }
+
+ void ClearOwner() { owner_ = nullptr; }
+
+ protected:
+ void SetUp() override {
+ CHECK(!disconnected_);
+ context_ = MakeGarbageCollected<MockContext>();
+ owner_ = MakeGarbageCollected<RemoteOwner<Mode>>(context_);
+ scoped_refptr<base::NullTaskRunner> null_task_runner =
+ base::MakeRefCounted<base::NullTaskRunner>();
+ impl_.receiver().Bind(
+ owner_->remote().BindNewPipeAndPassReceiver(null_task_runner));
+ impl_.receiver().set_disconnect_handler(WTF::Bind(
+ [](HeapMojoRemoteGCBaseTest* remote_test) {
+ remote_test->run_loop().Quit();
+ remote_test->disconnected() = true;
+ },
+ WTF::Unretained(this)));
+ }
+
+ ServiceImpl impl_;
+ Persistent<MockContext> context_;
+ Persistent<RemoteOwner<Mode>> owner_;
+ base::RunLoop run_loop_;
+ bool disconnected_ = false;
+};
+
+template <HeapMojoWrapperMode Mode>
+class HeapMojoRemoteDestroyContextBaseTest : public TestSupportingGC {
+ protected:
+ void SetUp() override {
+ context_ = MakeGarbageCollected<MockContext>();
+ owner_ = MakeGarbageCollected<RemoteOwner<Mode>>(context_);
+ scoped_refptr<base::NullTaskRunner> null_task_runner =
+ base::MakeRefCounted<base::NullTaskRunner>();
+ impl_.receiver().Bind(
+ owner_->remote().BindNewPipeAndPassReceiver(null_task_runner));
+ }
+
+ ServiceImpl impl_;
+ Persistent<MockContext> context_;
+ Persistent<RemoteOwner<Mode>> owner_;
+};
+
+} // namespace
+
+class HeapMojoRemoteGCWithContextObserverTest
+ : public HeapMojoRemoteGCBaseTest<
+ HeapMojoWrapperMode::kWithContextObserver> {};
+class HeapMojoRemoteGCWithoutContextObserverTest
+ : public HeapMojoRemoteGCBaseTest<
+ HeapMojoWrapperMode::kWithoutContextObserver> {};
+class HeapMojoRemoteDestroyContextWithContextObserverTest
+ : public HeapMojoRemoteDestroyContextBaseTest<
+ HeapMojoWrapperMode::kWithContextObserver> {};
+class HeapMojoRemoteDestroyContextWithoutContextObserverTest
+ : public HeapMojoRemoteDestroyContextBaseTest<
+ HeapMojoWrapperMode::kWithoutContextObserver> {};
+
+// Make HeapMojoRemote with context observer garbage collected and check that
+// the connection is disconnected right after the marking phase.
+TEST_F(HeapMojoRemoteGCWithContextObserverTest, ResetsOnGC) {
+ ClearOwner();
+ EXPECT_FALSE(disconnected());
+ PreciselyCollectGarbage();
+ run_loop().Run();
+ EXPECT_TRUE(disconnected());
+ CompleteSweepingIfNeeded();
+}
+
+// Make HeapMojoRemote without context observer garbage collected and check that
+// the connection is disconnected right after the marking phase.
+TEST_F(HeapMojoRemoteGCWithoutContextObserverTest, ResetsOnGC) {
+ ClearOwner();
+ EXPECT_FALSE(disconnected());
+ PreciselyCollectGarbage();
+ run_loop().Run();
+ EXPECT_TRUE(disconnected());
+ CompleteSweepingIfNeeded();
+}
+
+// Destroy the context with context observer and check that the connection is
+// disconnected.
+TEST_F(HeapMojoRemoteDestroyContextWithContextObserverTest,
+ ResetsOnContextDestroyed) {
+ EXPECT_TRUE(owner_->remote().is_bound());
+ context_->NotifyContextDestroyed();
+ EXPECT_FALSE(owner_->remote().is_bound());
+}
+
+// Destroy the context without context observer and check that the connection is
+// still connected.
+TEST_F(HeapMojoRemoteDestroyContextWithoutContextObserverTest,
+ ResetsOnContextDestroyed) {
+ EXPECT_TRUE(owner_->remote().is_bound());
+ context_->NotifyContextDestroyed();
+ EXPECT_TRUE(owner_->remote().is_bound());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h
new file mode 100644
index 00000000000..8479bf54e25
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h
@@ -0,0 +1,96 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_UNIQUE_RECEIVER_SET_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_UNIQUE_RECEIVER_SET_H_
+
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/unique_receiver_set.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+// HeapMojoUniqueReceiverSet is a wrapper for mojo::UniqueReceiverSet to be
+// owned by a garbage-collected object. Blink is expected to use
+// HeapMojoUniqueReceiverSet by default. HeapMojoUniqueReceiverSet must be
+// associated with context. HeapMojoUniqueReceiverSet's constructor takes
+// context as a mandatory parameter. HeapMojoUniqueReceiverSet resets the mojo
+// connection when 1) the owner object is garbage-collected or 2) the associated
+// ExecutionContext is detached.
+template <typename Interface,
+ typename Deleter = std::default_delete<Interface>,
+ HeapMojoWrapperMode Mode = HeapMojoWrapperMode::kWithContextObserver>
+class HeapMojoUniqueReceiverSet {
+ DISALLOW_NEW();
+
+ public:
+ using ImplPointerType = typename mojo::Receiver<
+ Interface,
+ mojo::UniquePtrImplRefTraits<Interface, Deleter>>::ImplPointerType;
+
+ explicit HeapMojoUniqueReceiverSet(ContextLifecycleNotifier* context)
+ : wrapper_(MakeGarbageCollected<Wrapper>(context)) {
+ DCHECK(context);
+ }
+
+ // Methods to redirect to mojo::ReceiverSet:
+ mojo::ReceiverId Add(ImplPointerType impl,
+ mojo::PendingReceiver<Interface> receiver,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ return wrapper_->receiver_set().Add(std::move(impl), std::move(receiver),
+ task_runner);
+ }
+
+ bool Remove(mojo::ReceiverId id) {
+ return wrapper_->receiver_set().Remove(id);
+ }
+
+ void Clear() { wrapper_->receiver_set().Clear(); }
+
+ bool HasReceiver(mojo::ReceiverId id) {
+ return wrapper_->receiver_set().HasReceiver(id);
+ }
+
+ void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
+
+ private:
+ // Garbage collected wrapper class to add a prefinalizer.
+ class Wrapper final : public GarbageCollected<Wrapper>,
+ public ContextLifecycleObserver {
+ USING_PRE_FINALIZER(Wrapper, Dispose);
+ USING_GARBAGE_COLLECTED_MIXIN(Wrapper);
+
+ public:
+ explicit Wrapper(ContextLifecycleNotifier* notifier) {
+ SetContextLifecycleNotifier(notifier);
+ }
+
+ void Trace(Visitor* visitor) override {
+ ContextLifecycleObserver::Trace(visitor);
+ }
+
+ void Dispose() { receiver_set_.Clear(); }
+
+ mojo::UniqueReceiverSet<Interface, void, Deleter>& receiver_set() {
+ return receiver_set_;
+ }
+
+ // ContextLifecycleObserver methods
+ void ContextDestroyed() override {
+ if (Mode == HeapMojoWrapperMode::kWithContextObserver)
+ receiver_set_.Clear();
+ }
+
+ private:
+ mojo::UniqueReceiverSet<Interface, void, Deleter> receiver_set_;
+ };
+
+ Member<Wrapper> wrapper_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_UNIQUE_RECEIVER_SET_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc
new file mode 100644
index 00000000000..5438160d598
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set_test.cc
@@ -0,0 +1,214 @@
+// 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 "third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h"
+#include "base/test/null_task_runner.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/interfaces/bindings/tests/sample_service.mojom-blink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/heap_observer_list.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+
+namespace blink {
+
+namespace {
+
+class FakeContextNotifier final : public GarbageCollected<FakeContextNotifier>,
+ public ContextLifecycleNotifier {
+ USING_GARBAGE_COLLECTED_MIXIN(FakeContextNotifier);
+
+ public:
+ FakeContextNotifier() = default;
+
+ void AddContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.AddObserver(observer);
+ }
+ void RemoveContextLifecycleObserver(
+ ContextLifecycleObserver* observer) override {
+ observers_.RemoveObserver(observer);
+ }
+
+ void NotifyContextDestroyed() {
+ observers_.ForEachObserver([](ContextLifecycleObserver* observer) {
+ observer->ContextDestroyed();
+ });
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(observers_);
+ ContextLifecycleNotifier::Trace(visitor);
+ }
+
+ private:
+ HeapObserverList<ContextLifecycleObserver> observers_;
+};
+
+template <HeapMojoWrapperMode Mode>
+class GCOwner : public GarbageCollected<GCOwner<Mode>> {
+ public:
+ explicit GCOwner(FakeContextNotifier* context) : receiver_set_(context) {}
+ void Trace(Visitor* visitor) { visitor->Trace(receiver_set_); }
+
+ HeapMojoUniqueReceiverSet<sample::blink::Service,
+ std::default_delete<sample::blink::Service>,
+ Mode>&
+ receiver_set() {
+ return receiver_set_;
+ }
+
+ private:
+ HeapMojoUniqueReceiverSet<sample::blink::Service,
+ std::default_delete<sample::blink::Service>,
+ Mode>
+ receiver_set_;
+};
+
+template <HeapMojoWrapperMode Mode>
+class HeapMojoUniqueReceiverSetBaseTest : public TestSupportingGC {
+ public:
+ FakeContextNotifier* context() { return context_; }
+ scoped_refptr<base::NullTaskRunner> task_runner() {
+ return null_task_runner_;
+ }
+ GCOwner<Mode>* owner() { return owner_; }
+
+ void ClearOwner() { owner_ = nullptr; }
+
+ void MarkServiceDeleted() { service_deleted_ = true; }
+
+ protected:
+ void SetUp() override {
+ context_ = MakeGarbageCollected<FakeContextNotifier>();
+ owner_ = MakeGarbageCollected<GCOwner<Mode>>(context());
+ }
+ void TearDown() override {}
+
+ Persistent<FakeContextNotifier> context_;
+ Persistent<GCOwner<Mode>> owner_;
+ scoped_refptr<base::NullTaskRunner> null_task_runner_ =
+ base::MakeRefCounted<base::NullTaskRunner>();
+ bool service_deleted_ = false;
+};
+
+class HeapMojoUniqueReceiverSetWithContextObserverTest
+ : public HeapMojoUniqueReceiverSetBaseTest<
+ HeapMojoWrapperMode::kWithContextObserver> {};
+class HeapMojoUniqueReceiverSetWithoutContextObserverTest
+ : public HeapMojoUniqueReceiverSetBaseTest<
+ HeapMojoWrapperMode::kWithoutContextObserver> {};
+
+} // namespace
+
+namespace {
+
+template <typename T>
+class MockService : public sample::blink::Service {
+ public:
+ explicit MockService(T* test) : test_(test) {}
+ // Notify the test when the service is deleted by the UniqueReceiverSet.
+ ~MockService() override { test_->MarkServiceDeleted(); }
+
+ void Frobinate(sample::blink::FooPtr foo,
+ Service::BazOptions baz,
+ mojo::PendingRemote<sample::blink::Port> port,
+ FrobinateCallback callback) override {}
+ void GetPort(mojo::PendingReceiver<sample::blink::Port> receiver) override {}
+
+ private:
+ T* test_;
+};
+
+} // namespace
+
+// GC the HeapMojoUniqueReceiverSet with context observer and verify that the
+// receiver is no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoUniqueReceiverSetWithContextObserverTest, ResetsOnGC) {
+ auto receiver_set = owner()->receiver_set();
+ auto service = std::make_unique<
+ MockService<HeapMojoUniqueReceiverSetWithContextObserverTest>>(this);
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(std::move(service), std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+ EXPECT_FALSE(service_deleted_);
+
+ ClearOwner();
+ PreciselyCollectGarbage();
+
+ EXPECT_TRUE(service_deleted_);
+
+ CompleteSweepingIfNeeded();
+}
+
+// GC the HeapMojoUniqueReceiverSet without context observer and verify that the
+// receiver is no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoUniqueReceiverSetWithoutContextObserverTest, ResetsOnGC) {
+ auto receiver_set = owner()->receiver_set();
+ auto service = std::make_unique<
+ MockService<HeapMojoUniqueReceiverSetWithoutContextObserverTest>>(this);
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(std::move(service), std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+ EXPECT_FALSE(service_deleted_);
+
+ ClearOwner();
+ PreciselyCollectGarbage();
+
+ EXPECT_TRUE(service_deleted_);
+
+ CompleteSweepingIfNeeded();
+}
+
+// Destroy the context with context observer and verify that the receiver is no
+// longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoUniqueReceiverSetWithContextObserverTest,
+ ResetsOnContextDestroyed) {
+ HeapMojoUniqueReceiverSet<sample::blink::Service> receiver_set(context());
+ auto service = std::make_unique<
+ MockService<HeapMojoUniqueReceiverSetWithContextObserverTest>>(this);
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(std::move(service), std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+ EXPECT_FALSE(service_deleted_);
+
+ context_->NotifyContextDestroyed();
+
+ EXPECT_FALSE(receiver_set.HasReceiver(rid));
+ EXPECT_TRUE(service_deleted_);
+}
+
+// Destroy the context without context observer and verify that the receiver is
+// no longer part of the set, and that the service was deleted.
+TEST_F(HeapMojoUniqueReceiverSetWithoutContextObserverTest,
+ ResetsOnContextDestroyed) {
+ HeapMojoUniqueReceiverSet<sample::blink::Service> receiver_set(context());
+ auto service = std::make_unique<
+ MockService<HeapMojoUniqueReceiverSetWithoutContextObserverTest>>(this);
+ auto receiver = mojo::PendingReceiver<sample::blink::Service>(
+ mojo::MessagePipe().handle0);
+
+ mojo::ReceiverId rid =
+ receiver_set.Add(std::move(service), std::move(receiver), task_runner());
+ EXPECT_TRUE(receiver_set.HasReceiver(rid));
+ EXPECT_FALSE(service_deleted_);
+
+ context_->NotifyContextDestroyed();
+
+ EXPECT_FALSE(receiver_set.HasReceiver(rid));
+ EXPECT_TRUE(service_deleted_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h
new file mode 100644
index 00000000000..f59f0e0e8dc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_WRAPPER_MODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_WRAPPER_MODE_H_
+
+namespace blink {
+
+// A list of modes for HeapMojo wrappers.
+// TODO(crbug.com/1058076) This is just a temporary thing to keep the existing
+// behavior during the release freeze.
+enum class HeapMojoWrapperMode {
+ // Resets the mojo connection when 1) the owner object is garbage-collected
+ // and 2) the associated ExecutionContext is detached.
+ kWithContextObserver,
+ // Resets the mojo connection when the owner object is garbage-collected.
+ // But, it will not reset the mojo connection when the associated
+ // ExecutionContext is detached.
+ kWithoutContextObserver,
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_HEAP_MOJO_WRAPPER_MODE_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/kurl.typemap b/chromium/third_party/blink/renderer/platform/mojo/kurl.typemap
deleted file mode 100644
index 8a25d18986b..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/kurl.typemap
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//url/mojom/url.mojom"
-public_headers = [
- "//third_party/blink/renderer/platform/weborigin/kurl.h",
- "//third_party/blink/renderer/platform/weborigin/kurl_hash.h",
-]
-traits_headers =
- [ "//third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h" ]
-
-# Note: consumers of this typemap must themselves depend on platform.
-deps = [
- "//mojo/public/cpp/bindings",
- "//url",
-]
-type_mappings = [ "url.mojom.Url=::blink::KURL[force_serialize]" ]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h
index bcd6a69e8df..f50dd8444e6 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h
@@ -5,15 +5,16 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_KURL_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_KURL_MOJOM_TRAITS_H_
+#include "mojo/public/cpp/bindings/string_traits_wtf.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "url/mojom/url.mojom-blink-forward.h"
+#include "url/mojom/url.mojom-shared.h"
#include "url/url_constants.h"
namespace mojo {
template <>
-struct StructTraits<url::mojom::blink::Url::DataView, ::blink::KURL> {
+struct StructTraits<url::mojom::UrlDataView, ::blink::KURL> {
static WTF::String url(const ::blink::KURL& blinkUrl) {
if (!blinkUrl.IsValid() ||
blinkUrl.GetString().length() > url::kMaxURLChars) {
@@ -22,7 +23,7 @@ struct StructTraits<url::mojom::blink::Url::DataView, ::blink::KURL> {
return blinkUrl.GetString();
}
- static bool Read(url::mojom::blink::Url::DataView data, ::blink::KURL* out) {
+ static bool Read(url::mojom::UrlDataView data, ::blink::KURL* out) {
WTF::String urlString;
if (!data.ReadUrl(&urlString))
return false;
diff --git a/chromium/third_party/blink/renderer/platform/mojo/security_origin.typemap b/chromium/third_party/blink/renderer/platform/mojo/security_origin.typemap
deleted file mode 100644
index f94a2bb7732..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/security_origin.typemap
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//url/mojom/origin.mojom"
-public_headers =
- [ "//third_party/blink/renderer/platform/weborigin/security_origin.h" ]
-traits_headers = [
- "//third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h",
-]
-
-# Note: consumers of this typemap must themselves depend on platform.
-deps = [
- "//mojo/public/cpp/bindings",
- "//url",
-]
-type_mappings = [ "url.mojom.Origin=::scoped_refptr<const ::blink::SecurityOrigin>[nullable_is_same_type]" ]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
index 386bc631ecd..925965d09b5 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
@@ -5,10 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_SECURITY_ORIGIN_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_SECURITY_ORIGIN_MOJOM_TRAITS_H_
+#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "mojo/public/cpp/bindings/string_traits_wtf.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "url/mojom/origin.mojom-blink-forward.h"
+#include "url/mojom/origin.mojom-shared.h"
#include "url/scheme_host_port.h"
namespace mojo {
@@ -22,7 +24,7 @@ struct UrlOriginAdapter {
const url::SchemeHostPort& tuple,
const base::Optional<base::UnguessableToken>& nonce_if_opaque) {
scoped_refptr<blink::SecurityOrigin> tuple_origin;
- if (!tuple.IsInvalid()) {
+ if (tuple.IsValid()) {
// url::SchemeHostPort is percent encoded and SecurityOrigin is percent
// decoded.
String host = blink::DecodeURLEscapeSequences(
@@ -45,7 +47,7 @@ struct UrlOriginAdapter {
};
template <>
-struct StructTraits<url::mojom::blink::Origin::DataView,
+struct StructTraits<url::mojom::OriginDataView,
scoped_refptr<const ::blink::SecurityOrigin>> {
static WTF::String scheme(
const scoped_refptr<const ::blink::SecurityOrigin>& origin) {
@@ -65,7 +67,7 @@ struct StructTraits<url::mojom::blink::Origin::DataView,
const scoped_refptr<const ::blink::SecurityOrigin>& origin) {
return UrlOriginAdapter::nonce_if_opaque(origin);
}
- static bool Read(url::mojom::blink::Origin::DataView data,
+ static bool Read(url::mojom::OriginDataView data,
scoped_refptr<const ::blink::SecurityOrigin>* out) {
// This implementation is very close to
// SecurityOrigin::CreateFromUrlOrigin, so keep in sync if modifications
@@ -79,7 +81,7 @@ struct StructTraits<url::mojom::blink::Origin::DataView,
const url::SchemeHostPort& tuple =
url::SchemeHostPort(scheme, host, data.port());
- if (tuple.IsInvalid()) {
+ if (!tuple.IsValid()) {
// If the tuple is invalid, it is a valid case if and only if it is an
// opaque origin and the scheme, host, and port are empty.
if (!nonce_if_opaque)
diff --git a/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc
index 07be8469c2d..9efcde17184 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/string16_mojom_traits_test.cc
@@ -7,7 +7,6 @@
#include "base/macros.h"
#include "base/rand_util.h"
#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "mojo/public/mojom/base/string16.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/renderer/platform/network/BUILD.gn b/chromium/third_party/blink/renderer/platform/network/BUILD.gn
index 2bc375f8c61..983c4aba408 100644
--- a/chromium/third_party/blink/renderer/platform/network/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/network/BUILD.gn
@@ -18,9 +18,7 @@ group("make_generated") {
"//third_party/blink/renderer/platform:*",
]
- public_deps = [
- ":http_names",
- ]
+ public_deps = [ ":http_names" ]
}
blink_platform_sources("network") {
@@ -41,6 +39,7 @@ blink_platform_sources("network") {
"header_field_tokenizer.h",
"http_header_map.cc",
"http_header_map.h",
+ "http_header_set.h",
"http_parsers.cc",
"http_parsers.h",
"http_request_headers_mojom_traits.cc",
@@ -69,9 +68,7 @@ blink_platform_sources("network") {
sources += get_target_outputs(":http_names")
- deps = [
- "//media",
- ]
+ deps = [ "//media" ]
}
jumbo_source_set("unit_tests") {
@@ -91,21 +88,15 @@ jumbo_source_set("unit_tests") {
configs += [ "//third_party/blink/renderer/platform:blink_platform_config" ]
- deps = [
- "//testing/gtest",
- ]
- public_deps = [
- "//third_party/blink/renderer/platform:platform",
- ]
+ deps = [ "//testing/gtest" ]
+ public_deps = [ "//third_party/blink/renderer/platform:platform" ]
}
jumbo_source_set("test_support") {
visibility = [ "//third_party/blink/renderer/platform:test_support" ]
testonly = true
- sources = [
- "mime/mock_mime_registry.h",
- ]
+ sources = [ "mime/mock_mime_registry.h" ]
configs += [
"//third_party/blink/renderer:non_test_config",
diff --git a/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc b/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc
index 3d106e98802..212c2b97594 100644
--- a/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc
+++ b/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
-#include "third_party/blink/public/platform/web_content_security_policy.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
@@ -58,16 +57,4 @@ bool IsMediaTypeCharacter(UChar c) {
return !IsASCIISpace(c) && c != '/';
}
-STATIC_ASSERT_ENUM(network::mojom::ContentSecurityPolicyType::kReport,
- kContentSecurityPolicyHeaderTypeReport);
-STATIC_ASSERT_ENUM(network::mojom::ContentSecurityPolicyType::kEnforce,
- kContentSecurityPolicyHeaderTypeEnforce);
-
-STATIC_ASSERT_ENUM(network::mojom::ContentSecurityPolicySource::kHTTP,
- kContentSecurityPolicyHeaderSourceHTTP);
-STATIC_ASSERT_ENUM(network::mojom::ContentSecurityPolicySource::kMeta,
- kContentSecurityPolicyHeaderSourceMeta);
-STATIC_ASSERT_ENUM(network::mojom::ContentSecurityPolicySource::kOriginPolicy,
- kContentSecurityPolicyHeaderSourceOriginPolicy);
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h b/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
index e352fa904e3..4165e180916 100644
--- a/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
+++ b/chromium/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
@@ -13,17 +13,6 @@ namespace blink {
typedef std::pair<unsigned, DigestValue> CSPHashValue;
-enum ContentSecurityPolicyHeaderType {
- kContentSecurityPolicyHeaderTypeReport,
- kContentSecurityPolicyHeaderTypeEnforce
-};
-
-enum ContentSecurityPolicyHeaderSource {
- kContentSecurityPolicyHeaderSourceHTTP,
- kContentSecurityPolicyHeaderSourceMeta,
- kContentSecurityPolicyHeaderSourceOriginPolicy
-};
-
enum ContentSecurityPolicyHashAlgorithm {
kContentSecurityPolicyHashAlgorithmNone = 0,
kContentSecurityPolicyHashAlgorithmSha256 = 1 << 2,
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc
index 03a6c6d3aac..eb21bafdb1f 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc
@@ -175,9 +175,11 @@ void EncodedFormData::AppendData(const void* data, wtf_size_t size) {
memcpy(e.data_.data() + old_size, data, size);
}
-void EncodedFormData::AppendFile(const String& filename) {
- elements_.push_back(
- FormDataElement(filename, 0, BlobData::kToEndOfFile, base::nullopt));
+void EncodedFormData::AppendFile(
+ const String& filename,
+ const base::Optional<base::Time>& expected_modification_time) {
+ elements_.push_back(FormDataElement(filename, 0, BlobData::kToEndOfFile,
+ expected_modification_time));
}
void EncodedFormData::AppendFileRange(
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h
index a3de079f0ce..cbb1eed257e 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h
@@ -110,7 +110,8 @@ class PLATFORM_EXPORT EncodedFormData : public RefCounted<EncodedFormData> {
~EncodedFormData();
void AppendData(const void* data, wtf_size_t);
- void AppendFile(const String& file_path);
+ void AppendFile(const String& file_path,
+ const base::Optional<base::Time>& expected_modification_time);
void AppendFileRange(
const String& filename,
int64_t start,
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
index 4807a6de7a7..d95ad2f00f0 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
@@ -18,7 +18,6 @@
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h"
diff --git a/chromium/third_party/blink/renderer/platform/network/http_header_set.h b/chromium/third_party/blink/renderer/platform/network/http_header_set.h
new file mode 100644
index 00000000000..80a501f9dad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/network/http_header_set.h
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_HTTP_HEADER_SET_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_HTTP_HEADER_SET_H_
+
+#include <set>
+#include <string>
+#include "base/strings/string_util.h"
+
+namespace blink {
+
+struct CompareIgnoreCase {
+ bool operator()(const std::string& left, const std::string& right) const {
+ return base::CompareCaseInsensitiveASCII(left, right) < 0;
+ }
+};
+
+using HTTPHeaderSet = std::set<std::string, CompareIgnoreCase>;
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_HTTP_HEADER_SET_H_
diff --git a/chromium/third_party/blink/renderer/platform/network/http_names.json5 b/chromium/third_party/blink/renderer/platform/network/http_names.json5
index 248c5e8a11c..fa2fda6cc0d 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_names.json5
+++ b/chromium/third_party/blink/renderer/platform/network/http_names.json5
@@ -31,6 +31,8 @@
"Content-Security-Policy",
"Content-Security-Policy-Report-Only",
"Content-Type",
+ "Document-Policy",
+ "Document-Policy-Report-Only",
"ETag",
"Expires",
"Date",
@@ -51,11 +53,11 @@
"Ping-To",
"Pragma",
"Range",
- // TODO(domfarolino): Remove "Referer" as part of https://crbug.com/850813.
"Referer",
"Referrer-Policy",
"Refresh",
"Resource-Freshness",
+ "Require-Document-Policy",
"Save-Data",
"Sec-CH-Lang",
"Sec-Required-CSP",
diff --git a/chromium/third_party/blink/renderer/platform/network/http_parsers.cc b/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
index 9c376f04607..49218661ef4 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
+++ b/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -409,17 +409,17 @@ CacheControlHeader ParseCacheControlDirectives(
for (wtf_size_t i = 0; i < directives_size; ++i) {
// RFC2616 14.9.1: A no-cache directive with a value is only meaningful
// for proxy caches. It should be ignored by a browser level cache.
- if (DeprecatedEqualIgnoringCase(directives[i].first, kNoCacheDirective) &&
+ if (EqualIgnoringASCIICase(directives[i].first, kNoCacheDirective) &&
directives[i].second.IsEmpty()) {
cache_control_header.contains_no_cache = true;
- } else if (DeprecatedEqualIgnoringCase(directives[i].first,
- kNoStoreDirective)) {
+ } else if (EqualIgnoringASCIICase(directives[i].first,
+ kNoStoreDirective)) {
cache_control_header.contains_no_store = true;
- } else if (DeprecatedEqualIgnoringCase(directives[i].first,
- kMustRevalidateDirective)) {
+ } else if (EqualIgnoringASCIICase(directives[i].first,
+ kMustRevalidateDirective)) {
cache_control_header.contains_must_revalidate = true;
- } else if (DeprecatedEqualIgnoringCase(directives[i].first,
- kMaxAgeDirective)) {
+ } else if (EqualIgnoringASCIICase(directives[i].first,
+ kMaxAgeDirective)) {
if (cache_control_header.max_age) {
// First max-age directive wins if there are multiple ones.
continue;
@@ -428,8 +428,8 @@ CacheControlHeader ParseCacheControlDirectives(
double max_age = directives[i].second.ToDouble(&ok);
if (ok)
cache_control_header.max_age = base::TimeDelta::FromSecondsD(max_age);
- } else if (DeprecatedEqualIgnoringCase(directives[i].first,
- kStaleWhileRevalidateDirective)) {
+ } else if (EqualIgnoringASCIICase(directives[i].first,
+ kStaleWhileRevalidateDirective)) {
if (cache_control_header.stale_while_revalidate) {
// First stale-while-revalidate directive wins if there are multiple
// ones.
diff --git a/chromium/third_party/blink/renderer/platform/network/mime/content_type.cc b/chromium/third_party/blink/renderer/platform/network/mime/content_type.cc
index 95072e109fa..5a3c8b0fa5e 100644
--- a/chromium/third_party/blink/renderer/platform/network/mime/content_type.cc
+++ b/chromium/third_party/blink/renderer/platform/network/mime/content_type.cc
@@ -32,35 +32,29 @@ namespace blink {
ContentType::ContentType(const String& content_type) : type_(content_type) {}
+static bool IsASCIIQuote(UChar c) {
+ return c == '"';
+}
+
String ContentType::Parameter(const String& parameter_name) const {
- String parameter_value;
- String stripped_type = type_.StripWhiteSpace();
+ Vector<String> parameters;
+ ParseParameters(parameters);
- // a MIME type can have one or more "param=value" after a semi-colon, and
- // separated from each other by semi-colons
- wtf_size_t semi = stripped_type.find(';');
- if (semi != kNotFound) {
- wtf_size_t start =
- stripped_type.FindIgnoringASCIICase(parameter_name, semi + 1);
- if (start != kNotFound) {
- start = stripped_type.find('=', start + parameter_name.length());
- if (start != kNotFound) {
- wtf_size_t quote = stripped_type.find('\"', start + 1);
- wtf_size_t end = stripped_type.find('\"', start + 2);
- if (quote != kNotFound && end != kNotFound) {
- start = quote;
- } else {
- end = stripped_type.find(';', start + 1);
- if (end == kNotFound)
- end = stripped_type.length();
- }
- parameter_value = stripped_type.Substring(start + 1, end - (start + 1))
- .StripWhiteSpace();
+ for (auto& parameter : parameters) {
+ String stripped_parameter = parameter.StripWhiteSpace();
+ wtf_size_t separator_pos = stripped_parameter.find('=');
+ if (separator_pos != kNotFound) {
+ String attribute =
+ stripped_parameter.Left(separator_pos).StripWhiteSpace();
+ if (EqualIgnoringASCIICase(attribute, parameter_name)) {
+ return stripped_parameter.Substring(separator_pos + 1)
+ .StripWhiteSpace()
+ .RemoveCharacters(IsASCIIQuote);
}
}
}
- return parameter_value;
+ return String();
}
String ContentType::GetType() const {
@@ -74,4 +68,29 @@ String ContentType::GetType() const {
return stripped_type;
}
+void ContentType::ParseParameters(Vector<String>& result) const {
+ String stripped_type = type_.StripWhiteSpace();
+
+ unsigned cur_pos = 0;
+ unsigned end_pos = stripped_type.length();
+ unsigned start_pos = 0;
+ bool is_quote = false;
+
+ while (cur_pos < end_pos) {
+ if (!is_quote && stripped_type[cur_pos] == ';') {
+ if (cur_pos != start_pos) {
+ result.push_back(
+ stripped_type.Substring(start_pos, cur_pos - start_pos));
+ }
+ start_pos = cur_pos + 1;
+ } else if (stripped_type[cur_pos] == '"') {
+ is_quote = !is_quote;
+ }
+ cur_pos++;
+ }
+
+ if (start_pos != end_pos)
+ result.push_back(stripped_type.Substring(start_pos));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/network/mime/content_type.h b/chromium/third_party/blink/renderer/platform/network/mime/content_type.h
index e1d5bbc6a75..e02b0986537 100644
--- a/chromium/third_party/blink/renderer/platform/network/mime/content_type.h
+++ b/chromium/third_party/blink/renderer/platform/network/mime/content_type.h
@@ -44,6 +44,8 @@ class PLATFORM_EXPORT ContentType {
const String& Raw() const { return type_; }
private:
+ void ParseParameters(Vector<String>& result) const;
+
String type_;
};
diff --git a/chromium/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc b/chromium/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc
index 9f56c4b2da6..e35ee692fe3 100644
--- a/chromium/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc
+++ b/chromium/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc
@@ -11,9 +11,9 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/mime_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/mime/mime_registry.mojom-blink.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -25,7 +25,7 @@ namespace {
struct MimeRegistryPtrHolder {
public:
MimeRegistryPtrHolder() {
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
mime_registry.BindNewPipeAndPassReceiver());
}
~MimeRegistryPtrHolder() = default;
@@ -193,7 +193,7 @@ bool MIMETypeRegistry::IsSupportedFontMIMEType(const String& mime_type) {
static const unsigned kFontLen = 5;
if (!mime_type.StartsWithIgnoringASCIICase("font/"))
return false;
- String sub_type = mime_type.Substring(kFontLen).DeprecatedLower();
+ String sub_type = mime_type.Substring(kFontLen).LowerASCII();
return sub_type == "woff" || sub_type == "woff2" || sub_type == "otf" ||
sub_type == "ttf" || sub_type == "sfnt";
}
diff --git a/chromium/third_party/blink/renderer/platform/p2p/OWNERS b/chromium/third_party/blink/renderer/platform/p2p/OWNERS
index 70573c449d9..eabc2b276ea 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/p2p/OWNERS
@@ -1,4 +1,5 @@
+guidou@chromium.org
sergeyu@chromium.org
-juberti@chromium.org
+steveanton@chromium.org
# COMPONENT: Blink>WebRTC
diff --git a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc
index c5131f81207..d2407625650 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc
@@ -6,22 +6,20 @@
#include <utility>
-#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/media_permission.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
FilteringNetworkManager::FilteringNetworkManager(
rtc::NetworkManager* network_manager,
- const GURL& requesting_origin,
media::MediaPermission* media_permission,
bool allow_mdns_obfuscation)
: network_manager_(network_manager),
media_permission_(media_permission),
- requesting_origin_(requesting_origin),
allow_mdns_obfuscation_(allow_mdns_obfuscation) {
DETACH_FROM_THREAD(thread_checker_);
set_enumeration_permission(ENUMERATION_BLOCKED);
@@ -117,12 +115,10 @@ void FilteringNetworkManager::CheckPermission() {
// Request for media permission asynchronously.
media_permission_->HasPermission(
media::MediaPermission::AUDIO_CAPTURE,
- base::BindOnce(&FilteringNetworkManager::OnPermissionStatus,
- GetWeakPtr()));
+ WTF::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
media_permission_->HasPermission(
media::MediaPermission::VIDEO_CAPTURE,
- base::BindOnce(&FilteringNetworkManager::OnPermissionStatus,
- GetWeakPtr()));
+ WTF::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
}
void FilteringNetworkManager::OnPermissionStatus(bool granted) {
@@ -210,9 +206,8 @@ void FilteringNetworkManager::FireEventIfStarted() {
//
// TODO(crbug.com/787254): Use Frame-based TaskRunner here.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&FilteringNetworkManager::SendNetworksChangedSignal,
- GetWeakPtr()));
+ FROM_HERE, WTF::Bind(&FilteringNetworkManager::SendNetworksChangedSignal,
+ GetWeakPtr()));
sent_first_update_ = true;
}
diff --git a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
index 1bc21566bab..8243e2f0046 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/rtc_base/network.h"
#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
-#include "url/gurl.h"
namespace media {
class MediaPermission;
@@ -34,8 +33,6 @@ namespace blink {
// rtc::NetworkManagerBase to have the same implementation of
// GetAnyAddressNetworks(). We can't mark the whole class PLATFORM_EXPORT
// as it requires all super classes to be PLATFORM_EXPORT as well.
-//
-// TODO(crbug.com/787254): Also, move it away from url/gurl.h.
class FilteringNetworkManager : public rtc::NetworkManagerBase,
public sigslot::has_slots<> {
public:
@@ -43,7 +40,6 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
// worker thread |task_runner|.
PLATFORM_EXPORT FilteringNetworkManager(
rtc::NetworkManager* network_manager,
- const GURL& requesting_origin,
media::MediaPermission* media_permission,
bool allow_mdns_obfuscation);
@@ -116,8 +112,6 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
// the setup time.
base::TimeTicks start_updating_time_;
- GURL requesting_origin_;
-
// When the mDNS obfuscation is allowed, access to the mDNS responder provided
// by the base network manager is provided to conceal IPs with mDNS hostnames.
bool allow_mdns_obfuscation_ = true;
diff --git a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
index 6b2da1ad524..177722fa4ae 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
@@ -171,7 +171,7 @@ class FilteringNetworkManagerTest : public testing::Test,
SetNewNetworkForBaseNetworkManager();
if (multiple_routes_requested) {
network_manager_ = std::make_unique<FilteringNetworkManager>(
- base_network_manager_.get(), GURL(), media_permission_.get(),
+ base_network_manager_.get(), media_permission_.get(),
allow_mdns_obfuscation_);
network_manager_->Initialize();
} else {
diff --git a/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc
index eca457b7ee7..1e36c27d132 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc
@@ -6,12 +6,12 @@
#include <utility>
-#include "base/bind.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "jingle/glue/utils.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -19,7 +19,6 @@ namespace blink {
P2PAsyncAddressResolver::P2PAsyncAddressResolver(
P2PSocketDispatcher* dispatcher)
: dispatcher_(dispatcher), state_(STATE_CREATED) {
- AddRef(); // Balanced in Destroy().
}
P2PAsyncAddressResolver::~P2PAsyncAddressResolver() {
@@ -37,8 +36,8 @@ void P2PAsyncAddressResolver::Start(const rtc::SocketAddress& host_name,
blink::features::kWebRtcHideLocalIpsWithMdns);
dispatcher_->GetP2PSocketManager()->GetHostAddress(
String(host_name.hostname().data()), enable_mdns,
- base::BindOnce(&P2PAsyncAddressResolver::OnResponse,
- base::Unretained(this)));
+ WTF::Bind(&P2PAsyncAddressResolver::OnResponse,
+ scoped_refptr<P2PAsyncAddressResolver>(this)));
}
void P2PAsyncAddressResolver::Cancel() {
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
index 1ac806df97a..8a125da49e4 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
@@ -8,7 +8,6 @@
#include <utility>
#include <vector>
-#include "base/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
@@ -19,6 +18,7 @@
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/webrtc/rtc_base/socket_address.h"
namespace blink {
@@ -62,8 +62,8 @@ void IpcNetworkManager::StartUpdating() {
if (network_list_received_) {
// Post a task to avoid reentrancy.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&IpcNetworkManager::SendNetworksChangedSignal,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, WTF::Bind(&IpcNetworkManager::SendNetworksChangedSignal,
+ weak_factory_.GetWeakPtr()));
} else {
VLOG(1) << "IpcNetworkManager::StartUpdating called; still waiting for "
"network list from browser process.";
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
index a28777e90c0..57c834e7e52 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
@@ -9,12 +9,10 @@
#include <algorithm>
#include <list>
-#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_checker.h"
#include "base/trace_event/trace_event.h"
@@ -25,6 +23,7 @@
#include "third_party/blink/renderer/platform/p2p/socket_client_delegate.h"
#include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/webrtc/rtc_base/async_packet_socket.h"
@@ -226,7 +225,7 @@ class AsyncAddressResolverImpl : public rtc::AsyncResolverInterface {
scoped_refptr<P2PAsyncAddressResolver> resolver_;
- SEQUENCE_CHECKER(sequence_checker_);
+ THREAD_CHECKER(thread_checker_);
rtc::SocketAddress addr_; // Address to resolve.
std::vector<rtc::IPAddress> addresses_; // Resolved addresses.
@@ -423,9 +422,8 @@ int IpcPacketSocket::SendTo(const void* data,
send_bytes_available_ -= data_size;
- const int8_t* data_char = reinterpret_cast<const int8_t*>(data);
Vector<int8_t> data_vector;
- data_vector.AppendRange(data_char, data_char + data_size);
+ data_vector.Append(reinterpret_cast<const int8_t*>(data), data_size);
uint64_t packet_id = client_->Send(address_chrome, data_vector, options);
// Ensure packet_id is not 0. It can't be the case according to
@@ -651,27 +649,26 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
AsyncAddressResolverImpl::AsyncAddressResolverImpl(
P2PSocketDispatcher* dispatcher)
- : resolver_(new P2PAsyncAddressResolver(dispatcher)) {}
+ : resolver_(base::MakeRefCounted<P2PAsyncAddressResolver>(dispatcher)) {}
AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Port and hostname must be copied to the resolved address returned from
// GetResolvedAddress.
addr_ = addr;
- resolver_->Start(addr,
- base::BindOnce(&AsyncAddressResolverImpl::OnAddressResolved,
- base::Unretained(this)));
+ resolver_->Start(addr, WTF::Bind(&AsyncAddressResolverImpl::OnAddressResolved,
+ WTF::Unretained(this)));
}
bool AsyncAddressResolverImpl::GetResolvedAddress(
int family,
rtc::SocketAddress* addr) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (addresses_.empty())
return false;
@@ -687,12 +684,12 @@ bool AsyncAddressResolverImpl::GetResolvedAddress(
}
int AsyncAddressResolverImpl::GetError() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return addresses_.empty() ? -1 : 0;
}
void AsyncAddressResolverImpl::Destroy(bool wait) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
resolver_->Cancel();
// Libjingle doesn't need this object any more and it's not going to delete
// it explicitly.
@@ -701,7 +698,7 @@ void AsyncAddressResolverImpl::Destroy(bool wait) {
void AsyncAddressResolverImpl::OnAddressResolved(
const Vector<net::IPAddress>& addresses) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (size_t i = 0; i < addresses.size(); ++i) {
rtc::SocketAddress socket_address;
if (!jingle_glue::IPEndPointToSocketAddress(
diff --git a/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
index ffb14185658..3c725d7bd96 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "base/bind.h"
#include "jingle/glue/utils.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/ip_address.h"
@@ -14,6 +13,7 @@
#include "services/network/public/mojom/mdns_responder.mojom-blink.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/webrtc/rtc_base/ip_address.h"
@@ -56,14 +56,14 @@ void MdnsResponderAdapter::CreateNameForAddress(const rtc::IPAddress& addr,
NameCreatedCallback callback) {
shared_remote_client_->CreateNameForAddress(
jingle_glue::RtcIPAddressToNetIPAddress(addr),
- base::BindOnce(&OnNameCreatedForAddress, callback, addr));
+ WTF::Bind(&OnNameCreatedForAddress, callback, addr));
}
void MdnsResponderAdapter::RemoveNameForAddress(const rtc::IPAddress& addr,
NameRemovedCallback callback) {
shared_remote_client_->RemoveNameForAddress(
jingle_glue::RtcIPAddressToNetIPAddress(addr),
- base::BindOnce(&OnNameRemovedForAddress, callback));
+ WTF::Bind(&OnNameRemovedForAddress, callback));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
index cbf7777bd9d..eb405977fad 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
-#include "base/bind.h"
#include "base/location.h"
#include "base/time/time.h"
#include "crypto/random.h"
#include "services/network/public/cpp/p2p_param_traits.h"
#include "third_party/blink/renderer/platform/p2p/socket_client_delegate.h"
#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace {
@@ -60,8 +60,8 @@ void P2PSocketClientImpl::Init(
type, local_address, network::P2PPortRange(min_port, max_port),
remote_address, receiver_.BindNewPipeAndPassRemote(),
socket_.BindNewPipeAndPassReceiver());
- receiver_.set_disconnect_handler(base::BindOnce(
- &P2PSocketClientImpl::OnConnectionError, base::Unretained(this)));
+ receiver_.set_disconnect_handler(WTF::Bind(
+ &P2PSocketClientImpl::OnConnectionError, WTF::Unretained(this)));
}
uint64_t P2PSocketClientImpl::Send(const net::IPEndPoint& address,
@@ -82,7 +82,7 @@ void P2PSocketClientImpl::SendWithPacketId(const net::IPEndPoint& address,
const Vector<int8_t>& data,
const rtc::PacketOptions& options,
uint64_t packet_id) {
- TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", packet_id);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("p2p", "Send", packet_id);
socket_->Send(data, network::P2PPacketInfo(address, options, packet_id),
net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
@@ -143,8 +143,8 @@ void P2PSocketClientImpl::IncomingTcpConnection(
new_client->socket_.Bind(std::move(socket));
new_client->receiver_.Bind(std::move(client_receiver));
- new_client->receiver_.set_disconnect_handler(base::BindOnce(
- &P2PSocketClientImpl::OnConnectionError, base::Unretained(this)));
+ new_client->receiver_.set_disconnect_handler(WTF::Bind(
+ &P2PSocketClientImpl::OnConnectionError, WTF::Unretained(this)));
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (delegate_) {
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
index 370e34ed1ac..6c3adda46f7 100644
--- a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
@@ -4,13 +4,14 @@
#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
-#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/cpp/p2p_param_traits.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
#include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -24,10 +25,10 @@ P2PSocketDispatcher::~P2PSocketDispatcher() {}
void P2PSocketDispatcher::AddNetworkListObserver(
blink::NetworkListObserver* network_list_observer) {
network_list_observers_->AddObserver(network_list_observer);
- main_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketDispatcher::RequestNetworkEventsIfNecessary,
- this));
+ PostCrossThreadTask(
+ *main_task_runner_.get(), FROM_HERE,
+ CrossThreadBindOnce(&P2PSocketDispatcher::RequestNetworkEventsIfNecessary,
+ scoped_refptr<P2PSocketDispatcher>(this)));
}
void P2PSocketDispatcher::RemoveNetworkListObserver(
@@ -47,13 +48,14 @@ P2PSocketDispatcher::GetP2PSocketManager() {
mojo::SharedRemote<network::mojom::blink::P2PSocketManager>(
std::move(p2p_socket_manager));
p2p_socket_manager_.set_disconnect_handler(
- base::BindOnce(&P2PSocketDispatcher::OnConnectionError,
- base::Unretained(this)),
+ WTF::Bind(&P2PSocketDispatcher::OnConnectionError,
+ WTF::Unretained(this)),
main_task_runner_);
}
- main_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketDispatcher::RequestInterfaceIfNecessary, this));
+ PostCrossThreadTask(
+ *main_task_runner_.get(), FROM_HERE,
+ CrossThreadBindOnce(&P2PSocketDispatcher::RequestInterfaceIfNecessary,
+ scoped_refptr<P2PSocketDispatcher>(this)));
return p2p_socket_manager_.get();
}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/DEPS b/chromium/third_party/blink/renderer/platform/peerconnection/DEPS
index 705fa3fe2c3..d6fd407fe98 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/DEPS
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/DEPS
@@ -14,10 +14,12 @@ include_rules = [
"+base/strings/string_split.h",
"+base/threading/thread_restrictions.h",
"+media/base",
+ "+media/capture/capture_switches.h",
"+media/media_buildflags.h",
"+media/video/gpu_video_accelerator_factories.h",
"+media/video/video_decode_accelerator.h",
"+media/video/h264_parser.h",
+ "+media/video/supported_video_decoder_config.h",
"+media/video/video_encode_accelerator.h",
"+third_party/blink/renderer/platform/bindings/script_wrappable.h",
"+third_party/blink/renderer/platform/heap",
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h
index 6f841c8a270..d88a917ed73 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h
@@ -18,7 +18,7 @@ class RTCAnswerOptionsPlatform final
bool VoiceActivityDetection() const { return voice_activity_detection_; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
bool voice_activity_detection_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h
index 86aa4a620e2..dd0ff33cf06 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_dtmf_sender_handler.h
@@ -39,7 +39,7 @@ class PLATFORM_EXPORT RtcDtmfSenderHandler final {
virtual ~Client() = default;
virtual void DidPlayTone(const String& tone) = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
RtcDtmfSenderHandler(scoped_refptr<base::SingleThreadTaskRunner> main_thread,
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc
new file mode 100644
index 00000000000..18f46d1d094
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.cc
@@ -0,0 +1,137 @@
+// 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 "third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/webrtc/api/frame_transformer_interface.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+
+namespace blink {
+
+namespace {
+
+// This delegate class exists to work around the fact that
+// RTCEncodedAudioStreamTransformer cannot derive from rtc::RefCountedObject
+// and post tasks referencing itself as an rtc::scoped_refptr. Instead,
+// RTCEncodedAudioStreamTransformer creates a delegate using
+// rtc::RefCountedObject and posts tasks referencing the delegate, which invokes
+// the RTCEncodedAudioStreamTransformer via callbacks.
+class RTCEncodedAudioStreamTransformerDelegate
+ : public webrtc::FrameTransformerInterface {
+ public:
+ RTCEncodedAudioStreamTransformerDelegate(
+ const base::WeakPtr<RTCEncodedAudioStreamTransformer>& transformer,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+ : transformer_(transformer),
+ main_task_runner_(std::move(main_task_runner)) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ }
+
+ // webrtc::FrameTransformerInterface
+ void RegisterTransformedFrameCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>
+ send_frame_to_sink_callback) override {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(
+ &RTCEncodedAudioStreamTransformer::RegisterTransformedFrameCallback,
+ transformer_, std::move(send_frame_to_sink_callback)));
+ }
+
+ void UnregisterTransformedFrameCallback() override {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::
+ UnregisterTransformedFrameCallback,
+ transformer_));
+ }
+
+ void Transform(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame) override {
+ auto audio_frame = base::WrapUnique(
+ static_cast<webrtc::TransformableFrameInterface*>(frame.release()));
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedAudioStreamTransformer::TransformFrame,
+ transformer_, std::move(audio_frame)));
+ }
+
+ private:
+ base::WeakPtr<RTCEncodedAudioStreamTransformer> transformer_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+};
+
+} // namespace
+
+RTCEncodedAudioStreamTransformer::RTCEncodedAudioStreamTransformer(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
+ DCHECK(main_task_runner->BelongsToCurrentThread());
+ delegate_ =
+ new rtc::RefCountedObject<RTCEncodedAudioStreamTransformerDelegate>(
+ weak_factory_.GetWeakPtr(), std::move(main_task_runner));
+}
+
+void RTCEncodedAudioStreamTransformer::RegisterTransformedFrameCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback> callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ send_frame_to_sink_cb_ = callback;
+}
+
+void RTCEncodedAudioStreamTransformer::UnregisterTransformedFrameCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ send_frame_to_sink_cb_ = nullptr;
+}
+
+void RTCEncodedAudioStreamTransformer::TransformFrame(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // If no transformer callback has been set, drop the frame.
+ if (!transformer_callback_)
+ return;
+
+ transformer_callback_.Run(std::move(frame));
+}
+
+void RTCEncodedAudioStreamTransformer::SendFrameToSink(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (send_frame_to_sink_cb_)
+ send_frame_to_sink_cb_->OnTransformedFrame(std::move(frame));
+}
+
+void RTCEncodedAudioStreamTransformer::SetTransformerCallback(
+ TransformerCallback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ transformer_callback_ = std::move(callback);
+}
+
+void RTCEncodedAudioStreamTransformer::ResetTransformerCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ transformer_callback_.Reset();
+}
+
+bool RTCEncodedAudioStreamTransformer::HasTransformerCallback() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return !transformer_callback_.is_null();
+}
+
+bool RTCEncodedAudioStreamTransformer::HasTransformedFrameCallback() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return !!send_frame_to_sink_cb_;
+}
+
+rtc::scoped_refptr<webrtc::FrameTransformerInterface>
+RTCEncodedAudioStreamTransformer::Delegate() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return delegate_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h
new file mode 100644
index 00000000000..f1beece05fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h
@@ -0,0 +1,84 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ENCODED_AUDIO_STREAM_TRANSFORMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ENCODED_AUDIO_STREAM_TRANSFORMER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace webrtc {
+class FrameTransformerInterface;
+class TransformedFrameCallback;
+class TransformableFrameInterface;
+} // namespace webrtc
+
+namespace blink {
+
+class PLATFORM_EXPORT RTCEncodedAudioStreamTransformer {
+ public:
+ using TransformerCallback = base::RepeatingCallback<void(
+ std::unique_ptr<webrtc::TransformableFrameInterface>)>;
+ explicit RTCEncodedAudioStreamTransformer(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+
+ // Called by WebRTC to let us know about a callback object to send transformed
+ // frames to the WebRTC decoder. Runs on an internal WebRTC thread.
+ // The callback can run on any thread.
+ void RegisterTransformedFrameCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>);
+
+ // Called by WebRTC to let us know that any reference to the callback object
+ // reported by RegisterTransformedFrameCallback() should be released since
+ // the callback is no longer useful and is intended for destruction.
+ void UnregisterTransformedFrameCallback();
+
+ // Called by WebRTC to notify of new untransformed frames from the WebRTC
+ // stack. Runs on an internal WebRTC thread.
+ void TransformFrame(std::unique_ptr<webrtc::TransformableFrameInterface>);
+
+ // Send a transformed frame to the WebRTC sink. Must run on the main
+ // thread.
+ void SendFrameToSink(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame);
+
+ // Set a callback to be invoked on every untransformed frame. Must run on the
+ // main thread.
+ void SetTransformerCallback(TransformerCallback);
+
+ // Removes the callback
+ void ResetTransformerCallback();
+
+ // Returns true if a callback has been set with SetTransformerCallback(),
+ // false otherwise. Must run on the main thread.
+ bool HasTransformerCallback() const;
+
+ // Returns true if a webrtc::TransformedFrameCallback is registered.
+ bool HasTransformedFrameCallback() const;
+
+ rtc::scoped_refptr<webrtc::FrameTransformerInterface> Delegate();
+
+ private:
+ THREAD_CHECKER(thread_checker_);
+ rtc::scoped_refptr<webrtc::FrameTransformerInterface> delegate_;
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback> send_frame_to_sink_cb_;
+ TransformerCallback transformer_callback_;
+ base::WeakPtrFactory<RTCEncodedAudioStreamTransformer> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ENCODED_AUDIO_STREAM_TRANSFORMER_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc
new file mode 100644
index 00000000000..bd72fe57397
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer_test.cc
@@ -0,0 +1,105 @@
+// 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 "third_party/blink/renderer/platform/peerconnection/rtc_encoded_audio_stream_transformer.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/webrtc/api/frame_transformer_interface.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+
+namespace blink {
+
+namespace {
+
+class MockWebRtcTransformedFrameCallback
+ : public webrtc::TransformedFrameCallback {
+ public:
+ MOCK_METHOD1(OnTransformedFrame,
+ void(std::unique_ptr<webrtc::TransformableFrameInterface>));
+};
+
+class MockTransformerCallbackHolder {
+ public:
+ MOCK_METHOD1(OnEncodedFrame,
+ void(std::unique_ptr<webrtc::TransformableFrameInterface>));
+};
+
+} // namespace
+
+class RTCEncodedAudioStreamTransformerTest : public ::testing::Test {
+ public:
+ RTCEncodedAudioStreamTransformerTest()
+ : main_task_runner_(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
+ webrtc_task_runner_(base::ThreadPool::CreateSingleThreadTaskRunner({})),
+ webrtc_callback_(
+ new rtc::RefCountedObject<MockWebRtcTransformedFrameCallback>()),
+ encoded_audio_stream_transformer_(main_task_runner_) {}
+
+ void SetUp() override {
+ EXPECT_FALSE(
+ encoded_audio_stream_transformer_.HasTransformedFrameCallback());
+ encoded_audio_stream_transformer_.RegisterTransformedFrameCallback(
+ webrtc_callback_);
+ EXPECT_TRUE(
+ encoded_audio_stream_transformer_.HasTransformedFrameCallback());
+ }
+
+ void TearDown() override {
+ encoded_audio_stream_transformer_.UnregisterTransformedFrameCallback();
+ EXPECT_FALSE(
+ encoded_audio_stream_transformer_.HasTransformedFrameCallback());
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> webrtc_task_runner_;
+ rtc::scoped_refptr<MockWebRtcTransformedFrameCallback> webrtc_callback_;
+ MockTransformerCallbackHolder mock_transformer_callback_holder_;
+ RTCEncodedAudioStreamTransformer encoded_audio_stream_transformer_;
+};
+
+TEST_F(RTCEncodedAudioStreamTransformerTest,
+ TransformerForwardsFrameToTransformerCallback) {
+ EXPECT_FALSE(encoded_audio_stream_transformer_.HasTransformerCallback());
+ encoded_audio_stream_transformer_.SetTransformerCallback(
+ WTF::BindRepeating(&MockTransformerCallbackHolder::OnEncodedFrame,
+ WTF::Unretained(&mock_transformer_callback_holder_)));
+ EXPECT_TRUE(encoded_audio_stream_transformer_.HasTransformerCallback());
+
+ EXPECT_CALL(mock_transformer_callback_holder_, OnEncodedFrame);
+ // Frames are pushed to the RTCEncodedAudioStreamTransformer via its delegate,
+ // which would normally be registered with a WebRTC sender or receiver.
+ // In this test, manually send the frame to the transformer on the simulated
+ // WebRTC thread.
+ PostCrossThreadTask(
+ *webrtc_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&webrtc::FrameTransformerInterface::Transform,
+ encoded_audio_stream_transformer_.Delegate(),
+ nullptr));
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(RTCEncodedAudioStreamTransformerTest, TransformerForwardsFrameToWebRTC) {
+ EXPECT_CALL(*webrtc_callback_, OnTransformedFrame);
+ encoded_audio_stream_transformer_.SendFrameToSink(nullptr);
+ task_environment_.RunUntilIdle();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.cc
new file mode 100644
index 00000000000..ba9c8507154
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.cc
@@ -0,0 +1,191 @@
+// 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 "third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/webrtc/api/frame_transformer_interface.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+
+namespace blink {
+
+namespace {
+
+// This delegate class exists to work around the fact that
+// RTCEncodedVideoStreamTransformer cannot derive from rtc::RefCountedObject
+// and post tasks referencing itself as an rtc::scoped_refptr. Instead,
+// RTCEncodedVideoStreamTransformer creates a delegate using
+// rtc::RefCountedObject and posts tasks referencing the delegate, which invokes
+// the RTCEncodedVideoStreamTransformer via callbacks.
+class RTCEncodedVideoStreamTransformerDelegate
+ : public webrtc::FrameTransformerInterface {
+ public:
+ RTCEncodedVideoStreamTransformerDelegate(
+ const base::WeakPtr<RTCEncodedVideoStreamTransformer>& transformer,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+ : transformer_(transformer),
+ main_task_runner_(std::move(main_task_runner)) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ }
+
+ // webrtc::FrameTransformerInterface
+ // TODO(crbug.com/1065838): Remove the non-ssrc version of the registration
+ // and unregistration methods once WebRTC uses the ssrc version in all cases.
+ void RegisterTransformedFrameCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>
+ send_frame_to_sink_callback) override {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedVideoStreamTransformer::
+ RegisterTransformedFrameSinkCallback,
+ transformer_,
+ std::move(send_frame_to_sink_callback), 0));
+ }
+
+ void UnregisterTransformedFrameCallback() override {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedVideoStreamTransformer::
+ UnregisterTransformedFrameSinkCallback,
+ transformer_, 0));
+ }
+
+ void RegisterTransformedFrameSinkCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>
+ send_frame_to_sink_callback,
+ uint32_t ssrc) override {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedVideoStreamTransformer::
+ RegisterTransformedFrameSinkCallback,
+ transformer_,
+ std::move(send_frame_to_sink_callback), ssrc));
+ }
+
+ void UnregisterTransformedFrameSinkCallback(uint32_t ssrc) override {
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedVideoStreamTransformer::
+ UnregisterTransformedFrameSinkCallback,
+ transformer_, ssrc));
+ }
+
+ void Transform(
+ std::unique_ptr<webrtc::TransformableFrameInterface> frame) override {
+ auto video_frame =
+ base::WrapUnique(static_cast<webrtc::TransformableVideoFrameInterface*>(
+ frame.release()));
+ PostCrossThreadTask(
+ *main_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&RTCEncodedVideoStreamTransformer::TransformFrame,
+ transformer_, std::move(video_frame)));
+ }
+
+ private:
+ base::WeakPtr<RTCEncodedVideoStreamTransformer> transformer_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+};
+
+} // namespace
+
+RTCEncodedVideoStreamTransformer::RTCEncodedVideoStreamTransformer(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
+ DCHECK(main_task_runner->BelongsToCurrentThread());
+ delegate_ =
+ new rtc::RefCountedObject<RTCEncodedVideoStreamTransformerDelegate>(
+ weak_factory_.GetWeakPtr(), std::move(main_task_runner));
+}
+
+void RTCEncodedVideoStreamTransformer::RegisterTransformedFrameSinkCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback> callback,
+ uint32_t ssrc) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ for (auto& sink_callback : send_frame_to_sink_callbacks_) {
+ if (sink_callback.first == ssrc) {
+ sink_callback.second = std::move(callback);
+ return;
+ }
+ }
+ send_frame_to_sink_callbacks_.push_back(std::make_pair(ssrc, callback));
+}
+
+void RTCEncodedVideoStreamTransformer::UnregisterTransformedFrameSinkCallback(
+ uint32_t ssrc) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ for (wtf_size_t i = 0; i < send_frame_to_sink_callbacks_.size(); ++i) {
+ if (send_frame_to_sink_callbacks_[i].first == ssrc) {
+ send_frame_to_sink_callbacks_.EraseAt(i);
+ return;
+ }
+ }
+}
+
+void RTCEncodedVideoStreamTransformer::TransformFrame(
+ std::unique_ptr<webrtc::TransformableVideoFrameInterface> frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // If no transformer callback has been set, drop the frame.
+ if (!transformer_callback_)
+ return;
+
+ transformer_callback_.Run(std::move(frame));
+}
+
+void RTCEncodedVideoStreamTransformer::SendFrameToSink(
+ std::unique_ptr<webrtc::TransformableVideoFrameInterface> frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // TODO(crbug.com/1069275): Remove this section once WebRTC reports ssrc in
+ // all sink callback registrations.
+ if (send_frame_to_sink_callbacks_.size() == 1 &&
+ send_frame_to_sink_callbacks_[0].first == 0) {
+ send_frame_to_sink_callbacks_[0].second->OnTransformedFrame(
+ std::move(frame));
+ return;
+ }
+ for (const auto& sink_callback : send_frame_to_sink_callbacks_) {
+ if (sink_callback.first == frame->GetSsrc()) {
+ sink_callback.second->OnTransformedFrame(std::move(frame));
+ return;
+ }
+ }
+}
+
+void RTCEncodedVideoStreamTransformer::SetTransformerCallback(
+ TransformerCallback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ transformer_callback_ = std::move(callback);
+}
+
+void RTCEncodedVideoStreamTransformer::ResetTransformerCallback() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ transformer_callback_.Reset();
+}
+
+bool RTCEncodedVideoStreamTransformer::HasTransformerCallback() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return !transformer_callback_.is_null();
+}
+
+bool RTCEncodedVideoStreamTransformer::HasTransformedFrameSinkCallback(
+ uint32_t ssrc) const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ for (const auto& sink_callbacks : send_frame_to_sink_callbacks_) {
+ if (sink_callbacks.first == ssrc)
+ return true;
+ }
+ return false;
+}
+
+rtc::scoped_refptr<webrtc::FrameTransformerInterface>
+RTCEncodedVideoStreamTransformer::Delegate() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return delegate_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h
new file mode 100644
index 00000000000..6da970263a4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h
@@ -0,0 +1,93 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ENCODED_VIDEO_STREAM_TRANSFORMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ENCODED_VIDEO_STREAM_TRANSFORMER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace webrtc {
+class FrameTransformerInterface;
+class TransformedFrameCallback;
+class TransformableVideoFrameInterface;
+} // namespace webrtc
+
+namespace blink {
+
+class PLATFORM_EXPORT RTCEncodedVideoStreamTransformer {
+ public:
+ using TransformerCallback = base::RepeatingCallback<void(
+ std::unique_ptr<webrtc::TransformableVideoFrameInterface>)>;
+ explicit RTCEncodedVideoStreamTransformer(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+
+ // Called by WebRTC to let us know about a callback object to send transformed
+ // frames to the WebRTC decoder. Runs on an internal WebRTC thread.
+ // The callback can run on any thread.
+ void RegisterTransformedFrameSinkCallback(
+ rtc::scoped_refptr<webrtc::TransformedFrameCallback>,
+ uint32_t ssrc);
+
+ // Called by WebRTC to let us know that any reference to the callback object
+ // reported by RegisterTransformedFrameCallback() should be released since
+ // the callback is no longer useful and is intended for destruction.
+ // TODO(crbug.com/1065838): Remove the non-ssrc version once WebRTC uses the
+ // ssrc version in all cases.
+ // void UnregisterTransformedFrameCallback();
+ void UnregisterTransformedFrameSinkCallback(uint32_t ssrc);
+
+ // Called by WebRTC to notify of new untransformed frames from the WebRTC
+ // stack. Runs on an internal WebRTC thread.
+ void TransformFrame(
+ std::unique_ptr<webrtc::TransformableVideoFrameInterface>);
+
+ // Send a transformed frame to the WebRTC sink. Must run on the main
+ // thread.
+ void SendFrameToSink(
+ std::unique_ptr<webrtc::TransformableVideoFrameInterface> frame);
+
+ // Set a callback to be invoked on every untransformed frame. Must run on the
+ // main thread.
+ void SetTransformerCallback(TransformerCallback);
+
+ // Removes the callback
+ void ResetTransformerCallback();
+
+ // Returns true if a callback has been set with SetTransformerCallback(),
+ // false otherwise. Must run on the main thread.
+ bool HasTransformerCallback() const;
+
+ // Returns true if a webrtc::TransformedFrameCallback is registered for
+ // the given ssrc.
+ bool HasTransformedFrameSinkCallback(uint32_t ssrc) const;
+
+ rtc::scoped_refptr<webrtc::FrameTransformerInterface> Delegate();
+
+ private:
+ THREAD_CHECKER(thread_checker_);
+ rtc::scoped_refptr<webrtc::FrameTransformerInterface> delegate_;
+ Vector<
+ std::pair<uint32_t, rtc::scoped_refptr<webrtc::TransformedFrameCallback>>>
+ send_frame_to_sink_callbacks_;
+ TransformerCallback transformer_callback_;
+ base::WeakPtrFactory<RTCEncodedVideoStreamTransformer> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ENCODED_VIDEO_STREAM_TRANSFORMER_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer_test.cc
new file mode 100644
index 00000000000..01f1af1a521
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer_test.cc
@@ -0,0 +1,140 @@
+// 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 "third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/webrtc/api/frame_transformer_interface.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+
+namespace blink {
+
+namespace {
+
+const uint32_t kSSRC = 1;
+const uint32_t kNonexistentSSRC = 0;
+
+class MockWebRtcTransformedFrameCallback
+ : public webrtc::TransformedFrameCallback {
+ public:
+ MOCK_METHOD1(OnTransformedFrame,
+ void(std::unique_ptr<webrtc::TransformableFrameInterface>));
+};
+
+class MockTransformerCallbackHolder {
+ public:
+ MOCK_METHOD1(OnEncodedFrame,
+ void(std::unique_ptr<webrtc::TransformableVideoFrameInterface>));
+};
+
+class FakeVideoFrame : public webrtc::TransformableVideoFrameInterface {
+ public:
+ explicit FakeVideoFrame(uint32_t ssrc) : ssrc_(ssrc) {}
+
+ rtc::ArrayView<const uint8_t> GetData() const override {
+ return rtc::ArrayView<const uint8_t>();
+ }
+
+ // Copies |data| into the owned frame payload data.
+ void SetData(rtc::ArrayView<const uint8_t> data) override {}
+ uint32_t GetTimestamp() const override { return 0; }
+ uint32_t GetSsrc() const override { return ssrc_; }
+ bool IsKeyFrame() const override { return true; }
+ std::vector<uint8_t> GetAdditionalData() const override {
+ return std::vector<uint8_t>();
+ }
+
+ private:
+ uint32_t ssrc_;
+};
+
+std::unique_ptr<webrtc::TransformableVideoFrameInterface> CreateFakeFrame() {
+ return std::make_unique<FakeVideoFrame>(kSSRC);
+}
+
+} // namespace
+
+class RTCEncodedVideoStreamTransformerTest : public ::testing::Test {
+ public:
+ RTCEncodedVideoStreamTransformerTest()
+ : main_task_runner_(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
+ webrtc_task_runner_(base::ThreadPool::CreateSingleThreadTaskRunner({})),
+ webrtc_callback_(
+ new rtc::RefCountedObject<MockWebRtcTransformedFrameCallback>()),
+ encoded_video_stream_transformer_(main_task_runner_) {}
+
+ void SetUp() override {
+ EXPECT_FALSE(
+ encoded_video_stream_transformer_.HasTransformedFrameSinkCallback(
+ kSSRC));
+ encoded_video_stream_transformer_.RegisterTransformedFrameSinkCallback(
+ webrtc_callback_, kSSRC);
+ EXPECT_TRUE(
+ encoded_video_stream_transformer_.HasTransformedFrameSinkCallback(
+ kSSRC));
+ EXPECT_FALSE(
+ encoded_video_stream_transformer_.HasTransformedFrameSinkCallback(
+ kNonexistentSSRC));
+ }
+
+ void TearDown() override {
+ encoded_video_stream_transformer_.UnregisterTransformedFrameSinkCallback(
+ kSSRC);
+ EXPECT_FALSE(
+ encoded_video_stream_transformer_.HasTransformedFrameSinkCallback(
+ kSSRC));
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> webrtc_task_runner_;
+ rtc::scoped_refptr<MockWebRtcTransformedFrameCallback> webrtc_callback_;
+ MockTransformerCallbackHolder mock_transformer_callback_holder_;
+ RTCEncodedVideoStreamTransformer encoded_video_stream_transformer_;
+};
+
+TEST_F(RTCEncodedVideoStreamTransformerTest,
+ TransformerForwardsFrameToTransformerCallback) {
+ EXPECT_FALSE(encoded_video_stream_transformer_.HasTransformerCallback());
+ encoded_video_stream_transformer_.SetTransformerCallback(
+ WTF::BindRepeating(&MockTransformerCallbackHolder::OnEncodedFrame,
+ WTF::Unretained(&mock_transformer_callback_holder_)));
+ EXPECT_TRUE(encoded_video_stream_transformer_.HasTransformerCallback());
+
+ EXPECT_CALL(mock_transformer_callback_holder_, OnEncodedFrame);
+ // Frames are pushed to the RTCEncodedVideoStreamTransformer via its delegate,
+ // which would normally be registered with a WebRTC sender or receiver.
+ // In this test, manually send the frame to the transformer on the simulated
+ // WebRTC thread.
+ PostCrossThreadTask(
+ *webrtc_task_runner_, FROM_HERE,
+ CrossThreadBindOnce(&webrtc::FrameTransformerInterface::Transform,
+ encoded_video_stream_transformer_.Delegate(),
+ CreateFakeFrame()));
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(RTCEncodedVideoStreamTransformerTest, TransformerForwardsFrameToWebRTC) {
+ EXPECT_CALL(*webrtc_callback_, OnTransformedFrame);
+ encoded_video_stream_transformer_.SendFrameToSink(CreateFakeFrame());
+ task_environment_.RunUntilIdle();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink.h
index be9e3f265a3..8e60db6aae9 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink.h
@@ -5,15 +5,16 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_EVENT_LOG_OUTPUT_SINK_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_EVENT_LOG_OUTPUT_SINK_H_
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
-class PLATFORM_EXPORT RtcEventLogOutputSink {
+class PLATFORM_EXPORT RtcEventLogOutputSink : public GarbageCollectedMixin {
public:
virtual ~RtcEventLogOutputSink() = default;
- virtual void OnWebRtcEventLogWrite(const std::string& output) = 0;
+ virtual void OnWebRtcEventLogWrite(const WTF::Vector<uint8_t>& output) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.cc
index 4a8649ad39c..f4c9b54ff52 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.cc
@@ -22,7 +22,10 @@ bool RtcEventLogOutputSinkProxy::IsActive() const {
}
bool RtcEventLogOutputSinkProxy::Write(const std::string& output) {
- sink_->OnWebRtcEventLogWrite(output);
+ WTF::Vector<uint8_t> converted_output;
+ converted_output.AppendRange(output.begin(), output.end());
+
+ sink_->OnWebRtcEventLogWrite(converted_output);
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.h
index 8ecdf912ee2..40b38869bf7 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_event_log_output_sink_proxy.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/rtc_event_log_output.h"
@@ -29,7 +30,7 @@ class PLATFORM_EXPORT RtcEventLogOutputSinkProxy final
bool Write(const std::string& output) override;
private:
- RtcEventLogOutputSink* const sink_;
+ CrossThreadWeakPersistent<RtcEventLogOutputSink> sink_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.cc
index 74d1d404a04..e9cbb3e94c5 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/webrtc/api/candidate.h"
#include "third_party/webrtc/p2p/base/p2p_constants.h"
#include "third_party/webrtc/p2p/base/port.h"
@@ -39,27 +40,6 @@ String CandidateTypeToString(const std::string& type) {
} // namespace
-// static
-scoped_refptr<RTCIceCandidatePlatform> RTCIceCandidatePlatform::Create(
- String candidate,
- String sdp_mid,
- base::Optional<uint16_t> sdp_m_line_index,
- String username_fragment) {
- return base::AdoptRef(new RTCIceCandidatePlatform(
- std::move(candidate), std::move(sdp_mid), std::move(sdp_m_line_index),
- std::move(username_fragment)));
-}
-
-scoped_refptr<RTCIceCandidatePlatform> RTCIceCandidatePlatform::Create(
- String candidate,
- String sdp_mid,
- int sdp_m_line_index) {
- return base::AdoptRef(new RTCIceCandidatePlatform(
- std::move(candidate), std::move(sdp_mid),
- sdp_m_line_index < 0 ? base::Optional<uint16_t>()
- : base::Optional<uint16_t>(sdp_m_line_index)));
-}
-
RTCIceCandidatePlatform::RTCIceCandidatePlatform(
String candidate,
String sdp_mid,
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h
index 6baacd5ae97..2751f57f056 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h
@@ -32,29 +32,29 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ICE_CANDIDATE_PLATFORM_H_
#include "base/optional.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
namespace blink {
class PLATFORM_EXPORT RTCIceCandidatePlatform final
- : public WTF::ThreadSafeRefCounted<RTCIceCandidatePlatform> {
+ : public GarbageCollected<RTCIceCandidatePlatform> {
public:
// Creates a new RTCIceCandidatePlatform using |candidate|, |sdp_mid| and
// |sdp_m_line_index|. If |sdp_m_line_index| is negative, it is
// considered as having no value.
- static scoped_refptr<RTCIceCandidatePlatform> Create(String candidate,
- String sdp_mid,
- int sdp_m_line_index);
+ RTCIceCandidatePlatform(String candidate,
+ String sdp_mid,
+ base::Optional<uint16_t> sdp_m_line_index);
// Creates a new RTCIceCandidatePlatform using |candidate|, |sdp_mid|,
// |sdp_m_line_index|, and |username_fragment|.
- static scoped_refptr<RTCIceCandidatePlatform> Create(
- String candidate,
- String sdp_mid,
- base::Optional<uint16_t> sdp_m_line_index,
- String username_fragment);
+ RTCIceCandidatePlatform(String candidate,
+ String sdp_mid,
+ base::Optional<uint16_t> sdp_m_line_index,
+ String username_fragment);
+ ~RTCIceCandidatePlatform() = default;
const String& Candidate() const { return candidate_; }
const String& SdpMid() const { return sdp_mid_; }
@@ -73,22 +73,11 @@ class PLATFORM_EXPORT RTCIceCandidatePlatform final
const base::Optional<uint16_t>& RelatedPort() const { return related_port_; }
const String& UsernameFragment() const { return username_fragment_; }
- private:
- friend class WTF::ThreadSafeRefCounted<RTCIceCandidatePlatform>;
-
- RTCIceCandidatePlatform(String candidate,
- String sdp_mid,
- base::Optional<uint16_t> sdp_m_line_index);
-
- RTCIceCandidatePlatform(String candidate,
- String sdp_mid,
- base::Optional<uint16_t> sdp_m_line_index,
- String username_fragment);
+ void Trace(Visitor*) {}
+ private:
void PopulateFields(bool use_username_from_candidate);
- ~RTCIceCandidatePlatform() = default;
-
String candidate_;
String sdp_mid_;
base::Optional<uint16_t> sdp_m_line_index_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h
index a986b96c3c0..9e8e23a538a 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h
@@ -26,7 +26,7 @@ class RTCOfferOptionsPlatform final
bool VoiceActivityDetection() const { return voice_activity_detection_; }
bool IceRestart() const { return ice_restart_; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
int32_t offer_to_receive_video_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.cc
new file mode 100644
index 00000000000..2b1e5693839
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.cc
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h"
+
+namespace blink {
+
+RTCPeerConnectionHandlerClient::~RTCPeerConnectionHandlerClient() = default;
+
+void RTCPeerConnectionHandlerClient::ClosePeerConnection() {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
new file mode 100644
index 00000000000..f7f61d75818
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_PEER_CONNECTION_HANDLER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_PEER_CONNECTION_HANDLER_CLIENT_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/sctp_transport_interface.h"
+
+namespace blink {
+
+class RTCIceCandidatePlatform;
+class RTCRtpTransceiverPlatform;
+class RTCRtpReceiverPlatform;
+
+struct PLATFORM_EXPORT WebRTCSctpTransportSnapshot {
+ rtc::scoped_refptr<webrtc::SctpTransportInterface> transport;
+ webrtc::SctpTransportInformation sctp_transport_state =
+ webrtc::SctpTransportInformation(webrtc::SctpTransportState::kNew);
+ webrtc::DtlsTransportInformation dtls_transport_state =
+ webrtc::DtlsTransportInformation(webrtc::DtlsTransportState::kNew);
+};
+
+class PLATFORM_EXPORT RTCPeerConnectionHandlerClient {
+ public:
+ virtual ~RTCPeerConnectionHandlerClient();
+
+ virtual void NegotiationNeeded() = 0;
+ virtual void DidGenerateICECandidate(RTCIceCandidatePlatform*) = 0;
+ virtual void DidFailICECandidate(const String& address,
+ base::Optional<uint16_t> port,
+ const String& host_candidate,
+ const String& url,
+ int error_code,
+ const String& error_text) = 0;
+ virtual void DidChangeSignalingState(
+ webrtc::PeerConnectionInterface::SignalingState) = 0;
+ virtual void DidChangeIceGatheringState(
+ webrtc::PeerConnectionInterface::IceGatheringState) = 0;
+ virtual void DidChangeIceConnectionState(
+ webrtc::PeerConnectionInterface::IceConnectionState) = 0;
+ virtual void DidChangePeerConnectionState(
+ webrtc::PeerConnectionInterface::PeerConnectionState) {}
+ virtual void DidAddReceiverPlanB(std::unique_ptr<RTCRtpReceiverPlatform>) = 0;
+ virtual void DidRemoveReceiverPlanB(
+ std::unique_ptr<RTCRtpReceiverPlatform>) = 0;
+ virtual void DidModifyTransceivers(
+ Vector<std::unique_ptr<RTCRtpTransceiverPlatform>>,
+ Vector<uintptr_t>,
+ bool is_remote_description) = 0;
+ virtual void DidModifySctpTransport(WebRTCSctpTransportSnapshot) = 0;
+ virtual void DidAddRemoteDataChannel(
+ scoped_refptr<webrtc::DataChannelInterface>) = 0;
+ virtual void DidNoteInterestingUsage(int usage_pattern) = 0;
+ virtual void UnregisterPeerConnectionHandler() = 0;
+ virtual void ClosePeerConnection();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_PEER_CONNECTION_HANDLER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h
new file mode 100644
index 00000000000..870ea35c526
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_PEER_CONNECTION_HANDLER_PLATFORM_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_PEER_CONNECTION_HANDLER_PLATFORM_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/rtc_error.h"
+#include "third_party/webrtc/api/rtp_transceiver_interface.h"
+#include "third_party/webrtc/api/stats/rtc_stats.h"
+
+namespace webrtc {
+enum class RTCErrorType;
+struct DataChannelInit;
+} // namespace webrtc
+
+namespace blink {
+
+class MediaConstraints;
+class RTCAnswerOptionsPlatform;
+class RTCIceCandidatePlatform;
+class RTCOfferOptionsPlatform;
+class RTCRtpSenderPlatform;
+class RTCRtpTransceiverPlatform;
+class RTCSessionDescriptionPlatform;
+class RTCSessionDescriptionRequest;
+class RTCStatsRequest;
+class RTCVoidRequest;
+class WebLocalFrame;
+class WebMediaStream;
+class WebMediaStreamTrack;
+
+class PLATFORM_EXPORT RTCPeerConnectionHandlerPlatform {
+ public:
+ enum class IceConnectionStateVersion {
+ // Only applicable in Unified Plan when the JavaScript-exposed
+ // iceConnectionState is calculated in blink. In this case, kLegacy is used
+ // to report the webrtc::PeerConnectionInterface implementation which is not
+ // visible in JavaScript, but still useful to track for debugging purposes.
+ kLegacy,
+ // The JavaScript-visible iceConnectionState. In Plan B, this is the same as
+ // the webrtc::PeerConnectionInterface implementation.
+ kDefault,
+ };
+
+ virtual ~RTCPeerConnectionHandlerPlatform() = default;
+
+ virtual bool Initialize(
+ const webrtc::PeerConnectionInterface::RTCConfiguration&,
+ const MediaConstraints&,
+ WebLocalFrame*) = 0;
+
+ virtual void Stop() = 0;
+ // This function should be called when the object is taken out of service.
+ // There might be functions that need to return through the object, so it
+ // cannot be deleted yet, but no new operations should be allowed.
+ // All references to the object except the owning reference are deleted
+ // by this function.
+ virtual void StopAndUnregister() = 0;
+
+ // Unified Plan: The list of transceivers after the createOffer() call.
+ // Because of offerToReceive[Audio/Video] it is possible for createOffer() to
+ // create new transceivers or update the direction of existing transceivers.
+ // https://w3c.github.io/webrtc-pc/#legacy-configuration-extensions
+ // Plan B: Returns an empty list.
+ virtual Vector<std::unique_ptr<RTCRtpTransceiverPlatform>> CreateOffer(
+ RTCSessionDescriptionRequest*,
+ const MediaConstraints&) = 0;
+ virtual Vector<std::unique_ptr<RTCRtpTransceiverPlatform>> CreateOffer(
+ RTCSessionDescriptionRequest*,
+ RTCOfferOptionsPlatform*) = 0;
+ virtual void CreateAnswer(RTCSessionDescriptionRequest*,
+ const MediaConstraints&) = 0;
+ virtual void CreateAnswer(RTCSessionDescriptionRequest*,
+ RTCAnswerOptionsPlatform*) = 0;
+ virtual void SetLocalDescription(RTCVoidRequest*) = 0;
+ virtual void SetLocalDescription(RTCVoidRequest*,
+ RTCSessionDescriptionPlatform*) = 0;
+ virtual void SetRemoteDescription(RTCVoidRequest*,
+ RTCSessionDescriptionPlatform*) = 0;
+ virtual RTCSessionDescriptionPlatform* LocalDescription() = 0;
+ virtual RTCSessionDescriptionPlatform* RemoteDescription() = 0;
+ virtual RTCSessionDescriptionPlatform* CurrentLocalDescription() = 0;
+ virtual RTCSessionDescriptionPlatform* CurrentRemoteDescription() = 0;
+ virtual RTCSessionDescriptionPlatform* PendingLocalDescription() = 0;
+ virtual RTCSessionDescriptionPlatform* PendingRemoteDescription() = 0;
+ virtual const webrtc::PeerConnectionInterface::RTCConfiguration&
+ GetConfiguration() const = 0;
+ virtual webrtc::RTCErrorType SetConfiguration(
+ const webrtc::PeerConnectionInterface::RTCConfiguration&) = 0;
+
+ virtual void AddICECandidate(RTCVoidRequest*, RTCIceCandidatePlatform*) = 0;
+ virtual void RestartIce() = 0;
+ virtual void GetStats(RTCStatsRequest*) = 0;
+ // Gets stats using the new stats collection API, see
+ // third_party/webrtc/api/stats/. These will replace the old stats collection
+ // API when the new API has matured enough.
+ virtual void GetStats(RTCStatsReportCallback,
+ const Vector<webrtc::NonStandardGroupId>&) = 0;
+ virtual scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
+ const String& label,
+ const webrtc::DataChannelInit&) = 0;
+ virtual webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>>
+ AddTransceiverWithTrack(const WebMediaStreamTrack&,
+ const webrtc::RtpTransceiverInit&) = 0;
+ virtual webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>>
+ AddTransceiverWithKind(
+ // webrtc::MediaStreamTrackInterface::kAudioKind or kVideoKind
+ const String& kind,
+ const webrtc::RtpTransceiverInit&) = 0;
+ // Adds the track to the peer connection, returning the resulting transceiver
+ // or error.
+ virtual webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>>
+ AddTrack(const WebMediaStreamTrack&, const Vector<WebMediaStream>&) = 0;
+ // Removes the sender.
+ // In Plan B: Returns OK() with value nullptr on success. The sender's track
+ // must be nulled by the caller.
+ // In Unified Plan: Returns OK() with the updated transceiver state.
+ virtual webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>>
+ RemoveTrack(RTCRtpSenderPlatform*) = 0;
+
+ // Returns a pointer to the underlying native PeerConnection object.
+ virtual webrtc::PeerConnectionInterface* NativePeerConnection() = 0;
+
+ virtual void RunSynchronousOnceClosureOnSignalingThread(
+ CrossThreadOnceClosure closure,
+ const char* trace_event_name) = 0;
+ virtual void RunSynchronousRepeatingClosureOnSignalingThread(
+ const base::RepeatingClosure& closure,
+ const char* trace_event_name) = 0;
+
+ // Inform chrome://webrtc-internals/ that the iceConnectionState has changed.
+ virtual void TrackIceConnectionStateChange(
+ IceConnectionStateVersion version,
+ webrtc::PeerConnectionInterface::IceConnectionState state) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_PEER_CONNECTION_HANDLER_PLATFORM_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h
index ad18bf33776..882a6893b69 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h
@@ -8,16 +8,18 @@
#include <memory>
#include "base/optional.h"
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_rtc_stats.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/webrtc/api/dtls_transport_interface.h"
#include "third_party/webrtc/api/rtp_parameters.h"
#include "third_party/webrtc/api/stats/rtc_stats.h"
namespace blink {
+class RTCEncodedAudioStreamTransformer;
+class RTCEncodedVideoStreamTransformer;
class RTCRtpSource;
class WebMediaStreamTrack;
@@ -25,7 +27,7 @@ class WebMediaStreamTrack;
// receiver alive through reference counting. Multiple |RTCRtpReceiverPlatform|s
// could reference the same receiver, see |id|.
// https://w3c.github.io/webrtc-pc/#rtcrtpreceiver-interface
-class BLINK_PLATFORM_EXPORT RTCRtpReceiverPlatform {
+class PLATFORM_EXPORT RTCRtpReceiverPlatform {
public:
virtual ~RTCRtpReceiverPlatform();
@@ -39,13 +41,21 @@ class BLINK_PLATFORM_EXPORT RTCRtpReceiverPlatform {
// The information is only interesting if DtlsTransport() is non-null.
virtual webrtc::DtlsTransportInformation DtlsTransportInformation() = 0;
virtual const WebMediaStreamTrack& Track() const = 0;
- virtual WebVector<WebString> StreamIds() const = 0;
- virtual WebVector<std::unique_ptr<RTCRtpSource>> GetSources() = 0;
- virtual void GetStats(blink::WebRTCStatsReportCallback,
- const WebVector<webrtc::NonStandardGroupId>&) = 0;
+ virtual Vector<String> StreamIds() const = 0;
+ virtual Vector<std::unique_ptr<RTCRtpSource>> GetSources() = 0;
+ virtual void GetStats(RTCStatsReportCallback,
+ const Vector<webrtc::NonStandardGroupId>&) = 0;
virtual std::unique_ptr<webrtc::RtpParameters> GetParameters() const = 0;
virtual void SetJitterBufferMinimumDelay(
base::Optional<double> delay_seconds) = 0;
+ virtual RTCEncodedAudioStreamTransformer* GetEncodedAudioStreamTransformer()
+ const {
+ return nullptr;
+ }
+ virtual RTCEncodedVideoStreamTransformer* GetEncodedVideoStreamTransformer()
+ const {
+ return nullptr;
+ }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h
index e2db21cc70f..b39bca799ea 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h
@@ -7,18 +7,21 @@
#include <memory>
-#include "third_party/blink/public/platform/web_rtc_stats.h"
-#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/webrtc/api/dtls_transport_interface.h"
#include "third_party/webrtc/api/rtp_parameters.h"
#include "third_party/webrtc/api/stats/rtc_stats.h"
namespace blink {
+class RtcDtmfSenderHandler;
+class RTCEncodedAudioStreamTransformer;
+class RTCEncodedVideoStreamTransformer;
class RTCVoidRequest;
class WebMediaStreamTrack;
-class RtcDtmfSenderHandler;
// Implementations of this interface keep the corresponding WebRTC-layer sender
// alive through reference counting. Multiple |RTCRtpSenderPlatform|s could
@@ -39,19 +42,27 @@ class PLATFORM_EXPORT RTCRtpSenderPlatform {
// The information is only interesting if DtlsTransport() is non-null.
virtual webrtc::DtlsTransportInformation DtlsTransportInformation() = 0;
virtual WebMediaStreamTrack Track() const = 0;
- virtual WebVector<WebString> StreamIds() const = 0;
+ virtual Vector<String> StreamIds() const = 0;
// TODO(hbos): Replace RTCVoidRequest by something resolving promises based
// on RTCError, as to surface both exception type and error message.
// https://crbug.com/790007
virtual void ReplaceTrack(WebMediaStreamTrack, RTCVoidRequest*) = 0;
virtual std::unique_ptr<RtcDtmfSenderHandler> GetDtmfSender() const = 0;
virtual std::unique_ptr<webrtc::RtpParameters> GetParameters() const = 0;
- virtual void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters>,
- webrtc::DegradationPreference,
+ virtual void SetParameters(Vector<webrtc::RtpEncodingParameters>,
+ absl::optional<webrtc::DegradationPreference>,
RTCVoidRequest*) = 0;
- virtual void GetStats(blink::WebRTCStatsReportCallback,
- const WebVector<webrtc::NonStandardGroupId>&) = 0;
- virtual void SetStreams(const WebVector<WebString>& stream_ids) = 0;
+ virtual void GetStats(RTCStatsReportCallback,
+ const Vector<webrtc::NonStandardGroupId>&) = 0;
+ virtual void SetStreams(const Vector<String>& stream_ids) = 0;
+ virtual RTCEncodedAudioStreamTransformer* GetEncodedAudioStreamTransformer()
+ const {
+ return nullptr;
+ }
+ virtual RTCEncodedVideoStreamTransformer* GetEncodedVideoStreamTransformer()
+ const {
+ return nullptr;
+ }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc
index be6a3c88bf9..704a4e90670 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/time/time.h"
#include "third_party/webrtc/api/scoped_refptr.h"
+#include "third_party/webrtc/system_wrappers/include/ntp_time.h"
namespace blink {
@@ -54,4 +55,11 @@ uint32_t RTCRtpSource::RtpTimestamp() const {
return source_.rtp_timestamp();
}
+base::Optional<int64_t> RTCRtpSource::CaptureTimestamp() const {
+ if (!source_.absolute_capture_time())
+ return base::nullopt;
+ return webrtc::UQ32x32ToInt64Ms(
+ source_.absolute_capture_time()->absolute_capture_timestamp);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h
index a36dd370c77..551ac0b3779 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_source.h
@@ -35,6 +35,7 @@ class PLATFORM_EXPORT RTCRtpSource {
uint32_t Source() const;
base::Optional<double> AudioLevel() const;
uint32_t RtpTimestamp() const;
+ base::Optional<int64_t> CaptureTimestamp() const;
private:
const webrtc::RtpSource source_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h
index 91e1c1a8b85..1ba93246f10 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h
@@ -8,9 +8,10 @@
#include <memory>
#include "base/optional.h"
-#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/webrtc/api/rtp_transceiver_interface.h"
namespace blink {
@@ -51,8 +52,8 @@ class PLATFORM_EXPORT RTCRtpTransceiverPlatform {
// Identifies the webrtc-layer transceiver. Multiple RTCRtpTransceiverPlatform
// can exist for the same webrtc-layer transceiver.
virtual uintptr_t Id() const = 0;
- virtual WebString Mid() const = 0;
- virtual void SetMid(base::Optional<WebString>) {}
+ virtual String Mid() const = 0;
+ virtual void SetMid(base::Optional<String>) {}
virtual std::unique_ptr<RTCRtpSenderPlatform> Sender() const = 0;
virtual std::unique_ptr<RTCRtpReceiverPlatform> Receiver() const = 0;
virtual bool Stopped() const = 0;
@@ -63,7 +64,7 @@ class PLATFORM_EXPORT RTCRtpTransceiverPlatform {
virtual base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
const = 0;
virtual webrtc::RTCError SetCodecPreferences(
- WebVector<webrtc::RtpCodecCapability>) {
+ Vector<webrtc::RtpCodecCapability>) {
return {};
}
};
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h
new file mode 100644
index 00000000000..753bb216047
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h
@@ -0,0 +1,22 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_SCOPED_REFPTR_CROSS_THREAD_COPIER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_SCOPED_REFPTR_CROSS_THREAD_COPIER_H_
+
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+namespace WTF {
+
+template <typename T>
+struct CrossThreadCopier<rtc::scoped_refptr<T>> {
+ STATIC_ONLY(CrossThreadCopier);
+ using Type = rtc::scoped_refptr<T>;
+ static Type Copy(Type pointer) { return pointer; }
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_SCOPED_REFPTR_CROSS_THREAD_COPIER_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h
index 6c003142933..69ea1e6b320 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h
@@ -23,7 +23,7 @@ class PLATFORM_EXPORT RTCSessionDescriptionPlatform final
String Sdp() { return sdp_; }
void SetSdp(const String& sdp) { sdp_ = sdp; }
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
String type_;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h
index 9d88696043e..6bc18622c67 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h
@@ -49,7 +49,7 @@ class RTCSessionDescriptionRequest
virtual void RequestSucceeded(RTCSessionDescriptionPlatform*) = 0;
virtual void RequestFailed(const webrtc::RTCError&) = 0;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
protected:
RTCSessionDescriptionRequest() = default;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
index 6093874c03c..a1f66c44901 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
@@ -9,24 +9,15 @@
#include <string>
#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_scoped_refptr_cross_thread_copier.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/webrtc/api/stats/rtc_stats.h"
#include "third_party/webrtc/api/stats/rtcstats_objects.h"
-namespace WTF {
-
-template <typename T>
-struct CrossThreadCopier<rtc::scoped_refptr<T>> {
- STATIC_ONLY(CrossThreadCopier);
- using Type = rtc::scoped_refptr<T>;
- static Type Copy(Type pointer) { return pointer; }
-};
-
-} // namespace WTF
-
namespace blink {
namespace {
@@ -82,7 +73,7 @@ bool IsWhitelistedStats(const webrtc::RTCStats& stats) {
// including one of its group IDs in |exposed_group_ids|.
std::vector<const webrtc::RTCStatsMemberInterface*> FilterMembers(
std::vector<const webrtc::RTCStatsMemberInterface*> stats_members,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids) {
// Note that using "is_standarized" avoids having to maintain a whitelist of
// every single standardized member, as we do at the "stats object" level
// with "RTCStatsWhitelist".
@@ -93,7 +84,7 @@ std::vector<const webrtc::RTCStatsMemberInterface*> FilterMembers(
return false;
}
- const blink::WebVector<webrtc::NonStandardGroupId>& ids =
+ const std::vector<webrtc::NonStandardGroupId>& ids =
member->group_ids();
for (const webrtc::NonStandardGroupId& id : exposed_group_ids) {
if (std::find(ids.begin(), ids.end(), id) != ids.end()) {
@@ -116,11 +107,18 @@ size_t CountWhitelistedStats(
return size;
}
+template <typename T>
+Vector<T> ToWTFVector(const std::vector<T>& vector) {
+ Vector<T> wtf_vector(SafeCast<WTF::wtf_size_t>(vector.size()));
+ std::move(vector.begin(), vector.end(), wtf_vector.begin());
+ return wtf_vector;
+}
+
} // namespace
RTCStatsReportPlatform::RTCStatsReportPlatform(
const scoped_refptr<const webrtc::RTCStatsReport>& stats_report,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids)
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids)
: stats_report_(stats_report),
it_(stats_report_->begin()),
end_(stats_report_->end()),
@@ -164,7 +162,7 @@ size_t RTCStatsReportPlatform::Size() const {
RTCStats::RTCStats(
const scoped_refptr<const webrtc::RTCStatsReport>& stats_owner,
const webrtc::RTCStats* stats,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids)
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids)
: stats_owner_(stats_owner),
stats_(stats),
stats_members_(FilterMembers(stats->Members(), exposed_group_ids)) {
@@ -255,63 +253,63 @@ String RTCStatsMember::ValueString() const {
*member_->cast_to<webrtc::RTCStatsMember<std::string>>());
}
-blink::WebVector<int> RTCStatsMember::ValueSequenceBool() const {
+Vector<bool> RTCStatsMember::ValueSequenceBool() const {
DCHECK(IsDefined());
- const std::vector<bool>& vector =
+ const std::vector<bool> vector =
*member_->cast_to<webrtc::RTCStatsMember<std::vector<bool>>>();
- std::vector<int> uint32_vector;
- uint32_vector.reserve(vector.size());
- for (size_t i = 0; i < vector.size(); ++i) {
- uint32_vector.push_back(vector[i] ? 1 : 0);
- }
- return blink::WebVector<int>(uint32_vector);
+ return ToWTFVector(vector);
}
-blink::WebVector<int32_t> RTCStatsMember::ValueSequenceInt32() const {
+Vector<int32_t> RTCStatsMember::ValueSequenceInt32() const {
DCHECK(IsDefined());
- return blink::WebVector<int32_t>(
- *member_->cast_to<webrtc::RTCStatsMember<std::vector<int32_t>>>());
+ const std::vector<int32_t> vector =
+ *member_->cast_to<webrtc::RTCStatsMember<std::vector<int32_t>>>();
+ return ToWTFVector(vector);
}
-blink::WebVector<uint32_t> RTCStatsMember::ValueSequenceUint32() const {
+Vector<uint32_t> RTCStatsMember::ValueSequenceUint32() const {
DCHECK(IsDefined());
- return blink::WebVector<uint32_t>(
- *member_->cast_to<webrtc::RTCStatsMember<std::vector<uint32_t>>>());
+ const std::vector<uint32_t> vector =
+ *member_->cast_to<webrtc::RTCStatsMember<std::vector<uint32_t>>>();
+ return ToWTFVector(vector);
}
-blink::WebVector<int64_t> RTCStatsMember::ValueSequenceInt64() const {
+Vector<int64_t> RTCStatsMember::ValueSequenceInt64() const {
DCHECK(IsDefined());
- return blink::WebVector<int64_t>(
- *member_->cast_to<webrtc::RTCStatsMember<std::vector<int64_t>>>());
+ const std::vector<int64_t> vector =
+ *member_->cast_to<webrtc::RTCStatsMember<std::vector<int64_t>>>();
+ return ToWTFVector(vector);
}
-blink::WebVector<uint64_t> RTCStatsMember::ValueSequenceUint64() const {
+Vector<uint64_t> RTCStatsMember::ValueSequenceUint64() const {
DCHECK(IsDefined());
- return blink::WebVector<uint64_t>(
- *member_->cast_to<webrtc::RTCStatsMember<std::vector<uint64_t>>>());
+ const std::vector<uint64_t> vector =
+ *member_->cast_to<webrtc::RTCStatsMember<std::vector<uint64_t>>>();
+ return ToWTFVector(vector);
}
-blink::WebVector<double> RTCStatsMember::ValueSequenceDouble() const {
+Vector<double> RTCStatsMember::ValueSequenceDouble() const {
DCHECK(IsDefined());
- return blink::WebVector<double>(
- *member_->cast_to<webrtc::RTCStatsMember<std::vector<double>>>());
+ const std::vector<double> vector =
+ *member_->cast_to<webrtc::RTCStatsMember<std::vector<double>>>();
+ return ToWTFVector(vector);
}
-blink::WebVector<String> RTCStatsMember::ValueSequenceString() const {
+Vector<String> RTCStatsMember::ValueSequenceString() const {
DCHECK(IsDefined());
const std::vector<std::string>& sequence =
*member_->cast_to<webrtc::RTCStatsMember<std::vector<std::string>>>();
- blink::WebVector<String> web_sequence(sequence.size());
+ Vector<String> wtf_sequence(sequence.size());
for (size_t i = 0; i < sequence.size(); ++i)
- web_sequence[i] = String::FromUTF8(sequence[i]);
- return web_sequence;
+ wtf_sequence[i] = String::FromUTF8(sequence[i]);
+ return wtf_sequence;
}
rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback>
CreateRTCStatsCollectorCallback(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
- blink::WebRTCStatsReportCallback callback,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ RTCStatsReportCallback callback,
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids) {
return rtc::scoped_refptr<RTCStatsCollectorCallbackImpl>(
new rtc::RefCountedObject<RTCStatsCollectorCallbackImpl>(
std::move(main_thread), std::move(callback), exposed_group_ids));
@@ -319,8 +317,8 @@ CreateRTCStatsCollectorCallback(
RTCStatsCollectorCallbackImpl::RTCStatsCollectorCallbackImpl(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
- blink::WebRTCStatsReportCallback callback,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids)
+ RTCStatsReportCallback callback,
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids)
: main_thread_(std::move(main_thread)),
callback_(std::move(callback)),
exposed_group_ids_(exposed_group_ids) {}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h
index e518f20d4d0..e6e85007988 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats.h
@@ -5,15 +5,26 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_STATS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_STATS_H_
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "base/callback.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
#include "third_party/webrtc/api/stats/rtc_stats.h"
#include "third_party/webrtc/api/stats/rtc_stats_collector_callback.h"
#include "third_party/webrtc/api/stats/rtc_stats_report.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace webrtc {
+class RTCStatsCollectorCallback;
+enum class NonStandardGroupId;
+} // namespace webrtc
+
namespace blink {
class RTCStats;
@@ -26,14 +37,11 @@ class RTCStatsMember;
//
// Note: This class is named |RTCStatsReportPlatform| not to collide with class
// |RTCStatsReport|, from renderer/modules/peerconnection/rtc_stats_report.cc|h.
-//
-// TODO(crbug.com/787254): Switch over the classes below from using WebVector
-// to WTF::Vector, when their respective parent classes are gone.
class PLATFORM_EXPORT RTCStatsReportPlatform {
public:
RTCStatsReportPlatform(
const scoped_refptr<const webrtc::RTCStatsReport>& stats_report,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids);
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids);
virtual ~RTCStatsReportPlatform();
// Creates a new report object that is a handle to the same underlying stats
// report (the stats are not copied). The new report's iterator is reset,
@@ -53,17 +61,16 @@ class PLATFORM_EXPORT RTCStatsReportPlatform {
const scoped_refptr<const webrtc::RTCStatsReport> stats_report_;
webrtc::RTCStatsReport::ConstIterator it_;
const webrtc::RTCStatsReport::ConstIterator end_;
- blink::WebVector<webrtc::NonStandardGroupId> exposed_group_ids_;
+ Vector<webrtc::NonStandardGroupId> exposed_group_ids_;
// Number of whitelisted webrtc::RTCStats in |stats_report_|.
const size_t size_;
};
class PLATFORM_EXPORT RTCStats {
public:
- RTCStats(
- const scoped_refptr<const webrtc::RTCStatsReport>& stats_owner,
- const webrtc::RTCStats* stats,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids);
+ RTCStats(const scoped_refptr<const webrtc::RTCStatsReport>& stats_owner,
+ const webrtc::RTCStats* stats,
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids);
virtual ~RTCStats();
String Id() const;
@@ -99,13 +106,13 @@ class PLATFORM_EXPORT RTCStatsMember {
uint64_t ValueUint64() const;
double ValueDouble() const;
String ValueString() const;
- blink::WebVector<int> ValueSequenceBool() const;
- blink::WebVector<int32_t> ValueSequenceInt32() const;
- blink::WebVector<uint32_t> ValueSequenceUint32() const;
- blink::WebVector<int64_t> ValueSequenceInt64() const;
- blink::WebVector<uint64_t> ValueSequenceUint64() const;
- blink::WebVector<double> ValueSequenceDouble() const;
- blink::WebVector<String> ValueSequenceString() const;
+ Vector<bool> ValueSequenceBool() const;
+ Vector<int32_t> ValueSequenceInt32() const;
+ Vector<uint32_t> ValueSequenceUint32() const;
+ Vector<int64_t> ValueSequenceInt64() const;
+ Vector<uint64_t> ValueSequenceUint64() const;
+ Vector<double> ValueSequenceDouble() const;
+ Vector<String> ValueSequenceString() const;
private:
// Reference to keep the report that owns |member_|'s stats object alive.
@@ -114,6 +121,16 @@ class PLATFORM_EXPORT RTCStatsMember {
const webrtc::RTCStatsMemberInterface* const member_;
};
+using RTCStatsReportCallback =
+ base::OnceCallback<void(std::unique_ptr<RTCStatsReportPlatform>)>;
+
+PLATFORM_EXPORT
+rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback>
+CreateRTCStatsCollectorCallback(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread,
+ RTCStatsReportCallback callback,
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids);
+
// A stats collector callback.
// It is invoked on the WebRTC signaling thread and will post a task to invoke
// |callback| on the thread given in the |main_thread| argument.
@@ -127,18 +144,20 @@ class PLATFORM_EXPORT RTCStatsCollectorCallbackImpl
protected:
RTCStatsCollectorCallbackImpl(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
- blink::WebRTCStatsReportCallback callback2,
- const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids);
+ RTCStatsReportCallback callback,
+ const Vector<webrtc::NonStandardGroupId>& exposed_group_ids);
~RTCStatsCollectorCallbackImpl() override;
void OnStatsDeliveredOnMainThread(
rtc::scoped_refptr<const webrtc::RTCStatsReport> report);
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
- blink::WebRTCStatsReportCallback callback_;
- blink::WebVector<webrtc::NonStandardGroupId> exposed_group_ids_;
+ RTCStatsReportCallback callback_;
+ Vector<webrtc::NonStandardGroupId> exposed_group_ids_;
};
+PLATFORM_EXPORT void WhitelistStatsForTesting(const char* type);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_STATS_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h
index 5c83bbd6d7f..e013c6b151d 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h
@@ -74,7 +74,7 @@ class RTCStatsRequest : public GarbageCollected<RTCStatsRequest> {
virtual MediaStreamComponent* Component() = 0;
virtual void RequestSucceeded(RTCStatsResponseBase*) = 0;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
protected:
RTCStatsRequest() = default;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_test.cc
index 12678fb053f..98ec0d03b41 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_test.cc
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
#include "third_party/webrtc/api/stats/rtc_stats_report.h"
#include "third_party/webrtc/api/stats/rtcstats_objects.h"
#include "third_party/webrtc/stats/test/rtc_test_stats.h"
@@ -103,7 +103,7 @@ TEST(RTCStatsTest, IncludeAllMembers) {
// Include both standard and non-standard member.
RTCStatsReportPlatform report(
- webrtc_report.get(), std::vector<webrtc::NonStandardGroupId>{
+ webrtc_report.get(), Vector<webrtc::NonStandardGroupId>{
webrtc::NonStandardGroupId::kGroupIdForTesting});
std::unique_ptr<RTCStats> stats = report.GetStats("id");
ASSERT_NE(nullptr, stats);
@@ -127,7 +127,7 @@ TEST(RTCStatsTest, CopyHandle) {
ASSERT_EQ(1u, standard_members_copy->GetStats("id")->MembersCount());
RTCStatsReportPlatform all_members_report(
- webrtc_report.get(), std::vector<webrtc::NonStandardGroupId>{
+ webrtc_report.get(), Vector<webrtc::NonStandardGroupId>{
webrtc::NonStandardGroupId::kGroupIdForTesting});
std::unique_ptr<RTCStatsReportPlatform> all_members_copy =
all_members_report.CopyHandle();
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
index 3783f4c79f8..c61e2df1da5 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
@@ -8,6 +8,7 @@
#include <functional>
#include <utility>
+#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/logging.h"
@@ -18,6 +19,7 @@
#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
@@ -68,12 +70,6 @@ const int32_t kMaxDecodeHistory = 32;
// requesting fallback to software decode.
const int32_t kMaxConsecutiveErrors = 5;
-// Currently, RTCVideoDecoderAdapter only tries one VideoDecoderImplementation.
-// Since we use it in multiple places, memorize it here to make it clear that
-// they must be changed together.
-constexpr media::VideoDecoderImplementation kImplementation =
- media::VideoDecoderImplementation::kDefault;
-
// Map webrtc::VideoCodecType to media::VideoCodec.
media::VideoCodec ToVideoCodec(webrtc::VideoCodecType video_codec_type) {
switch (video_codec_type) {
@@ -123,10 +119,10 @@ void FinishWait(base::WaitableEvent* waiter, bool* result_out, bool result) {
}
void OnRequestOverlayInfo(bool decoder_requires_restart_for_overlay,
- const media::ProvideOverlayInfoCB& overlay_info_cb) {
+ media::ProvideOverlayInfoCB overlay_info_cb) {
// Android overlays are not supported.
if (overlay_info_cb)
- overlay_info_cb.Run(media::OverlayInfo());
+ std::move(overlay_info_cb).Run(media::OverlayInfo());
}
} // namespace
@@ -157,8 +153,9 @@ std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
kDefaultSize, media::EmptyExtraData(),
media::EncryptionScheme::kUnencrypted);
if (gpu_factories->IsDecoderConfigSupported(kImplementation, config) ==
- media::GpuVideoAcceleratorFactories::Supported::kFalse)
+ media::GpuVideoAcceleratorFactories::Supported::kFalse) {
return nullptr;
+ }
// Synchronously verify that the decoder can be initialized.
std::unique_ptr<RTCVideoDecoderAdapter> rtc_video_decoder_adapter =
@@ -209,7 +206,9 @@ bool RTCVideoDecoderAdapter::InitializeSync(
CrossThreadBindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
CrossThreadUnretained(this), config,
std::move(init_cb)))) {
- waiter.Wait();
+ // TODO(crbug.com/1076817) Remove if a root cause is found.
+ if (!waiter.TimedWait(base::TimeDelta::FromSeconds(10)))
+ return false;
}
return result;
}
@@ -225,6 +224,10 @@ int32_t RTCVideoDecoderAdapter::InitDecode(
base::AutoLock auto_lock(lock_);
UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", !has_error_);
+ if (!has_error_) {
+ UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderProfile",
+ GuessVideoCodecProfile(format_));
+ }
return has_error_ ? WEBRTC_VIDEO_CODEC_UNINITIALIZED : WEBRTC_VIDEO_CODEC_OK;
}
@@ -388,9 +391,17 @@ void RTCVideoDecoderAdapter::InitializeOnMediaThread(
media::VideoDecoder::OutputCB output_cb = ConvertToBaseRepeatingCallback(
CrossThreadBindRepeating(&RTCVideoDecoderAdapter::OnOutput, weak_this_));
- video_decoder_->Initialize(config, low_delay, cdm_context,
- ConvertToBaseOnceCallback(std::move(init_cb)),
- output_cb, base::DoNothing());
+ video_decoder_->Initialize(
+ config, low_delay, cdm_context,
+ base::BindOnce(&RTCVideoDecoderAdapter::OnInitializeDone,
+ ConvertToBaseOnceCallback(std::move(init_cb))),
+ output_cb, base::DoNothing());
+}
+
+// static
+void RTCVideoDecoderAdapter::OnInitializeDone(base::OnceCallback<void(bool)> cb,
+ media::Status status) {
+ std::move(cb).Run(status.is_ok());
}
void RTCVideoDecoderAdapter::DecodeOnMediaThread() {
@@ -454,7 +465,8 @@ void RTCVideoDecoderAdapter::OnOutput(scoped_refptr<media::VideoFrame> frame) {
webrtc::VideoFrame::Builder()
.set_video_frame_buffer(
new rtc::RefCountedObject<blink::WebRtcVideoFrameAdapter>(
- std::move(frame)))
+ std::move(frame),
+ WebRtcVideoFrameAdapter::LogStatus::kNoLogging))
.set_timestamp_rtp(static_cast<uint32_t>(timestamp.InMicroseconds()))
.set_timestamp_us(0)
.set_rotation(webrtc::kVideoRotation_0)
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
index 89bb76c62f2..9d67fb60e8b 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
@@ -14,9 +14,11 @@
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "media/base/decode_status.h"
+#include "media/base/status.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"
+#include "media/video/supported_video_decoder_config.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -51,6 +53,12 @@ namespace blink {
// way to synchronize this correctly.
class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
public:
+ // Currently, RTCVideoDecoderAdapter only tries one
+ // VideoDecoderImplementation.
+ // Since we use it in multiple places, memorize it here to make it clear that
+ // they must be changed together.
+ static constexpr media::VideoDecoderImplementation kImplementation =
+ media::VideoDecoderImplementation::kDefault;
// Creates and initializes an RTCVideoDecoderAdapter. Returns nullptr if
// |format| cannot be supported.
// Called on the worker thread.
@@ -92,6 +100,8 @@ class PLATFORM_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
bool InitializeSync(const media::VideoDecoderConfig& config);
void InitializeOnMediaThread(const media::VideoDecoderConfig& config,
InitCB init_cb);
+ static void OnInitializeDone(base::OnceCallback<void(bool)> cb,
+ media::Status status);
void DecodeOnMediaThread();
void OnDecodeDone(media::DecodeStatus status);
void OnOutput(scoped_refptr<media::VideoFrame> frame);
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc
index 213daa35f8a..37becc9aaf0 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter_test.cc
@@ -162,8 +162,12 @@ class RTCVideoDecoderAdapterTest : public ::testing::Test {
bool CreateAndInitialize(bool init_cb_result = true) {
EXPECT_CALL(*video_decoder_, Initialize_(_, _, _, _, _, _))
- .WillOnce(DoAll(SaveArg<0>(&vda_config_), SaveArg<4>(&output_cb_),
- base::test::RunOnceCallback<3>(init_cb_result)));
+ .WillOnce(DoAll(
+ SaveArg<0>(&vda_config_), SaveArg<4>(&output_cb_),
+ base::test::RunOnceCallback<3>(
+ init_cb_result
+ ? media::OkStatus()
+ : media::Status(media::StatusCode::kCodeOnlyForTesting))));
rtc_video_decoder_adapter_ =
RTCVideoDecoderAdapter::Create(&gpu_factories_, sdp_format_);
return !!rtc_video_decoder_adapter_;
@@ -363,7 +367,7 @@ TEST_F(RTCVideoDecoderAdapterTest, ReinitializesForHDRColorSpaceInitially) {
// First Decode() should cause a reinitialize as new color space is given.
EXPECT_CALL(*video_decoder_, Initialize_(_, _, _, _, _, _))
.WillOnce(DoAll(SaveArg<0>(&vda_config_),
- base::test::RunOnceCallback<3>(true)));
+ base::test::RunOnceCallback<3>(media::OkStatus())));
webrtc::EncodedImage first_input_image = GetEncodedImageWithColorSpace(0);
ASSERT_EQ(rtc_video_decoder_adapter_->Decode(first_input_image, false, 0),
WEBRTC_VIDEO_CODEC_OK);
@@ -395,7 +399,8 @@ TEST_F(RTCVideoDecoderAdapterTest, HandlesReinitializeFailure) {
// Set Initialize() to fail.
EXPECT_CALL(*video_decoder_, Initialize_(_, _, _, _, _, _))
- .WillOnce(base::test::RunOnceCallback<3>(false));
+ .WillOnce(base::test::RunOnceCallback<3>(
+ media::Status(media::StatusCode::kCodeOnlyForTesting)));
ASSERT_EQ(rtc_video_decoder_adapter_->Decode(input_image, false, 0),
WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
index 2ab30075132..cb12d36124c 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
@@ -4,17 +4,128 @@
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h"
+#include <array>
#include <memory>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
+#include "media/base/media_util.h"
+#include "media/base/video_codecs.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h"
+#include "third_party/webrtc/media/base/h264_profile_level_id.h"
+#include "third_party/webrtc/media/base/media_constants.h"
+#include "third_party/webrtc/media/base/vp9_profile.h"
+#include "ui/gfx/color_space.h"
+#include "ui/gfx/geometry/size.h"
namespace blink {
namespace {
+const int kDefaultFps = 30;
+// Any reasonable size, will be overridden by the decoder anyway.
+const gfx::Size kDefaultSize(640, 480);
+
+struct CodecConfig {
+ media::VideoCodec codec;
+ media::VideoCodecProfile profile;
+};
+
+constexpr std::array<CodecConfig, 6> kCodecConfigs = {{
+ {media::kCodecVP8, media::VP8PROFILE_ANY},
+ {media::kCodecVP9, media::VP9PROFILE_PROFILE0},
+ {media::kCodecVP9, media::VP9PROFILE_PROFILE2},
+ {media::kCodecH264, media::H264PROFILE_BASELINE},
+ {media::kCodecH264, media::H264PROFILE_MAIN},
+ {media::kCodecH264, media::H264PROFILE_HIGH},
+}};
+
+// Translate from media::VideoDecoderConfig to webrtc::SdpVideoFormat, or return
+// nothing if the profile isn't supported.
+base::Optional<webrtc::SdpVideoFormat> VdcToWebRtcFormat(
+ const media::VideoDecoderConfig& config) {
+ switch (config.codec()) {
+ case media::VideoCodec::kCodecVP8:
+ return webrtc::SdpVideoFormat("VP8");
+ case media::VideoCodec::kCodecVP9: {
+ webrtc::VP9Profile vp9_profile;
+ switch (config.profile()) {
+ case media::VP9PROFILE_PROFILE0:
+ vp9_profile = webrtc::VP9Profile::kProfile0;
+ break;
+ case media::VP9PROFILE_PROFILE2:
+ vp9_profile = webrtc::VP9Profile::kProfile2;
+ break;
+ default:
+ // Unsupported profile in WebRTC.
+ return base::nullopt;
+ }
+ return webrtc::SdpVideoFormat(
+ "VP9", {{webrtc::kVP9FmtpProfileId,
+ webrtc::VP9ProfileToString(vp9_profile)}});
+ }
+ case media::VideoCodec::kCodecH264: {
+ webrtc::H264::Profile h264_profile;
+ switch (config.profile()) {
+ case media::H264PROFILE_BASELINE:
+ h264_profile = webrtc::H264::kProfileBaseline;
+ break;
+ case media::H264PROFILE_MAIN:
+ h264_profile = webrtc::H264::kProfileMain;
+ break;
+ case media::H264PROFILE_HIGH:
+ h264_profile = webrtc::H264::kProfileHigh;
+ break;
+ default:
+ // Unsupported H264 profile in WebRTC.
+ return base::nullopt;
+ }
+
+ const int width = config.visible_rect().width();
+ const int height = config.visible_rect().height();
+
+ const absl::optional<webrtc::H264::Level> h264_level =
+ webrtc::H264::SupportedLevel(width * height, kDefaultFps);
+ const webrtc::H264::ProfileLevelId profile_level_id(
+ h264_profile, h264_level.value_or(webrtc::H264::kLevel1));
+
+ webrtc::SdpVideoFormat format("H264");
+ format.parameters = {
+ {cricket::kH264FmtpProfileLevelId,
+ *webrtc::H264::ProfileLevelIdToString(profile_level_id)},
+ {cricket::kH264FmtpLevelAsymmetryAllowed, "1"},
+ {cricket::kH264FmtpPacketizationMode, "1"}};
+ return format;
+ }
+ default:
+ return base::nullopt;
+ }
+}
+
+// Due to https://crbug.com/345569, HW decoders do not distinguish between
+// Constrained Baseline(CBP) and Baseline(BP) profiles. Since CBP is a subset of
+// BP, we can report support for both. It is safe to do so when SW fallback is
+// available.
+// TODO(emircan): Remove this when the bug referred above is fixed.
+void MapBaselineProfile(
+ std::vector<webrtc::SdpVideoFormat>* supported_formats) {
+ for (const auto& format : *supported_formats) {
+ const absl::optional<webrtc::H264::ProfileLevelId> profile_level_id =
+ webrtc::H264::ParseSdpProfileLevelId(format.parameters);
+ if (profile_level_id &&
+ profile_level_id->profile == webrtc::H264::kProfileBaseline) {
+ webrtc::SdpVideoFormat cbp_format = format;
+ webrtc::H264::ProfileLevelId cbp_profile = *profile_level_id;
+ cbp_profile.profile = webrtc::H264::kProfileConstrainedBaseline;
+ cbp_format.parameters[cricket::kH264FmtpProfileLevelId] =
+ *webrtc::H264::ProfileLevelIdToString(cbp_profile);
+ supported_formats->push_back(cbp_format);
+ return;
+ }
+ }
+}
+
// This extra indirection is needed so that we can delete the decoder on the
// correct thread.
class ScopedVideoDecoder : public webrtc::VideoDecoder {
@@ -66,8 +177,25 @@ RTCVideoDecoderFactory::RTCVideoDecoderFactory(
std::vector<webrtc::SdpVideoFormat>
RTCVideoDecoderFactory::GetSupportedFormats() const {
- NOTREACHED();
- return std::vector<webrtc::SdpVideoFormat>();
+ std::vector<webrtc::SdpVideoFormat> supported_formats;
+ for (auto& codec_config : kCodecConfigs) {
+ media::VideoDecoderConfig config(
+ codec_config.codec, codec_config.profile,
+ media::VideoDecoderConfig::AlphaMode::kIsOpaque,
+ media::VideoColorSpace(), media::kNoTransformation, kDefaultSize,
+ gfx::Rect(kDefaultSize), kDefaultSize, media::EmptyExtraData(),
+ media::EncryptionScheme::kUnencrypted);
+ if (gpu_factories_->IsDecoderConfigSupported(
+ RTCVideoDecoderAdapter::kImplementation, config) ==
+ media::GpuVideoAcceleratorFactories::Supported::kTrue) {
+ base::Optional<webrtc::SdpVideoFormat> format = VdcToWebRtcFormat(config);
+ if (format) {
+ supported_formats.push_back(*format);
+ }
+ }
+ }
+ MapBaselineProfile(&supported_formats);
+ return supported_formats;
}
RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
index fdb679f48a6..9f7a84d505d 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -20,19 +20,19 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
+#include "base/thread_annotations.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/bitstream_buffer.h"
-#include "media/base/media_switches.h"
#include "media/base/video_bitrate_allocation.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
+#include "media/capture/capture_switches.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "media/video/h264_parser.h"
#include "media/video/video_encode_accelerator.h"
-#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
@@ -61,6 +61,38 @@ namespace blink {
namespace {
+webrtc::VideoEncoder::EncoderInfo CopyToWebrtcEncoderInfo(
+ const media::VideoEncoderInfo& enc_info) {
+ webrtc::VideoEncoder::EncoderInfo info;
+ info.implementation_name = enc_info.implementation_name;
+ info.supports_native_handle = enc_info.supports_native_handle;
+ info.has_trusted_rate_controller = enc_info.has_trusted_rate_controller;
+ info.is_hardware_accelerated = enc_info.is_hardware_accelerated;
+ info.supports_simulcast = enc_info.supports_simulcast;
+ // TODO(crbug.com/1034686): Copy ScalingSettings once getStats() hang issue
+ // is resolved.
+ // info.scaling_settings = webrtc::VideoEncoder::ScalingSettings(
+ // enc_info.scaling_settings.min_qp, enc_info.scaling_settings.max_qp);
+ static_assert(
+ webrtc::kMaxSpatialLayers >= media::VideoEncoderInfo::kMaxSpatialLayers,
+ "webrtc::kMaxSpatiallayers is less than "
+ "media::VideoEncoderInfo::kMaxSpatialLayers");
+ for (size_t i = 0; i < base::size(enc_info.fps_allocation); ++i) {
+ if (enc_info.fps_allocation[i].empty())
+ continue;
+ info.fps_allocation[i] =
+ absl::InlinedVector<uint8_t, webrtc::kMaxTemporalStreams>(
+ enc_info.fps_allocation[i].begin(),
+ enc_info.fps_allocation[i].end());
+ }
+ for (const auto& limit : enc_info.resolution_bitrate_limits) {
+ info.resolution_bitrate_limits.emplace_back(
+ limit.frame_size.GetArea(), limit.min_start_bitrate_bps,
+ limit.min_bitrate_bps, limit.max_bitrate_bps);
+ }
+ return info;
+}
+
struct RTCTimestamps {
RTCTimestamps(const base::TimeDelta& media_timestamp,
int32_t rtp_timestamp,
@@ -156,6 +188,9 @@ class RTCVideoEncoder::Impl
media::VideoCodecProfile profile,
base::WaitableEvent* async_waiter,
int32_t* async_retval);
+
+ webrtc::VideoEncoder::EncoderInfo GetEncoderInfo() const;
+
// Enqueue a frame from WebRTC for encoding.
// RTCVideoEncoder expects to be able to call this function synchronously from
// its own thread, hence the |async_waiter| and |async_retval| arguments.
@@ -196,6 +231,7 @@ class RTCVideoEncoder::Impl
int32_t bitstream_buffer_id,
const media::BitstreamBufferMetadata& metadata) override;
void NotifyError(media::VideoEncodeAccelerator::Error error) override;
+ void NotifyEncoderInfoChange(const media::VideoEncoderInfo& info) override;
private:
friend class base::RefCountedThreadSafe<Impl>;
@@ -319,15 +355,18 @@ class RTCVideoEncoder::Impl
// The content type, as reported to WebRTC (screenshare vs realtime video).
const webrtc::VideoContentType video_content_type_;
- // Protect |status_|. |status_| is read or written on |gpu_task_runner_| in
- // Impl. It can be read in RTCVideoEncoder on other threads.
- mutable base::Lock status_lock_;
+ webrtc::VideoEncoder::EncoderInfo encoder_info_ GUARDED_BY(lock_);
+
+ // Protect |status_| and |encoder_info_|. |status_| is read or written on
+ // |gpu_task_runner_| in Impl. It can be read in RTCVideoEncoder on other
+ // threads.
+ mutable base::Lock lock_;
// We cannot immediately return error conditions to the WebRTC user of this
// class, as there is no error callback in the webrtc::VideoEncoder interface.
// Instead, we cache an error status here and return it the next time an
- // interface entry point is called. This is protected by |status_lock_|.
- int32_t status_;
+ // interface entry point is called. This is protected by |lock_|.
+ int32_t status_ GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(Impl);
};
@@ -348,6 +387,13 @@ RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
video_content_type_(video_content_type),
status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) {
DETACH_FROM_THREAD(thread_checker_);
+
+ // The default values of EncoderInfo.
+ encoder_info_.implementation_name =
+ RTCVideoEncoder::Impl::ImplementationName();
+ encoder_info_.supports_native_handle = true;
+ encoder_info_.is_hardware_accelerated = true;
+ encoder_info_.has_internal_source = false;
}
void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
@@ -369,8 +415,10 @@ void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
// Check that |profile| supports |input_visible_size|.
if (base::FeatureList::IsEnabled(features::kWebRtcUseMinMaxVEADimensions)) {
const auto vea_supported_profiles =
- gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles();
- for (const auto vea_profile : vea_supported_profiles) {
+ gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles().value_or(
+ media::VideoEncodeAccelerator::SupportedProfiles());
+
+ for (const auto& vea_profile : vea_supported_profiles) {
if (vea_profile.profile == profile &&
(input_visible_size.width() > vea_profile.max_resolution.width() ||
input_visible_size.height() > vea_profile.max_resolution.height() ||
@@ -424,6 +472,18 @@ void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
// be signaled.
}
+webrtc::VideoEncoder::EncoderInfo RTCVideoEncoder::Impl::GetEncoderInfo()
+ const {
+ base::AutoLock lock(lock_);
+ return encoder_info_;
+}
+
+void RTCVideoEncoder::Impl::NotifyEncoderInfoChange(
+ const media::VideoEncoderInfo& info) {
+ base::AutoLock lock(lock_);
+ encoder_info_ = CopyToWebrtcEncoderInfo(info);
+}
+
void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame,
bool force_keyframe,
base::WaitableEvent* async_waiter,
@@ -542,12 +602,12 @@ void RTCVideoEncoder::Impl::Destroy(base::WaitableEvent* async_waiter) {
}
int32_t RTCVideoEncoder::Impl::GetStatus() const {
- base::AutoLock lock(status_lock_);
+ base::AutoLock lock(lock_);
return status_;
}
void RTCVideoEncoder::Impl::SetStatus(int32_t status) {
- base::AutoLock lock(status_lock_);
+ base::AutoLock lock(lock_);
status_ = status;
}
@@ -571,9 +631,9 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
input_frame_coded_size_ = input_coded_size;
for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
- base::UnsafeSharedMemoryRegion shm =
- mojo::CreateUnsafeSharedMemoryRegion(media::VideoFrame::AllocationSize(
- media::PIXEL_FORMAT_I420, input_coded_size));
+ base::UnsafeSharedMemoryRegion shm = base::UnsafeSharedMemoryRegion::Create(
+ media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
+ input_coded_size));
if (!shm.IsValid()) {
LogAndNotifyError(FROM_HERE, "failed to create input buffer ",
media::VideoEncodeAccelerator::kPlatformFailureError);
@@ -1223,11 +1283,10 @@ void RTCVideoEncoder::SetRates(
}
webrtc::VideoEncoder::EncoderInfo RTCVideoEncoder::GetEncoderInfo() const {
- EncoderInfo info;
- info.implementation_name = RTCVideoEncoder::Impl::ImplementationName();
- info.supports_native_handle = true;
- info.is_hardware_accelerated = true;
- info.has_internal_source = false;
+ webrtc::VideoEncoder::EncoderInfo info;
+ if (impl_)
+ info = impl_->GetEncoderInfo();
+
return info;
}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
index 5ba62ba4f96..2ad849e639a 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
@@ -21,6 +21,31 @@ namespace blink {
namespace {
+base::Optional<media::VideoCodecProfile> WebRTCFormatToCodecProfile(
+ const webrtc::SdpVideoFormat& sdp) {
+ if (sdp.name == "H264") {
+#if !defined(OS_ANDROID)
+ // Enable H264 HW encode for WebRTC when SW fallback is available, which is
+ // checked by kWebRtcH264WithOpenH264FFmpeg flag. This check should be
+ // removed when SW implementation is fully enabled.
+ bool webrtc_h264_sw_enabled = false;
+#if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+ webrtc_h264_sw_enabled = base::FeatureList::IsEnabled(
+ blink::features::kWebRtcH264WithOpenH264FFmpeg);
+#endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+ if (!webrtc_h264_sw_enabled)
+ return base::nullopt;
+#endif
+
+ return media::VideoCodecProfile::H264PROFILE_MIN;
+ } else if (sdp.name == "VP8") {
+ return media::VideoCodecProfile::VP8PROFILE_MIN;
+ } else if (sdp.name == "VP9") {
+ return media::VideoCodecProfile::VP9PROFILE_MIN;
+ }
+ return base::nullopt;
+}
+
// Translate from media::VideoEncodeAccelerator::SupportedProfile to
// webrtc::SdpVideoFormat, or return nothing if the profile isn't supported.
base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat(
@@ -101,38 +126,63 @@ bool IsSameFormat(const webrtc::SdpVideoFormat& format1,
format2.parameters);
}
-} // anonymous namespace
-
-RTCVideoEncoderFactory::RTCVideoEncoderFactory(
- media::GpuVideoAcceleratorFactories* gpu_factories)
- : gpu_factories_(gpu_factories) {
- const media::VideoEncodeAccelerator::SupportedProfiles& profiles =
- gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles();
- for (const auto& profile : profiles) {
+struct SupportedFormats {
+ bool unknown = true;
+ std::vector<media::VideoCodecProfile> profiles;
+ std::vector<webrtc::SdpVideoFormat> sdp_formats;
+};
+
+SupportedFormats GetSupportedFormatsInternal(
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ SupportedFormats supported_formats;
+ auto profiles = gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles();
+ if (!profiles)
+ return supported_formats;
+
+ // |profiles| are either the info at GpuInfo instance or the info got by
+ // querying GPU process.
+ supported_formats.unknown = false;
+ for (const auto& profile : *profiles) {
base::Optional<webrtc::SdpVideoFormat> format = VEAToWebRTCFormat(profile);
if (format) {
- supported_formats_.push_back(std::move(*format));
- profiles_.push_back(profile.profile);
+ supported_formats.profiles.push_back(profile.profile);
+ supported_formats.sdp_formats.push_back(std::move(*format));
}
}
+ return supported_formats;
}
+} // anonymous namespace
+
+RTCVideoEncoderFactory::RTCVideoEncoderFactory(
+ media::GpuVideoAcceleratorFactories* gpu_factories)
+ : gpu_factories_(gpu_factories) {}
+
RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {}
std::unique_ptr<webrtc::VideoEncoder>
RTCVideoEncoderFactory::CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) {
- for (size_t i = 0; i < supported_formats_.size(); ++i) {
- if (IsSameFormat(format, supported_formats_[i])) {
- return std::make_unique<RTCVideoEncoder>(profiles_[i], gpu_factories_);
+ std::unique_ptr<webrtc::VideoEncoder> encoder;
+ auto supported_formats = GetSupportedFormatsInternal(gpu_factories_);
+ if (!supported_formats.unknown) {
+ for (size_t i = 0; i < supported_formats.sdp_formats.size(); ++i) {
+ if (IsSameFormat(format, supported_formats.sdp_formats[i])) {
+ encoder = std::make_unique<RTCVideoEncoder>(
+ supported_formats.profiles[i], gpu_factories_);
+ }
}
+ } else {
+ auto profile = WebRTCFormatToCodecProfile(format);
+ if (profile)
+ encoder = std::make_unique<RTCVideoEncoder>(*profile, gpu_factories_);
}
- return nullptr;
+ return encoder;
}
std::vector<webrtc::SdpVideoFormat>
RTCVideoEncoderFactory::GetSupportedFormats() const {
- return supported_formats_;
+ return GetSupportedFormatsInternal(gpu_factories_).sdp_formats;
}
webrtc::VideoEncoderFactory::CodecInfo
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h
index 06236092987..72f0768a1db 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/optional.h"
#include "media/base/video_codecs.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
@@ -36,12 +37,6 @@ class RTCVideoEncoderFactory : public webrtc::VideoEncoderFactory {
private:
media::GpuVideoAcceleratorFactories* gpu_factories_;
- // List of supported webrtc::SdpVideoFormat. |profiles_| and
- // |supported_formats_| have the same length and the profile for
- // |supported_formats_[i]| is |profiles_[i]|.
- std::vector<media::VideoCodecProfile> profiles_;
- std::vector<webrtc::SdpVideoFormat> supported_formats_;
-
DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
};
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h
index 173a1bddab5..9376feb9ced 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h
@@ -44,7 +44,7 @@ class RTCVoidRequest : public GarbageCollected<RTCVoidRequest> {
virtual void RequestSucceeded() = 0;
virtual void RequestFailed(const webrtc::RTCError&) = 0;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
protected:
RTCVoidRequest() = default;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map.h b/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map.h
index 792fc6562b7..75e3561bd2b 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map.h
@@ -5,11 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_TWO_KEYS_ADAPTER_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_TWO_KEYS_ADAPTER_MAP_H_
-#include <map>
#include <memory>
#include <utility>
#include "base/logging.h"
+#include "base/optional.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -27,10 +28,6 @@ namespace blink {
// webrtc/blink object that was used to create the adapter and the secondary key
// is based on the resulting blink/webrtc object after the adapter has been
// initialized.
-//
-// TODO(crbug.com/787254): Move this class out of the Blink exposed API when
-// its clients get Onion souped, and change the use of std::map below to
-// WTF::HashMap.
template <typename PrimaryKey, typename SecondaryKey, typename Value>
class TwoKeysAdapterMap {
public:
@@ -41,13 +38,13 @@ class TwoKeysAdapterMap {
// words |!FindByPrimary(primary)| must hold.
Value* Insert(PrimaryKey primary, Value value) {
DCHECK(entries_by_primary_.find(primary) == entries_by_primary_.end());
- auto it = entries_by_primary_
- .insert(std::make_pair(
- std::move(primary),
- std::unique_ptr<Entry>(new Entry(std::move(value)))))
- .first;
- it->second->primary_it = it;
- return &it->second->value;
+ auto* add_result =
+ entries_by_primary_
+ .insert(std::move(primary),
+ std::unique_ptr<Entry>(new Entry(std::move(value))))
+ .stored_value;
+ add_result->value->primary_key = add_result->key;
+ return &add_result->value->value;
}
// Maps the secondary key to the value mapped by the primary key, increasing
@@ -61,11 +58,10 @@ class TwoKeysAdapterMap {
DCHECK(it != entries_by_primary_.end());
DCHECK(entries_by_secondary_.find(secondary) ==
entries_by_secondary_.end());
- Entry* entry = it->second.get();
- entry->secondary_it =
- entries_by_secondary_
- .insert(std::make_pair(std::move(secondary), entry))
- .first;
+ Entry* entry = it->value.get();
+ auto* add_result =
+ entries_by_secondary_.insert(std::move(secondary), entry).stored_value;
+ entry->secondary_key = add_result->key;
}
// Returns a pointer to the value mapped by the primary key, or null if the
@@ -75,7 +71,7 @@ class TwoKeysAdapterMap {
auto it = entries_by_primary_.find(primary);
if (it == entries_by_primary_.end())
return nullptr;
- return &it->second->value;
+ return &it->value->value;
}
// Returns a pointer to the value mapped by the secondary key, or null if the
@@ -85,7 +81,7 @@ class TwoKeysAdapterMap {
auto it = entries_by_secondary_.find(secondary);
if (it == entries_by_secondary_.end())
return nullptr;
- return &it->second->value;
+ return &it->value->value;
}
// Erases the value associated with the primary key, removing the mapping of
@@ -95,8 +91,13 @@ class TwoKeysAdapterMap {
auto primary_it = entries_by_primary_.find(primary);
if (primary_it == entries_by_primary_.end())
return false;
- if (primary_it->second->secondary_it != entries_by_secondary_.end())
- entries_by_secondary_.erase(primary_it->second->secondary_it);
+
+ if (primary_it->value->secondary_key.has_value()) {
+ auto secondary_it =
+ entries_by_secondary_.find(*primary_it->value->secondary_key);
+ if (secondary_it != entries_by_secondary_.end())
+ entries_by_secondary_.erase(secondary_it);
+ }
entries_by_primary_.erase(primary_it);
return true;
}
@@ -108,7 +109,10 @@ class TwoKeysAdapterMap {
auto secondary_it = entries_by_secondary_.find(secondary);
if (secondary_it == entries_by_secondary_.end())
return false;
- entries_by_primary_.erase(secondary_it->second->primary_it);
+
+ auto primary_it =
+ entries_by_primary_.find(secondary_it->value->primary_key);
+ entries_by_primary_.erase(primary_it);
entries_by_secondary_.erase(secondary_it);
return true;
}
@@ -117,21 +121,34 @@ class TwoKeysAdapterMap {
size_t PrimarySize() const { return entries_by_primary_.size(); }
// The number of elements in the map which have secondary keys.
size_t SecondarySize() const { return entries_by_secondary_.size(); }
- bool empty() const { return entries_by_primary_.empty(); }
+ bool empty() const { return entries_by_primary_.IsEmpty(); }
private:
- // TODO(crbug.com/787254): Move this class out of the Blink exposed API when
- // its clients get Onion souped.
struct Entry {
Entry(Value value) : value(std::move(value)) {}
Value value;
- typename std::map<PrimaryKey, std::unique_ptr<Entry>>::iterator primary_it;
- typename std::map<SecondaryKey, Entry*>::iterator secondary_it;
+
+ // The primary and secondary keys are cached here, instead of the
+ // respective iterators, because WTF::HashMap invalidates iterators
+ // upon changes on the set (eg insertion, deletions).
+ //
+ // Entries are only created in TwoKeysAdapterMap::Insert, which initializes
+ // |primary_key| right afterward (so it can never be read while
+ // uninitialized).
+ PrimaryKey primary_key;
+
+ // However, for |secondary_key|, calling EraseByPrimaryKey() can
+ // read an uninitialized secondary_key in case it is left uninitialized.
+ // Hence, it is guarded with base::Optional.
+ base::Optional<SecondaryKey> secondary_key;
};
- typename std::map<PrimaryKey, std::unique_ptr<Entry>> entries_by_primary_;
- typename std::map<SecondaryKey, Entry*> entries_by_secondary_;
+ using PrimaryMap = WTF::HashMap<PrimaryKey, std::unique_ptr<Entry>>;
+ using SecondaryMap = WTF::HashMap<SecondaryKey, Entry*>;
+
+ PrimaryMap entries_by_primary_;
+ SecondaryMap entries_by_secondary_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc b/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc
index 0d27ce7e9ae..511f5322f13 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/two_keys_adapter_map_unittest.cc
@@ -6,25 +6,27 @@
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
class TwoKeysAdapterMapTest : public ::testing::Test {
public:
struct MoveOnlyValue {
- explicit MoveOnlyValue(std::string str) : str(std::move(str)) {}
+ explicit MoveOnlyValue(String str) : str(std::move(str)) {}
MoveOnlyValue(MoveOnlyValue&& other) : str(std::move(other.str)) {}
MoveOnlyValue& operator=(MoveOnlyValue&& other) {
str = std::move(other.str);
return *this;
}
- std::string str;
+ String str;
DISALLOW_COPY_AND_ASSIGN(MoveOnlyValue);
};
- TwoKeysAdapterMap<std::string, std::string, MoveOnlyValue> map_;
+ TwoKeysAdapterMap<String, String, MoveOnlyValue> map_;
};
TEST_F(TwoKeysAdapterMapTest, ShouldInitiallyBeEmpty) {
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc
index 0f6c85f8258..2de94cef8fa 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc
@@ -11,10 +11,21 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+namespace {
+
+void SendLogMessage(const std::string& message) {
+ blink::WebRtcLogMessage("WRAS::" + message);
+}
+
+} // namespace
+
namespace WTF {
template <>
@@ -48,12 +59,14 @@ WebRtcAudioSink::WebRtcAudioSink(
fifo_(ConvertToBaseRepeatingCallback(
CrossThreadBindRepeating(&WebRtcAudioSink::DeliverRebufferedAudio,
CrossThreadUnretained(this)))) {
- DVLOG(1) << "WebRtcAudioSink::WebRtcAudioSink()";
+ SendLogMessage(base::StringPrintf("WebRtcAudioSink({label=%s})",
+ adapter_->label().c_str()));
}
WebRtcAudioSink::~WebRtcAudioSink() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DVLOG(1) << "WebRtcAudioSink::~WebRtcAudioSink()";
+ SendLogMessage(base::StringPrintf("~WebRtcAudioSink([label=%s])",
+ adapter_->label().c_str()));
}
void WebRtcAudioSink::SetAudioProcessor(
@@ -72,6 +85,9 @@ void WebRtcAudioSink::SetLevel(
void WebRtcAudioSink::OnEnabledChanged(bool enabled) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ SendLogMessage(base::StringPrintf("OnEnabledChanged([label=%s] {enabled=%s})",
+ adapter_->label().c_str(),
+ (enabled ? "true" : "false")));
PostCrossThreadTask(
*adapter_->signaling_task_runner(), FROM_HERE,
CrossThreadBindOnce(
@@ -83,6 +99,16 @@ void WebRtcAudioSink::OnData(const media::AudioBus& audio_bus,
base::TimeTicks estimated_capture_time) {
// No thread check: OnData might be called on different threads (but not
// concurrently).
+
+ // TODO(crbug.com/1054769): Better to let |fifo_| handle the estimated capture
+ // time and let it return a corrected interpolated capture time to
+ // DeliverRebufferedAudio(). Current, similar treatment is used at different
+ // places where |AudioPushFifo| is applied. So a update to |AudioPushFifo|
+ // will be a joint effort, and should be carefully carried out.
+ last_estimated_capture_time_ = estimated_capture_time;
+
+ adapter_->UpdateTimestampAligner(estimated_capture_time);
+
// The following will result in zero, one, or multiple synchronous calls to
// DeliverRebufferedAudio().
fifo_.Push(audio_bus);
@@ -90,6 +116,9 @@ void WebRtcAudioSink::OnData(const media::AudioBus& audio_bus,
void WebRtcAudioSink::OnSetFormat(const media::AudioParameters& params) {
DCHECK(params.IsValid());
+ SendLogMessage(base::StringPrintf("OnSetFormat([label=%s] {params=[%s]})",
+ adapter_->label().c_str(),
+ params.AsHumanReadableString().c_str()));
params_ = params;
// Make sure that our params always reflect a buffer size of 10ms.
params_.set_frames_per_buffer(params_.sample_rate() / 100);
@@ -112,9 +141,14 @@ void WebRtcAudioSink::DeliverRebufferedAudio(const media::AudioBus& audio_bus,
"ToInterleaved expects 2 bytes.");
audio_bus.ToInterleaved<media::SignedInt16SampleTypeTraits>(
audio_bus.frames(), interleaved_data_.get());
+
+ const base::TimeTicks estimated_capture_time =
+ last_estimated_capture_time_ + media::AudioTimestampHelper::FramesToTime(
+ frame_delay, params_.sample_rate());
+
adapter_->DeliverPCMToWebRtcSinks(interleaved_data_.get(),
params_.sample_rate(), audio_bus.channels(),
- audio_bus.frames());
+ audio_bus.frames(), estimated_capture_time);
}
namespace {
@@ -129,14 +163,19 @@ WebRtcAudioSink::Adapter::Adapter(
scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
: webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
+ label_(label),
source_(std::move(source)),
signaling_task_runner_(std::move(signaling_task_runner)),
main_task_runner_(std::move(main_task_runner)) {
DCHECK(signaling_task_runner_);
DCHECK(main_task_runner_);
+ SendLogMessage(
+ base::StringPrintf("Adapter::Adapter({label=%s})", label_.c_str()));
}
WebRtcAudioSink::Adapter::~Adapter() {
+ SendLogMessage(
+ base::StringPrintf("Adapter::~Adapter([label=%s])", label_.c_str()));
if (audio_processor_) {
PostCrossThreadTask(*main_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&DereferenceOnMainThread,
@@ -148,11 +187,20 @@ void WebRtcAudioSink::Adapter::DeliverPCMToWebRtcSinks(
const int16_t* audio_data,
int sample_rate,
size_t number_of_channels,
- size_t number_of_frames) {
+ size_t number_of_frames,
+ base::TimeTicks estimated_capture_time) {
base::AutoLock auto_lock(lock_);
+
+ // This use |timestamp_aligner_| to transform |estimated_capture_timestamp| to
+ // rtc::TimeMicros(). See the comment at UpdateTimestampAligner() for more
+ // details.
+ const int64_t capture_timestamp_us = timestamp_aligner_.TranslateTimestamp(
+ estimated_capture_time.since_origin().InMicroseconds());
+
for (webrtc::AudioTrackSinkInterface* sink : sinks_) {
sink->OnData(audio_data, sizeof(int16_t) * 8, sample_rate,
- number_of_channels, number_of_frames);
+ number_of_channels, number_of_frames,
+ capture_timestamp_us / rtc::kNumMicrosecsPerMillisec);
}
}
@@ -163,6 +211,9 @@ std::string WebRtcAudioSink::Adapter::kind() const {
bool WebRtcAudioSink::Adapter::set_enabled(bool enable) {
DCHECK(!signaling_task_runner_ ||
signaling_task_runner_->RunsTasksInCurrentSequence());
+ SendLogMessage(
+ base::StringPrintf("Adapter::set_enabled([label=%s] {enable=%s})",
+ label_.c_str(), (enable ? "true" : "false")));
return webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>::set_enabled(
enable);
}
@@ -171,6 +222,8 @@ void WebRtcAudioSink::Adapter::AddSink(webrtc::AudioTrackSinkInterface* sink) {
DCHECK(!signaling_task_runner_ ||
signaling_task_runner_->RunsTasksInCurrentSequence());
DCHECK(sink);
+ SendLogMessage(
+ base::StringPrintf("Adapter::AddSink({label=%s})", label_.c_str()));
base::AutoLock auto_lock(lock_);
DCHECK(!base::Contains(sinks_, sink));
sinks_.push_back(sink);
@@ -180,6 +233,8 @@ void WebRtcAudioSink::Adapter::RemoveSink(
webrtc::AudioTrackSinkInterface* sink) {
DCHECK(!signaling_task_runner_ ||
signaling_task_runner_->RunsTasksInCurrentSequence());
+ SendLogMessage(
+ base::StringPrintf("Adapter::RemoveSink([label=%s])", label_.c_str()));
base::AutoLock auto_lock(lock_);
const auto it = std::find(sinks_.begin(), sinks_.end(), sink);
if (it != sinks_.end())
@@ -200,6 +255,8 @@ bool WebRtcAudioSink::Adapter::GetSignalLevel(int* level) {
// Convert from float in range [0.0,1.0] to an int in range [0,32767].
*level = static_cast<int>(signal_level * std::numeric_limits<int16_t>::max() +
0.5f /* rounding to nearest int */);
+ // TODO(crbug/1073391): possibly log the signal level but first check the
+ // calling frequency of this method to avoid creating too much data.
return true;
}
@@ -216,4 +273,16 @@ webrtc::AudioSourceInterface* WebRtcAudioSink::Adapter::GetSource() const {
return source_.get();
}
+void WebRtcAudioSink::Adapter::UpdateTimestampAligner(
+ base::TimeTicks capture_time) {
+ // The |timestamp_aligner_| stamps an audio frame as if it is captured 'now',
+ // taking rtc::TimeMicros as the reference clock. It does not provide the time
+ // that the frame was originally captured, Using |timestamp_aligner_| rather
+ // than calling rtc::TimeMicros is to take the advantage that it aligns its
+ // output timestamps such that the time spacing in the |capture_time| is
+ // maintained.
+ timestamp_aligner_.TranslateTimestamp(
+ capture_time.since_origin().InMicroseconds(), rtc::TimeMicros());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h
index b405636dffe..20782171732 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h
@@ -24,6 +24,8 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/media_stream_interface.h"
#include "third_party/webrtc/pc/media_stream_track.h"
+#include "third_party/webrtc/rtc_base/time_utils.h"
+#include "third_party/webrtc/rtc_base/timestamp_aligner.h"
namespace blink {
@@ -100,7 +102,10 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
void DeliverPCMToWebRtcSinks(const int16_t* audio_data,
int sample_rate,
size_t number_of_channels,
- size_t number_of_frames);
+ size_t number_of_frames,
+ base::TimeTicks estimated_capture_time);
+
+ std::string label() const { return label_; }
// webrtc::MediaStreamTrack implementation.
std::string kind() const override;
@@ -114,10 +119,14 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
override;
webrtc::AudioSourceInterface* GetSource() const override;
+ void UpdateTimestampAligner(base::TimeTicks capture_time);
+
protected:
~Adapter() override;
private:
+ const std::string label_;
+
const scoped_refptr<webrtc::AudioSourceInterface> source_;
// Task runner for operations that must be done on libjingle's signaling
@@ -147,6 +156,11 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
// receive the audio data.
std::vector<webrtc::AudioTrackSinkInterface*> sinks_;
+ // Used for getting capture timestamps referenced on the rtc::TimeMicros()
+ // clock. See the comment at the implementation of UpdateTimestampAligner()
+ // for more details.
+ rtc::TimestampAligner timestamp_aligner_;
+
DISALLOW_COPY_AND_ASSIGN(Adapter);
};
@@ -178,6 +192,8 @@ class PLATFORM_EXPORT WebRtcAudioSink : public WebMediaStreamAudioSink {
// interleaved samples.
std::unique_ptr<int16_t[]> interleaved_data_;
+ base::TimeTicks last_estimated_capture_time_;
+
// In debug builds, check that WebRtcAudioSink's public methods are all being
// called on the main render thread.
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink_test.cc
new file mode 100644
index 00000000000..0088ef19091
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink_test.cc
@@ -0,0 +1,126 @@
+// 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 "third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.h"
+
+#include "media/base/fake_single_thread_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace blink {
+
+namespace {
+
+class MockAudioSink : public webrtc::AudioTrackSinkInterface {
+ public:
+ MockAudioSink() = default;
+ ~MockAudioSink() override = default;
+ MOCK_METHOD6(OnData,
+ void(const void* audio_data,
+ int bits_per_sample,
+ int sample_rate,
+ size_t number_of_channels,
+ size_t number_of_samples,
+ absl::optional<int64_t> absolute_capture_timestamp_ms));
+};
+
+class ScopedFakeClock : public rtc::ClockInterface {
+ public:
+ explicit ScopedFakeClock(int64_t init_time_ms)
+ : prev_clock_(rtc::SetClockForTesting(this)),
+ time_ns_(init_time_ms * rtc::kNumNanosecsPerMillisec) {}
+
+ ~ScopedFakeClock() override { rtc::SetClockForTesting(prev_clock_); }
+
+ int64_t TimeNanos() const override { return time_ns_; }
+
+ void AdvanceTimeMilliseconds(int64_t time_ms) {
+ time_ns_ += time_ms * rtc::kNumNanosecsPerMillisec;
+ }
+
+ private:
+ ClockInterface* const prev_clock_;
+ int64_t time_ns_;
+};
+
+} // namespace
+
+TEST(WebRtcAudioSinkTest, CaptureTimestamp) {
+ MockAudioSink sink_1;
+ MockAudioSink sink_2;
+ base::SimpleTestTickClock dummy_clock;
+ std::unique_ptr<WebRtcAudioSink> webrtc_audio_sink(
+ new WebRtcAudioSink("test_sink", nullptr,
+ /*signaling_task_runner=*/
+ new media::FakeSingleThreadTaskRunner(&dummy_clock),
+ /*main_task_runner=*/
+ new media::FakeSingleThreadTaskRunner(&dummy_clock)));
+
+ // |web_media_stream_audio_sink| is to access methods that are privately
+ // inherited by WebRtcAudioSink.
+ WebMediaStreamAudioSink* const web_media_stream_audio_sink =
+ static_cast<WebMediaStreamAudioSink*>(webrtc_audio_sink.get());
+
+ webrtc_audio_sink->webrtc_audio_track()->AddSink(&sink_1);
+ webrtc_audio_sink->webrtc_audio_track()->AddSink(&sink_2);
+
+ constexpr int kInputChannels = 2;
+ constexpr int kInputFramesPerBuffer = 96;
+ constexpr int kSampleRateHz = 8000;
+ constexpr int kOutputFramesPerBuffer = kSampleRateHz / 100;
+ constexpr int kEnqueueFrames = kInputFramesPerBuffer - kOutputFramesPerBuffer;
+
+ constexpr int64_t kStartRtcTimestampMs = 87654321;
+ constexpr int64_t kStartCaptureTimestampMs = 12345678;
+ constexpr int64_t kCaptureIntervalMs = 567;
+
+ web_media_stream_audio_sink->OnSetFormat(media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO,
+ kSampleRateHz, kOutputFramesPerBuffer));
+ std::unique_ptr<media::AudioBus> bus =
+ media::AudioBus::Create(kInputChannels, kInputFramesPerBuffer);
+ bus->Zero();
+
+ {
+ ScopedFakeClock clock(kStartRtcTimestampMs);
+
+ base::TimeTicks capture_time =
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(kStartCaptureTimestampMs);
+
+ // The first time to the call OnData(), the TimestampAligner should have no
+ // effect work. So expected capture timestamp is from fake_clock.
+ EXPECT_CALL(
+ sink_1,
+ OnData(_, _, kSampleRateHz, kInputChannels, kOutputFramesPerBuffer,
+ absl::make_optional<int64_t>(kStartRtcTimestampMs)));
+ EXPECT_CALL(
+ sink_2,
+ OnData(_, _, kSampleRateHz, kInputChannels, kOutputFramesPerBuffer,
+ absl::make_optional<int64_t>(kStartRtcTimestampMs)));
+
+ web_media_stream_audio_sink->OnData(*bus, capture_time);
+
+ capture_time += base::TimeDelta::FromMilliseconds(kCaptureIntervalMs);
+ clock.AdvanceTimeMilliseconds(kCaptureIntervalMs);
+
+ constexpr int64_t kExpectedTimestampMs =
+ kStartRtcTimestampMs + kCaptureIntervalMs -
+ kEnqueueFrames * 1000 / kSampleRateHz;
+ EXPECT_CALL(
+ sink_1,
+ OnData(_, _, kSampleRateHz, kInputChannels, kOutputFramesPerBuffer,
+ absl::make_optional<int64_t>(kExpectedTimestampMs)));
+ EXPECT_CALL(
+ sink_2,
+ OnData(_, _, kSampleRateHz, kInputChannels, kOutputFramesPerBuffer,
+ absl::make_optional<int64_t>(kExpectedTimestampMs)));
+
+ web_media_stream_audio_sink->OnData(*bus, capture_time);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
index 0fcc39afecb..3ed4b1a517a 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
@@ -67,12 +67,18 @@ gfx::Rect ScaleRectangle(const gfx::Rect& input_rect,
namespace blink {
+const base::Feature kWebRtcLogWebRtcVideoFrameAdapter{
+ "WebRtcLogWebRtcVideoFrameAdapter", base::FEATURE_DISABLED_BY_DEFAULT};
+
WebRtcVideoTrackSource::WebRtcVideoTrackSource(
bool is_screencast,
absl::optional<bool> needs_denoising)
: AdaptedVideoTrackSource(/*required_alignment=*/1),
is_screencast_(is_screencast),
- needs_denoising_(needs_denoising) {
+ needs_denoising_(needs_denoising),
+ log_to_webrtc_(is_screencast &&
+ base::FeatureList::IsEnabled(
+ blink::kWebRtcLogWebRtcVideoFrameAdapter)) {
DETACH_FROM_THREAD(thread_checker_);
}
@@ -325,7 +331,11 @@ void WebRtcVideoTrackSource::DeliverFrame(
webrtc::VideoFrame::Builder frame_builder =
webrtc::VideoFrame::Builder()
.set_video_frame_buffer(
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame))
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ frame,
+ (log_to_webrtc_
+ ? WebRtcVideoFrameAdapter::LogStatus::kLogToWebRtc
+ : WebRtcVideoFrameAdapter::LogStatus::kNoLogging)))
.set_rotation(webrtc::kVideoRotation_0)
.set_timestamp_us(timestamp_us);
if (update_rect) {
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
index 9a6c26f42cb..5fada0dbf5b 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_VIDEO_TRACK_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_WEBRTC_VIDEO_TRACK_SOURCE_H_
+#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_checker.h"
#include "media/base/video_frame_pool.h"
@@ -14,6 +15,8 @@
namespace blink {
+PLATFORM_EXPORT extern const base::Feature kWebRtcLogWebRtcVideoFrameAdapter;
+
// This class implements webrtc's VideoTrackSourceInterface. To pass frames down
// the webrtc video pipeline, each received a media::VideoFrame is converted to
// a webrtc::VideoFrame, taking any adaptation requested by downstream classes
@@ -80,6 +83,8 @@ class PLATFORM_EXPORT WebRtcVideoTrackSource
absl::optional<FrameAdaptationParams>
custom_frame_adaptation_params_for_testing_;
+ const bool log_to_webrtc_;
+
DISALLOW_COPY_AND_ASSIGN(WebRtcVideoTrackSource);
};
diff --git a/chromium/third_party/blink/renderer/platform/platform.gni b/chromium/third_party/blink/renderer/platform/platform.gni
index 1afa35e16a2..aa108489f23 100644
--- a/chromium/third_party/blink/renderer/platform/platform.gni
+++ b/chromium/third_party/blink/renderer/platform/platform.gni
@@ -25,9 +25,8 @@ template("blink_platform_sources") {
assert(
!defined(invoker.public_deps),
"$target_name's public_deps should be moved to //third_party/blink/renderer/platform:blink_platform_public_deps")
- deps = [
- "//third_party/blink/renderer/platform:blink_platform_public_deps",
- ]
+ deps =
+ [ "//third_party/blink/renderer/platform:blink_platform_public_deps" ]
if (defined(invoker.deps)) {
deps += invoker.deps
}
diff --git a/chromium/third_party/blink/renderer/platform/prerender.cc b/chromium/third_party/blink/renderer/platform/prerender.cc
deleted file mode 100644
index 5f2e2ce8b63..00000000000
--- a/chromium/third_party/blink/renderer/platform/prerender.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "third_party/blink/renderer/platform/prerender.h"
-
-#include "third_party/blink/public/platform/web_prerender.h"
-#include "third_party/blink/public/platform/web_prerendering_support.h"
-#include "third_party/blink/renderer/platform/prerender_client.h"
-
-namespace blink {
-
-Prerender::Prerender(PrerenderClient* client,
- const KURL& url,
- const unsigned rel_types,
- const Referrer& referrer,
- const SecurityOrigin* security_origin)
- : client_(client),
- url_(url),
- rel_types_(rel_types),
- referrer_(referrer),
- security_origin_(security_origin) {}
-
-Prerender::~Prerender() = default;
-
-void Prerender::Trace(blink::Visitor* visitor) {
- visitor->Trace(client_);
-}
-
-void Prerender::Dispose() {
- client_ = nullptr;
- extra_data_ = nullptr;
-}
-
-void Prerender::Add() {
- if (WebPrerenderingSupport* platform = WebPrerenderingSupport::Current())
- platform->Add(WebPrerender(this));
-}
-
-void Prerender::Cancel() {
- if (WebPrerenderingSupport* platform = WebPrerenderingSupport::Current())
- platform->Cancel(WebPrerender(this));
-}
-
-void Prerender::Abandon() {
- if (WebPrerenderingSupport* platform = WebPrerenderingSupport::Current())
- platform->Abandon(WebPrerender(this));
-}
-
-void Prerender::DidStartPrerender() {
- if (client_)
- client_->DidStartPrerender();
-}
-
-void Prerender::DidStopPrerender() {
- if (client_)
- client_->DidStopPrerender();
-}
-
-void Prerender::DidSendLoadForPrerender() {
- if (client_)
- client_->DidSendLoadForPrerender();
-}
-
-void Prerender::DidSendDOMContentLoadedForPrerender() {
- if (client_)
- client_->DidSendDOMContentLoadedForPrerender();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/prerender.h b/chromium/third_party/blink/renderer/platform/prerender.h
deleted file mode 100644
index 06b32a45f55..00000000000
--- a/chromium/third_party/blink/renderer/platform/prerender.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRERENDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRERENDER_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/referrer.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class PrerenderClient;
-
-class PLATFORM_EXPORT Prerender final : public GarbageCollected<Prerender> {
- DISALLOW_COPY_AND_ASSIGN(Prerender);
-
- public:
- class ExtraData : public RefCounted<ExtraData> {
- public:
- virtual ~ExtraData() = default;
- };
-
- Prerender(PrerenderClient*,
- const KURL&,
- unsigned rel_types,
- const Referrer&,
- const SecurityOrigin* security_origin);
- ~Prerender();
- void Trace(blink::Visitor*);
-
- void Dispose();
-
- void Add();
- void Cancel();
- void Abandon();
-
- const KURL& Url() const { return url_; }
- unsigned RelTypes() const { return rel_types_; }
- const String& GetReferrer() const { return referrer_.referrer; }
- network::mojom::ReferrerPolicy GetReferrerPolicy() const {
- return referrer_.referrer_policy;
- }
- const SecurityOrigin* GetSecurityOrigin() const { return security_origin_; }
-
- void SetExtraData(scoped_refptr<ExtraData> extra_data) {
- extra_data_ = std::move(extra_data);
- }
- ExtraData* GetExtraData() { return extra_data_.get(); }
-
- void DidStartPrerender();
- void DidStopPrerender();
- void DidSendLoadForPrerender();
- void DidSendDOMContentLoadedForPrerender();
-
- private:
- // The embedder's prerendering support holds on to pending Prerender objects;
- // those references should not keep the PrerenderClient alive -- if the client
- // becomes otherwise unreachable it should be GCed (at which point it will
- // abandon this Prerender object.)
- WeakMember<PrerenderClient> client_;
-
- const KURL url_;
- const unsigned rel_types_;
- const Referrer referrer_;
- const SecurityOrigin* const security_origin_;
-
- scoped_refptr<ExtraData> extra_data_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRERENDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/prerender_client.h b/chromium/third_party/blink/renderer/platform/prerender_client.h
deleted file mode 100644
index 0d56cf628c9..00000000000
--- a/chromium/third_party/blink/renderer/platform/prerender_client.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRERENDER_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRERENDER_CLIENT_H_
-
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT PrerenderClient : public GarbageCollectedMixin {
- public:
- virtual ~PrerenderClient() = default;
-
- virtual void DidStartPrerender() = 0;
- virtual void DidStopPrerender() = 0;
- virtual void DidSendLoadForPrerender() = 0;
- virtual void DidSendDOMContentLoadedForPrerender() = 0;
-
- void Trace(blink::Visitor* visitor) override {}
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
index fb78dd6dfb9..502ead1d51b 100644
--- a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -94,11 +94,6 @@
valid_type: "bool",
},
- // Set to true to have customised {feature}Enabled() method implementation.
- custom: {
- valid_type: "bool",
- },
-
// Feature policy IDL extended attribute (see crrev.com/2247923004).
feature_policy: {
},
@@ -116,14 +111,17 @@
},
{
name: "AccessibilityExposeARIAAnnotations",
- origin_trial_feature_name: "AccessibilityExposeARIAAnnotations",
- status: "experimental",
+ status: "stable",
},
{
name: "AccessibilityExposeDisplayNone",
status: "test",
},
{
+ name: "AccessibilityExposeHTMLElement",
+ status: "experimental",
+ },
+ {
name: "AccessibilityObjectModel",
status: "experimental",
},
@@ -147,22 +145,25 @@
{
name: "AllowSyncXHRInPageDismissal",
origin_trial_feature_name: "AllowSyncXHRInPageDismissal",
- status: "experimental",
},
{
name: "AnimationWorklet",
- origin_trial_feature_name: "AnimationWorklet",
status: "experimental",
},
{
name: "AOMAriaProperties",
- status: "experimental",
+ status: "stable",
},
{
name: "AOMAriaRelationshipProperties",
status: "experimental",
},
{
+ // Enabled when blink::features::kAppCache is enabled.
+ name: "AppCache",
+ status: "stable",
+ },
+ {
// Use an aspect ratio from the HTML attributes even when we use sizing
// from CSS.
// https://github.com/WICG/intrinsicsize-attribute/issues/16
@@ -170,10 +171,6 @@
status: "stable",
},
{
- name: "AsyncClipboard",
- status: "stable",
- },
- {
name: "AudioOutputDevices",
// Android does not yet support switching of audio output devices
status: {"Android": "", "default": "stable"},
@@ -228,56 +225,41 @@
},
{
name: "Badging",
- origin_trial_feature_name: "BadgingV2",
- status: "experimental",
+ status: "stable",
},
{
- name: "BidiCaretAffinity",
+ name: "BarcodeDetector",
+ status: "stable",
},
{
- name: "BlinkRuntimeCallStats",
+ name: "BidiCaretAffinity",
},
{
- // Adding simpler reading methods - stream(), text(), and arrayBuffer() -
- // to the Blob interface. See: https://github.com/w3c/FileAPI/pull/117
- name: "BlobReadMethods",
- status: "stable"
+ name: "BlinkRuntimeCallStats",
},
{
name: "BlockCredentialedSubresources",
status: "stable",
},
{
+ name: "BlockFlowHandlesWebkitLineClamp",
+ },
+ {
name: "BlockHTMLParserOnStyleSheets",
},
{
name: "BlockingDownloadsInSandbox",
- status: "test",
+ status: "stable",
},
{
name: "BlockingFocusWithoutUserActivation",
status: "experimental",
},
{
- name: "BuiltInModuleAll",
- implied_by: ["ExperimentalProductivityFeatures"],
- },
- {
- name: "BuiltInModuleInfra",
- origin_trial_feature_name: "BuiltInModuleInfra",
- implied_by: ["ExperimentalProductivityFeatures",
- "BuiltInModuleAll",
- "BuiltInModuleKvStorage",
- "BuiltInModuleSwitchElement"],
- },
- {
- name: "BuiltInModuleKvStorage",
- origin_trial_feature_name: "BuiltInModuleKvStorage",
- implied_by: ["ExperimentalProductivityFeatures"],
+ name: "BrowserVerifiedUserActivationKeyboard",
},
{
- name: "BuiltInModuleSwitchElement",
- implied_by: ["BuiltInModuleAll"],
+ name: "BrowserVerifiedUserActivationMouse",
},
{
name: "CacheInlineScriptCode"
@@ -311,6 +293,10 @@
status: "experimental",
},
{
+ name: "CaptureTimeInCsrc",
+ status: "stable",
+ },
+ {
name: "ClickPointerEvent",
status: "experimental",
},
@@ -324,6 +310,8 @@
// NativeFileSystem is in Origin Trial, which doesn't support having
// non-origin-trial-enabled features depend on it. https://crbug.com/1000486
// depends_on: ["NativeFileSystem"]
+ origin_trial_feature_name: "NativeFileSystem2",
+ origin_trial_os: ["win", "macosx", "linux", "chromeos"],
},
{
name: "CompositeAfterPaint",
@@ -364,12 +352,19 @@
status: "experimental",
},
{
+ name: "ConversionMeasurement",
+ status: "test",
+ },
+ {
name: "CookieDeprecationMessages",
status: "experimental",
},
{
- name: "CookieStore",
- origin_trial_feature_name: "CookieStore",
+ name: "CookieStoreDocument",
+ status: "experimental",
+ },
+ {
+ name: "CookieStoreWorker",
status: "experimental",
},
{
@@ -381,7 +376,6 @@
},
{
name: "CorsRFC1918",
- depends_on: ["AddressSpace"],
},
{
name: "CSS3Text",
@@ -392,9 +386,8 @@
status: "stable",
},
{
- name: "CSSAdditiveAnimations",
- depends_on: ["StackedCSSPropertyAnimations"],
- status: "experimental",
+ name: "CSSAspectRatioProperty",
+ status: "test",
},
{
name: "CSSCalcAsInt",
@@ -402,17 +395,21 @@
},
{
name: "CSSCascade",
+ status: "stable",
},
- // Support for the CSS color-scheme property from the css-color-adjust spec.
- // https://drafts.csswg.org/css-color-adjust/#color-scheme-prop
{
+ // Support for the CSS color-scheme property from the css-color-adjust spec.
+ // https://drafts.csswg.org/css-color-adjust/#color-scheme-prop
name: "CSSColorScheme",
+ status: "stable",
},
{
- // CSS min(), max() and clamp()
- // https://drafts.csswg.org/css-values-4/#comp-func
- name: "CSSComparisonFunctions",
- status: "stable",
+ // When the color-scheme is supported via the CSS color-scheme property
+ // (CSSColorScheme) or the meta tag (MetaColorScheme), the only UA
+ // rendering change is for the canvas background and the :root element
+ // color property. Enabling this runtime flag will enable dark UA
+ // rendering for form controls, scrollbars, etc.
+ name: "CSSColorSchemeUARendering",
},
{
name: "CSSFocusVisible",
@@ -434,11 +431,11 @@
status: "experimental",
},
{
- // Support for CSS intrinsic-* sizing properties.
- // https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override
+ // Support for CSS contain-intrinsic-size property.
+ // https://wicg.github.io/display-locking/contain-intrinsic-size.html
name: "CSSIntrinsicSize",
- implied_by: ["DisplayLocking"],
- status: "experimental",
+ implied_by: ["CSSSubtreeVisibility"],
+ status: "stable",
},
{
name: "CSSLayoutAPI",
@@ -462,6 +459,15 @@
status: "experimental",
},
{
+ name: "CSSMathStyle",
+ status: "experimental",
+ implied_by: ["MathMLCore"],
+ },
+ {
+ name: "CSSModules",
+ status: "experimental",
+ },
+ {
name: "CSSOffsetPathRay",
status: "experimental",
},
@@ -496,7 +502,9 @@
status: "experimental",
},
{
- name: "CSSRenderSubtree",
+ // Perform partial style and layout invalidation on web font loading.
+ // See https://crbug.com/441925 and https://bit.ly/35JjPmq for details.
+ name: "CSSReducedFontLoadingInvalidations",
status: "test",
},
{
@@ -504,6 +512,32 @@
status: "experimental",
},
{
+ // The main subtree-visibility feature.
+ // https://wicg.github.io/display-locking/
+ name: "CSSSubtreeVisibility",
+ status: "experimental",
+ implied_by: ["CSSSubtreeVisibilityHiddenMatchable"]
+ },
+ {
+ // The subtree-visibility activation event which will be replaced by
+ // the beforematch event. When beforematch is available, this feaure
+ // will be removed.
+ name: "CSSSubtreeVisibilityActivationEvent",
+ implied_by: ["CSSSubtreeVisibility"]
+ },
+ {
+ // The subtree-visibility: hidden-matchable feature. This is a planned
+ // follow-up to the main CSSSubtreeVisibility feature, thus it is gated
+ // by a different flag.
+ // https://wicg.github.io/display-locking/
+ name: "CSSSubtreeVisibilityHiddenMatchable",
+ status: "experimental"
+ },
+ {
+ name: "CSSSupportsSelector",
+ status: "stable",
+ },
+ {
name: "CSSVariables2",
status: "stable",
},
@@ -551,7 +585,12 @@
status: "stable",
},
{
+ name: "DeclarativeShadowDOM",
+ status: "experimental",
+ },
+ {
name: "DecodeJpeg420ImagesToYUV",
+ status: "test",
},
{
name: "DecodeLossyWebPImagesToYUV",
@@ -571,19 +610,10 @@
status: "experimental",
},
{
- name: "DiscardInputToMovingIframes",
- status: "stable",
- },
- {
name: "DisplayCutoutAPI",
settable_from_internals: true,
},
{
- name: "DisplayLocking",
- origin_trial_feature_name: "DisplayLocking",
- status: "experimental",
- },
- {
name: "DocumentCookie",
},
{
@@ -591,6 +621,8 @@
},
{
name: "DocumentPolicy",
+ origin_trial_feature_name: "DocumentPolicy",
+ status: "experimental",
},
{
name: "DocumentWrite",
@@ -605,12 +637,8 @@
name: "EditingNG",
},
{
- name: "EmbeddedVTTStylesheets",
- status: "experimental",
- },
- {
name: "EncryptedMediaEncryptionSchemeQuery",
- status: "test",
+ status: "stable",
},
{
name: "EncryptedMediaHdcpPolicyCheck",
@@ -679,11 +707,11 @@
name: "ExtraWebGLVideoTextureMetadata",
},
{
- name: "FallbackCursorMode",
+ name: "FaceDetector",
+ status: "experimental",
},
{
- name: "FastBorderRadius",
- status: "experimental",
+ name: "FallbackCursorMode",
},
{
name: "FeaturePolicyForClientHints",
@@ -707,18 +735,13 @@
name: "FeaturePolicyVibrateFeature"
},
{
- name: "FetchMetadata",
- status: "stable"
- },
- {
- name: "FetchMetadataDestination",
- status: "experimental"
- },
- {
+ // Also enabled when blink::features::kFileHandlingAPI is overridden
+ // on the command line (or via chrome://flags).
name: "FileHandling",
- // NativeFileSystem is in Origin Trial, which doesn't support having
- // non-origin-trial-enabled features depend on it. https://crbug.com/1000486
- // depends_on: ["NativeFileSystem"]
+ depends_on: ["NativeFileSystem"],
+ status: {"Android": "test", "default": "experimental"},
+ origin_trial_feature_name: "FileHandling",
+ origin_trial_os: ["win", "macosx", "linux", "chromeos"],
},
{
name: "FileSystem",
@@ -735,6 +758,10 @@
settable_from_internals: true,
},
{
+ name: "FontAccess",
+ status: "experimental",
+ },
+ {
name: "FontSrcLocalMatching",
// No status, as the web platform runtime enabled feature is controlled by
// a Chromium level feature.
@@ -748,22 +775,23 @@
name: "ForceDeferScriptIntervention",
},
{
- name: "ForceOverlayFullscreenVideo",
+ // This is used in tests to perform memory measurement without
+ // waiting for GC.
+ name:"ForceEagerMeasureMemory",
},
{
- name: "ForceSynchronousHTMLParsing",
+ name: "ForceLoadAtTop",
+ origin_trial_feature_name: "ForceLoadAtTop",
},
{
- name: "ForceTallerSelectPopup",
- status: {"ChromeOS": "stable"},
+ name: "ForceOverlayFullscreenVideo",
},
- // This is to communicate features::FormControlsRefresh from ui (and can be
- // removed when the feature launches).
{
- name: "FormControlsRefresh",
+ name: "ForceSynchronousHTMLParsing",
},
{
- name: "FractionalMouseEvent",
+ name: "ForceTallerSelectPopup",
+ status: {"ChromeOS": "stable"},
},
{
name: "FractionalScrollOffsets",
@@ -779,7 +807,7 @@
},
{
name: "GetDisplayMedia",
- status: "stable",
+ status: {"Android": "", "default": "stable"},
},
{
name: "GroupEffect",
@@ -789,7 +817,7 @@
name: "HrefTranslate",
depends_on: ["TranslateService"],
origin_trial_feature_name: "HrefTranslate",
- status: "experimental",
+ status: "stable",
},
// TODO(937746): Web Components v0 is disabled by default, and will be
// removed after M87.
@@ -806,7 +834,7 @@
},
{
name: "IDBRelaxedDurability",
- status: "experimental",
+ status: "stable",
},
{
name: "IdleDetection",
@@ -818,7 +846,7 @@
},
{
name: "ImageOrientation",
- status: "test",
+ status: "stable",
},
{
name: "ImplicitRootScroller",
@@ -827,13 +855,17 @@
},
{
name: "ImportMaps",
- implied_by: ["ExperimentalProductivityFeatures", "BuiltInModuleInfra"],
+ implied_by: ["ExperimentalProductivityFeatures"],
},
{
name: "InertAttribute",
status: "experimental",
},
{
+ name: "InputElementRawValue",
+ status: "experimental",
+ },
+ {
name: "InputMultipleFieldsUI",
// No plan to support complex UI for date/time INPUT types on Android.
status: {"Android": "test", "default": "stable"},
@@ -844,7 +876,7 @@
},
{
name: "IntersectionObserverDocumentScrollingElementRoot",
- status: "experimental",
+ status: "stable",
},
{
name: "IntersectionObserverV2",
@@ -866,9 +898,6 @@
name: "IsolatedWorldCSP"
},
{
- name: "JSONModules",
- },
- {
name: "KeyboardFocusableScrollers",
status: "experimental",
},
@@ -880,8 +909,14 @@
status: "experimental",
},
{
+ // LayoutNG has been enabled in M76, but we still keep this flag for
+ // testing. See web_tests/FlagExpectations/disable-layout-ng for more
+ // details about running web tests with LayoutNG disabled. This flag also
+ // provides a convenient way for testing legacy layout code path in blink
+ // unit tests.
name: "LayoutNG",
- implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFlexBox", "LayoutNGFragmentItem", "LayoutNGLineCache", "EditingNG", "BidiCaretAffinity", "LayoutNGTable"],
+ // Keep this list in sync with the one in LayoutNGFlexBox below.
+ implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFragmentItem", "LayoutNGLineCache", "EditingNG", "BidiCaretAffinity", "LayoutNGTable", "LayoutNGFragmentTraversal"],
status: "stable",
},
{
@@ -892,17 +927,22 @@
},
{
name: "LayoutNGFlexBox",
+ implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFragmentItem", "LayoutNGLineCache", "EditingNG", "BidiCaretAffinity", "LayoutNGTable", "LayoutNGFragmentTraversal"],
+ status: "experimental",
},
{
- name: "LayoutNGFragmentCaching",
- implied_by: ["LayoutNG"],
+ name: "LayoutNGForControls",
+ depends_on: ["LayoutNG"],
+ status: "experimental",
},
{
name: "LayoutNGFragmentItem",
+ implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFragmentTraversal"],
},
{
- name: "LayoutNGFragmentPaint",
- implied_by: ["LayoutNG"],
+ // Traverse the fragment tree when painting and hit-testing, instead of
+ // the layout object tree.
+ name: "LayoutNGFragmentTraversal",
},
{
name: "LayoutNGLineCache",
@@ -937,20 +977,17 @@
// Enabled by features::kLegacyWindowsDWriteFontFallback;
},
{
- name: "LinkSystemColors",
- status: "stable",
- },
- {
name:"ManualSlotting",
status:"experimental",
},
{
name: "MathMLCore",
- status:"test",
+ status:"experimental",
depends_on: ["LayoutNG"],
},
{
name:"MeasureMemory",
+ origin_trial_feature_name: "MeasureMemory",
status:"experimental",
},
{
@@ -1007,10 +1044,6 @@
name: "MediaQueryNavigationControls",
},
{
- name: "MediaQueryPrefersColorScheme",
- status: "stable",
- },
- {
name: "MediaQueryShape",
status: "experimental",
},
@@ -1020,7 +1053,7 @@
},
{
name: "MediaSessionPosition",
- status: "experimental",
+ status: "stable",
},
{
name: "MediaSessionSeeking",
@@ -1051,6 +1084,7 @@
// https://drafts.csswg.org/css-color-adjust/#color-scheme-meta
{
name: "MetaColorScheme",
+ status: "stable",
},
// This is enabled by default on Windows only. The only part that's
// "experimental" is the support on other platforms.
@@ -1063,14 +1097,14 @@
name: "MobileLayoutTheme",
},
{
- name: "ModuleDedicatedWorker",
- status: "stable",
- },
- {
name: "ModuleServiceWorker",
status: "test",
},
{
+ name: "ModuleSharedWorker",
+ status: "stable",
+ },
+ {
name: "MojoJS",
status: "test",
},
@@ -1085,14 +1119,23 @@
name: "MouseSubframeNoImplicitCapture",
},
{
+ // Named pages for pagination (the "page" CSS property).
+ name: "NamedPages",
+ status: "experimental",
+ },
+ {
// Also enabled when blink::features::kNativeFileSystemAPI is overridden
// on the command line (or via chrome://flags).
name: "NativeFileSystem",
status: {"Android": "test", "default": "experimental"},
- origin_trial_feature_name: "NativeFileSystem",
+ origin_trial_feature_name: "NativeFileSystem2",
origin_trial_os: ["win", "macosx", "linux", "chromeos"],
},
{
+ name: "NativeIO",
+ status: "experimental",
+ },
+ {
name: "NavigatorContentUtils",
// Android does not yet support NavigatorContentUtils.
status: {"Android": "", "default": "stable"},
@@ -1118,10 +1161,6 @@
name: "NewRemotePlaybackPipeline",
},
{
- name: "NewSystemColors",
- status: "stable",
- },
- {
name: "NoIdleEncodingForWebTests",
status: "test",
},
@@ -1148,6 +1187,7 @@
},
{
name: "OffMainThreadCSSPaint",
+ status: "stable",
},
{
name: "OffscreenCanvasCommit",
@@ -1162,6 +1202,10 @@
name: "OrientationEvent",
status: {"Android": "stable"},
},
+ {
+ name: "OriginPolicy",
+ status: "experimental",
+ },
// Define a sample API for testing integration with the Origin Trials
// Framework. The sample API is used in both unit and web tests for the
@@ -1251,7 +1295,6 @@
// This is to add an option to enable the Reveal button on password inputs while waiting ::reveal gets standardized.
{
name: "PasswordReveal",
- depends_on: ["FormControlsRefresh"],
},
{
name: "PaymentApp",
@@ -1266,6 +1309,10 @@
status: "stable",
},
{
+ name: "PaymentHandlerMinimalUI",
+ status: "experimental",
+ },
+ {
name: "PaymentMethodChangeEvent",
status: "stable",
},
@@ -1283,14 +1330,11 @@
status: "stable",
},
{
- name: "PerformanceManagerInstrumentation",
+ name: "PercentBasedScrolling",
+ settable_from_internals: true,
},
{
- // Flag enabling the performance observers buffered flag. The buffered
- // flag indicates whether or not the buffered entries should be loaded
- // into the observer's buffer upon registration. See crbug.com/725567.
- name: "PerformanceObserverBufferedFlag",
- status: "stable",
+ name: "PerformanceManagerInstrumentation",
},
{
name: "PeriodicBackgroundSync",
@@ -1344,6 +1388,7 @@
{
name: "Portals",
status: "test",
+ origin_trial_feature_name: "Portals",
},
{
name: "PostAnimationFrame",
@@ -1367,9 +1412,6 @@
status: "stable",
},
{
- name: "PrintBrowser",
- },
- {
name: "PriorityHints",
origin_trial_feature_name: "PriorityHints",
status: "experimental",
@@ -1387,7 +1429,12 @@
status: "experimental",
},
{
+ // Enabled when blink::features::kRawClipboard is enabled.
+ name: "RawClipboard",
+ },
+ {
name: "ReducedReferrerGranularity",
+ status: "experimental",
},
{
name: "RemotePlayback",
@@ -1400,6 +1447,15 @@
status: {"Android": "stable", "default": ""},
},
{
+ // See https://crbug.com/1012063
+ name: "RequestVideoFrameCallback",
+ status: "stable",
+ },
+ {
+ name: "ResizeObserverUpdates",
+ status: "test",
+ },
+ {
name: "RestrictAppCacheToSecureContexts",
status: "stable",
},
@@ -1414,10 +1470,6 @@
status: "stable",
},
{
- name: "RestrictedWebkitAppearance",
- status: "stable",
- },
- {
name: "RtcAudioJitterBufferMaxPackets",
origin_trial_feature_name: "RtcAudioJitterBufferMaxPackets",
status: "experimental",
@@ -1427,28 +1479,24 @@
origin_trial_feature_name: "RtcAudioJitterBufferRtxHandling",
status: "experimental",
},
- // Enables the use of the RTCDtlsTransport object.
- {
- name: "RTCDtlsTransport",
- status: "stable",
- },
// Enables the use of the RTCIceTransport with extensions.
{
name: "RTCIceTransportExtension",
origin_trial_feature_name: "RTCQuicTransport",
status: "experimental",
},
+ // Enables the use of Insertable Streams.
+ {
+ name: "RTCInsertableStreams",
+ origin_trial_feature_name: "RTCInsertableStreams",
+ status: "experimental",
+ },
// Enables the use of the RTCQuicTransport object.
{
name: "RTCQuicTransport",
origin_trial_feature_name: "RTCQuicTransport",
status: "experimental",
},
- // Enables the use of the RTCSctpTransport object.
- {
- name: "RTCSctpTransport",
- status: "stable",
- },
{
name: "RTCStatsRelativePacketArrivalDelay",
origin_trial_feature_name: "RTCStatsRelativePacketArrivalDelay",
@@ -1481,6 +1529,11 @@
name: "ScreenEnumeration",
status: "experimental",
},
+ {
+ name: "ScreenWakeLock",
+ origin_trial_feature_name: "WakeLock",
+ status: "experimental",
+ },
// WebSpeech API with both speech recognition and synthesis functionality
// is not fully enabled on all platforms.
{
@@ -1499,12 +1552,11 @@
},
{
name: "ScrollSnapAfterLayout",
- status: "experimental",
+ status: "stable",
},
{
name: "ScrollTimeline",
status: "experimental",
- origin_trial_feature_name: "AnimationWorklet",
implied_by: ['AnimationWorklet']
},
// Implements documentElement.scrollTop/Left and bodyElement.scrollTop/Left
@@ -1556,10 +1608,6 @@
status: "experimental",
},
{
- name: "ShapeDetection",
- status: "experimental",
- },
- {
name: "SharedArrayBuffer",
status: "stable",
},
@@ -1594,9 +1642,10 @@
},
{
name: "SmsReceiver",
- origin_trial_feature_name: "SmsReceiver",
- origin_trial_os: ["android"],
- status: {"default": "experimental"},
+ status: {"default": "experimental", "Android": "experimental"},
+ },
+ {
+ name: "SquashAfterPaint",
},
// Used as argument in attribute of stable-release functions/interfaces
// where a runtime-enabled feature name is required for correct IDL syntax.
@@ -1606,19 +1655,11 @@
status: "stable",
},
{
- name: "StackedCSSPropertyAnimations",
- status: "experimental",
- },
- {
// Enabled when blink::features::kStorageAccessAPI is enabled.
name: "StorageAccessAPI",
status: "test",
},
{
- name: "StorageQuotaDetails",
- status: "stable"
- },
- {
name: "StrictMimeTypesForWorkers",
status: "experimental"
},
@@ -1627,9 +1668,31 @@
status: "stable",
},
{
+ name: "SystemWakeLock",
+ status: "experimental",
+ },
+ // For unit tests.
+ {
+ name: "TestFeature",
+ },
+ // For unit tests.
+ {
+ name: "TestFeatureDependent",
+ depends_on: ["TestFeatureImplied"],
+ },
+ // For unit tests.
+ {
+ name: "TestFeatureImplied",
+ implied_by: ["TestFeature"],
+ },
+ {
+ name: "TextDetector",
+ status: "experimental",
+ },
+ {
name: "TextFragmentIdentifiers",
origin_trial_feature_name: "TextFragmentIdentifiers",
- status: "experimental",
+ status: "stable",
},
{
name: "TimerThrottlingForBackgroundTabs",
@@ -1639,6 +1702,10 @@
name: "TimerThrottlingForHiddenFrames",
status: "stable",
},
+ {
+ name: "TimeZoneChangeEvent",
+ status: "experimental",
+ },
// Many websites disable mouse support when touch APIs are available. We'd
// like to enable this always but can't until more websites fix this bug.
// Chromium sets this conditionally (eg. based on the presence of a
@@ -1657,6 +1724,8 @@
{
name: "TransferableStreams",
status: "experimental",
+ origin_trial_feature_name: "RTCInsertableStreams",
+ implied_by: ["RTCInsertableStreams"],
},
// This is conditionally set if the platform supports translation.
{
@@ -1664,13 +1733,21 @@
},
{
name: "TrustedDOMTypes",
- status: "experimental",
+ status: "stable",
+ },
+ {
+ name: "TrustTokens",
+ status: "test",
},
{
name: "UnclosedFormControlIsInvalid",
status: "experimental",
},
{
+ name: "UnderlineOffsetThickness",
+ status: "test",
+ },
+ {
name: "UnifiedPointerCaptureInBlink",
status: "stable",
},
@@ -1691,10 +1768,6 @@
implied_by: ["ExperimentalProductivityFeatures"]
},
{
- name: "UpdateHoverAtBeginFrame",
- settable_from_internals: true,
- },
- {
name: "UserActivationAPI",
status: "stable",
},
@@ -1722,9 +1795,6 @@
settable_from_internals: true,
},
{
- name: "VideoFullscreenDetection",
- },
- {
name: "VideoFullscreenOrientationLock",
},
{
@@ -1732,11 +1802,6 @@
status: "stable",
},
{
- // See https://crbug.com/1012063
- name: "VideoRequestAnimationFrame",
- status: "experimental",
- },
- {
name: "VideoRotateToFullscreen",
},
{
@@ -1745,11 +1810,7 @@
{
name: "WakeLock",
origin_trial_feature_name: "WakeLock",
- status: "experimental",
- },
- {
- name: "WasmCodeCache",
- status: "experimental",
+ implied_by: ['ScreenWakeLock', 'SystemWakeLock'],
},
{
name: "WebAnimationsAPI",
@@ -1787,10 +1848,22 @@
},
},
{
+ name: "WebBluetoothGetDevices",
+ status: "experimental",
+ },
+ {
name: "WebBluetoothScanning",
status: "experimental",
},
{
+ name: "WebCodecs",
+ status: "test",
+ },
+ {
+ name: "WebCryptoCurve25519",
+ status: "experimental",
+ },
+ {
name: "WebGL2ComputeContext",
status: "experimental",
},
@@ -1814,15 +1887,14 @@
status: "experimental",
},
{
- name: "WebkitBoxLayoutUsesFlexLayout",
- status: "stable",
- },
- {
name: "WebNFC",
+ origin_trial_feature_name: "WebNFC",
+ origin_trial_os: ["android"],
status: "experimental",
},
{
name: "WebScheduler",
+ origin_trial_feature_name: "WebScheduler",
status: "experimental",
},
// WebShare is enabled by default on Android.
@@ -1858,32 +1930,24 @@
status: "stable",
},
{
- name: "WebXRAnchors",
- // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
- },
- {
- name: "WebXRARDOMOverlay",
- // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
- status: "experimental",
- },
- {
name: "WebXRARModule",
depends_on: ["WebXR"],
- status: "experimental",
+ status: "stable",
},
{
- name: "WebXrGamepadModule",
- // depends_on: ["WebXR"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
+ name: "WebXRHitTest",
+ depends_on: ["WebXRARModule"],
status: "stable",
},
{
- name: "WebXRHitTest",
- // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
+ name: "WebXRHitTestEntityTypes",
+ depends_on: ["WebXRHitTest"],
status: "experimental"
},
{
- name: "WebXRPlaneDetection",
- // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
+ name: "WebXRIncubations",
+ depends_on: ["WebXRARModule"],
+ status: "experimental",
},
// Extends window placement functionality for multi-screen devices.
{
@@ -1891,6 +1955,15 @@
status: "experimental",
},
{
+ name: "WritableFileStream",
+ status: "experimental",
+ // NativeFileSystem is in Origin Trial, which doesn't support having
+ // non-origin-trial-enabled features depend on it. https://crbug.com/1000486
+ // depends_on: ["NativeFileSystem"]
+ origin_trial_feature_name: "NativeFileSystem2",
+ origin_trial_os: ["win", "macosx", "linux", "chromeos"],
+ },
+ {
name: "XSLT",
status: "stable",
},
diff --git a/chromium/third_party/blink/renderer/platform/runtime_enabled_features_test.cc b/chromium/third_party/blink/renderer/platform/runtime_enabled_features_test.cc
new file mode 100644
index 00000000000..099680c6127
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/runtime_enabled_features_test.cc
@@ -0,0 +1,275 @@
+// 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 "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+
+namespace blink {
+namespace {
+
+class RuntimeEnabledFeaturesTest : public testing::Test {
+ void CheckAllDisabled() {
+ CHECK(!RuntimeEnabledFeatures::TestFeatureEnabled());
+ CHECK(!RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ CHECK(!RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ CHECK(!RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabledByRuntimeFlag());
+ CHECK(!RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIImpliedEnabledByRuntimeFlag());
+ CHECK(!RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIDependentEnabledByRuntimeFlag());
+ }
+ void SetUp() override { CheckAllDisabled(); }
+ void TearDown() override {
+ backup_.Restore();
+ CheckAllDisabled();
+ }
+ RuntimeEnabledFeatures::Backup backup_;
+};
+
+// Test setup:
+// TestFeatureDependent
+// depends_on
+// TestFeatureImplied
+// implied_by
+// TestFeature
+
+TEST_F(RuntimeEnabledFeaturesTest, Relationship) {
+ // Internal status: false, false, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureEnabled(true);
+ // Internal status: true, false, false.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureImpliedEnabled(true);
+ // Internal status: true, true, false.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureDependentEnabled(true);
+ // Internal status: true, true, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureImpliedEnabled(false);
+ // Internal status: true, false, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureEnabled(false);
+ // Internal status: false, false, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ // Depends on TestFeatureImplied.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureImpliedEnabled(true);
+ // Internal status: false, true, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureDependentEnabled(false);
+ // Internal status: false, true, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+}
+
+TEST_F(RuntimeEnabledFeaturesTest, ScopedForTest) {
+ // Internal status: false, false, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureForTest f1(true);
+ // Internal status: true, false, false.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureImpliedForTest f2(true);
+ // Internal status: true, true, false.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureDependentForTest f3(true);
+ // Internal status: true, true, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureDependentForTest f3a(false);
+ // Internal status: true, true, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ }
+ // Internal status: true, true, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ }
+ }
+ // Internal status: true, false, false.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureImpliedForTest f2a(false);
+ // Internal status: true, false, false.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ }
+ }
+ // Internal status: false, false, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ {
+ ScopedTestFeatureDependentForTest f3(true);
+ // Internal status: false, false, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ // Depends on TestFeatureImplied.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureImpliedForTest f2(true);
+ // Internal status: false, true, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureForTest f1(true);
+ // Internal status: true, true, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ }
+ // Internal status: false, true, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ }
+ // Internal status: false, false, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ // Depends on TestFeatureImplied.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ {
+ ScopedTestFeatureImpliedForTest f2(true);
+ // Internal status: false, true, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+ }
+ }
+ // Internal status: false, false, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+}
+
+TEST_F(RuntimeEnabledFeaturesTest, BackupRestore) {
+ // Internal status: false, false, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureEnabled(true);
+ RuntimeEnabledFeatures::SetTestFeatureDependentEnabled(true);
+ // Internal status: true, false, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::Backup backup;
+
+ RuntimeEnabledFeatures::SetTestFeatureEnabled(false);
+ RuntimeEnabledFeatures::SetTestFeatureImpliedEnabled(true);
+ RuntimeEnabledFeatures::SetTestFeatureDependentEnabled(false);
+ // Internal status: false, true, false.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ backup.Restore();
+ // Should restore the internal status to: true, false, true.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ // Implied by TestFeature.
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ EXPECT_TRUE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+
+ RuntimeEnabledFeatures::SetTestFeatureEnabled(false);
+ // Internal status: false, false, true.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureEnabled());
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureImpliedEnabled());
+ // Depends on TestFeatureImplied.
+ EXPECT_FALSE(RuntimeEnabledFeatures::TestFeatureDependentEnabled());
+}
+
+// Test setup:
+// OriginTrialsSampleAPIImplied impled_by \
+// OriginTrialsSampleAPI
+// OriginTrialsSampleAPIDependent depends_on /
+TEST_F(RuntimeEnabledFeaturesTest, OriginTrialsByRuntimeEnabled) {
+ // Internal status: false, false, false.
+ EXPECT_FALSE(
+ RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabledByRuntimeFlag());
+ EXPECT_FALSE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIImpliedEnabledByRuntimeFlag());
+ EXPECT_FALSE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIDependentEnabledByRuntimeFlag());
+
+ RuntimeEnabledFeatures::SetOriginTrialsSampleAPIEnabled(true);
+ // Internal status: true, false, false.
+ EXPECT_TRUE(
+ RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabledByRuntimeFlag());
+ // Implied by OriginTrialsSampleAPI.
+ EXPECT_TRUE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIImpliedEnabledByRuntimeFlag());
+ EXPECT_FALSE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIDependentEnabledByRuntimeFlag());
+
+ RuntimeEnabledFeatures::SetOriginTrialsSampleAPIImpliedEnabled(true);
+ RuntimeEnabledFeatures::SetOriginTrialsSampleAPIDependentEnabled(true);
+ // Internal status: true, true, true.
+ EXPECT_TRUE(
+ RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabledByRuntimeFlag());
+ EXPECT_TRUE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIImpliedEnabledByRuntimeFlag());
+ EXPECT_TRUE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIDependentEnabledByRuntimeFlag());
+
+ RuntimeEnabledFeatures::SetOriginTrialsSampleAPIEnabled(false);
+ // Internal status: false, true, true.
+ EXPECT_FALSE(
+ RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabledByRuntimeFlag());
+ EXPECT_TRUE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIImpliedEnabledByRuntimeFlag());
+ // Depends on OriginTrialsSampleAPI.
+ EXPECT_FALSE(RuntimeEnabledFeatures::
+ OriginTrialsSampleAPIDependentEnabledByRuntimeFlag());
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
index 751e13bde93..0d5114005ab 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -14,7 +14,6 @@ blink_platform_sources("scheduler") {
"common/cooperative_scheduling_manager.cc",
"common/dummy_schedulers.cc",
"common/event_loop.cc",
- "common/features.cc",
"common/features.h",
"common/frame_or_worker_scheduler.cc",
"common/idle_helper.cc",
@@ -69,6 +68,8 @@ blink_platform_sources("scheduler") {
"main_thread/compositor_priority_experiments.h",
"main_thread/deadline_task_runner.cc",
"main_thread/deadline_task_runner.h",
+ "main_thread/find_in_page_budget_pool_controller.cc",
+ "main_thread/find_in_page_budget_pool_controller.h",
"main_thread/frame_origin_type.cc",
"main_thread/frame_origin_type.h",
"main_thread/frame_scheduler_impl.cc",
@@ -90,6 +91,8 @@ blink_platform_sources("scheduler") {
"main_thread/main_thread_task_queue.h",
"main_thread/memory_purge_manager.cc",
"main_thread/memory_purge_manager.h",
+ "main_thread/non_waking_time_domain.cc",
+ "main_thread/non_waking_time_domain.h",
"main_thread/page_scheduler_impl.cc",
"main_thread/page_scheduler_impl.h",
"main_thread/page_visibility_state.cc",
@@ -114,6 +117,8 @@ blink_platform_sources("scheduler") {
"main_thread/web_scheduling_task_queue_impl.cc",
"main_thread/web_scheduling_task_queue_impl.h",
"main_thread/web_scoped_virtual_time_pauser.cc",
+ "main_thread/widget_scheduler.cc",
+ "main_thread/widget_scheduler.h",
"public/aggregated_metric_reporter.h",
"public/cooperative_scheduling_manager.h",
"public/dummy_schedulers.h",
@@ -188,6 +193,8 @@ jumbo_source_set("test_support") {
"test/test_queueing_time_estimator_client.cc",
"test/test_queueing_time_estimator_client.h",
"test/web_fake_thread_scheduler.cc",
+ "test/web_fake_widget_scheduler.cc",
+ "test/web_fake_widget_scheduler.h",
]
deps = [
@@ -232,7 +239,6 @@ jumbo_source_set("unit_tests") {
"main_thread/queueing_time_estimator_unittest.cc",
"main_thread/render_widget_signals_unittest.cc",
"main_thread/user_model_unittest.cc",
- "worker/compositor_thread_scheduler_unittest.cc",
"worker/worker_scheduler_proxy_unittest.cc",
"worker/worker_scheduler_unittest.cc",
"worker/worker_thread_scheduler_unittest.cc",
@@ -253,9 +259,7 @@ jumbo_source_set("unit_tests") {
source_set("perf_tests") {
testonly = true
- sources = [
- "test/queueing_time_estimator_perf_test.cc",
- ]
+ sources = [ "test/queueing_time_estimator_perf_test.cc" ]
deps = [
"//base",
@@ -327,7 +331,5 @@ fuzzer_test("sequence_manager_fuzzer") {
}
proto_library("sequence_manager_test_description_proto") {
- sources = [
- "test/fuzzer/proto/sequence_manager_test_description.proto",
- ]
+ sources = [ "test/fuzzer/proto/sequence_manager_test_description.proto" ]
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
index a42789826bd..09f3deab389 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
@@ -52,7 +52,6 @@ include_rules = [
"+services/metrics",
"+third_party/blink/renderer/platform/bindings/parkable_string_manager.h",
- "+third_party/blink/renderer/platform/instrumentation/histogram.h",
"+third_party/blink/renderer/platform/instrumentation",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/runtime_enabled_features.h",
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/OWNERS b/chromium/third_party/blink/renderer/platform/scheduler/OWNERS
index 3df140deab0..a1de77fc540 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/OWNERS
@@ -1,6 +1,5 @@
# LON scheduling team
altimin@chromium.org
-alexclarke@chromium.org
carlscab@google.com
rmcilroy@chromium.org
skyostil@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
index 0413fe7b99a..f6a029de1f6 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
@@ -47,15 +47,17 @@ CooperativeSchedulingManager::CooperativeSchedulingManager()
}
void CooperativeSchedulingManager::EnterAllowedStackScope() {
- TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", "PreemptionAllowedStackScope",
- this);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("renderer.scheduler",
+ "PreemptionAllowedStackScope",
+ TRACE_ID_LOCAL(this));
allowed_stack_scope_depth_++;
}
void CooperativeSchedulingManager::LeaveAllowedStackScope() {
- TRACE_EVENT_ASYNC_END0("renderer.scheduler", "PreemptionAllowedStackScope",
- this);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+ "PreemptionAllowedStackScope",
+ TRACE_ID_LOCAL(this));
allowed_stack_scope_depth_--;
DCHECK_GE(allowed_stack_scope_depth_, 0);
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
index 4633243ee58..c456a695bac 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -37,8 +37,8 @@ class DummyFrameScheduler : public FrameScheduler {
bool IsPageVisible() const override { return true; }
void SetPaused(bool) override {}
void SetShouldReportPostedTasksWhenDisabled(bool) override {}
- void SetCrossOrigin(bool) override {}
- bool IsCrossOrigin() const override { return false; }
+ void SetCrossOriginToMainFrame(bool) override {}
+ bool IsCrossOriginToMainFrame() const override { return false; }
void SetIsAdFrame() override {}
bool IsAdFrame() const override { return false; }
void TraceUrlChange(const String&) override {}
@@ -175,6 +175,10 @@ class DummyThreadScheduler : public ThreadScheduler {
return base::ThreadTaskRunnerHandle::Get();
}
+ scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override {
+ return base::ThreadTaskRunnerHandle::Get();
+ }
+
std::unique_ptr<PageScheduler> CreatePageScheduler(
PageScheduler::Delegate*) override {
return std::make_unique<DummyPageScheduler>();
@@ -231,11 +235,6 @@ class DummyWebThreadScheduler : public WebThreadScheduler,
return base::ThreadTaskRunnerHandle::Get();
}
- scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override {
- DCHECK(WTF::IsMainThread());
- return base::ThreadTaskRunnerHandle::Get();
- }
-
scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override {
DCHECK(WTF::IsMainThread());
return base::ThreadTaskRunnerHandle::Get();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc
deleted file mode 100644
index b49ffd20c5b..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/common/features.h"
-
-namespace blink {
-namespace scheduler {
-
-// Field trial parameters associated with |kThrottleAndFreezeTaskTypes| feature.
-// These override the throttleable and freezable QueueTraits bits for the tasks
-// specified in the parameters. The parameters are comma separated lists, of the
-// the form: "throttleable": "name1,name2", "freezable": "name1,name3". The
-// names should be those returned by TaskTypeNames::TaskTypeToString().
-const char kThrottleableTaskTypesListParam[] = "ThrottleableTasks";
-const char kFreezableTaskTypesListParam[] = "FreezableTasks";
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/features.h b/chromium/third_party/blink/renderer/platform/scheduler/common/features.h
index b65ab55a0a4..6f12fc5f39a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/features.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/features.h
@@ -12,9 +12,6 @@
namespace blink {
namespace scheduler {
-const base::Feature kHighPriorityInputOnMainThread{
- "BlinkSchedulerHighPriorityInput", base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kHighPriorityInputOnCompositorThread{
"BlinkSchedulerHighPriorityInputOnCompositorThread",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -22,6 +19,10 @@ const base::Feature kHighPriorityInputOnCompositorThread{
const base::Feature kDedicatedWorkerThrottling{
"BlinkSchedulerWorkerThrottling", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kBestEffortPriorityForFindInPage{
+ "BlinkSchedulerBestEffortPriorityForFindInPage",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// COMPOSITING PRIORITY EXPERIMENT CONTROLS
// Enables experiment to increase priority of the compositing tasks during
@@ -76,7 +77,7 @@ const base::Feature kVeryHighPriorityForCompositingAlternating{
// to kNormalPriority.
const base::Feature kVeryHighPriorityForCompositingAfterDelay{
"BlinkSchedulerVeryHighPriorityForCompositingAfterDelay",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Param for kVeryHighPriorityForCompositingAfterDelay experiment. How long
// in ms the compositor will wait to be prioritized if no compositor tasks run.
@@ -197,32 +198,11 @@ const base::Feature kLowPriorityForCrossOriginOnlyWhenLoading{
"BlinkSchedulerLowPriorityForCrossOriginOnlyWhenLoading",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Enable setting throttleable and freezable task types from field trial
-// parameters.
-const base::Feature kThrottleAndFreezeTaskTypes{
- "ThrottleAndFreezeTaskTypes", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Prioritizes loading and compositing tasks while loading.
const base::Feature kPrioritizeCompositingAndLoadingDuringEarlyLoading{
"PrioritizeCompositingAndLoadingDuringEarlyLoading",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Parameters for |kThrottleAndFreezeTaskTypes|.
-extern const char PLATFORM_EXPORT kThrottleableTaskTypesListParam[];
-extern const char PLATFORM_EXPORT kFreezableTaskTypesListParam[];
-
-// If enabled, the scheduler will bypass the priority-based anti-starvation
-// logic that prevents indefinite starvation of lower priority tasks in the
-// presence of higher priority tasks by occasionally selecting lower
-// priority task queues over higher priority task queues.
-//
-// Note: this does not affect the anti-starvation logic that is in place for
-// preventing delayed tasks from starving immediate tasks, which is always
-// enabled.
-const base::Feature kBlinkSchedulerDisableAntiStarvationForPriorities{
- "BlinkSchedulerDisableAntiStarvationForPriorities",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enable setting high priority database task type from field trial parameters.
const base::Feature kHighPriorityDatabaseTaskType{
"HighPriorityDatabaseTaskType", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
index 23246956a95..4f769b7a650 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
@@ -439,9 +439,15 @@ void IdleHelper::State::TraceEventIdlePeriodStateChange(
!new_running_idle_task) {
running_idle_task_for_tracing_ = false;
if (!idle_period_deadline_.is_null() && now > idle_period_deadline_) {
- TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(
- "renderer.scheduler", idle_period_tracing_name_, this,
- "DeadlineOverrun",
+ if (last_sub_trace_event_name_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+ last_sub_trace_event_name_,
+ TRACE_ID_LOCAL(this));
+ }
+ last_sub_trace_event_name_ = "DeadlineOverrun";
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "renderer.scheduler", last_sub_trace_event_name_,
+ TRACE_ID_LOCAL(this),
std::max(idle_period_deadline_, last_idle_task_trace_time_));
}
}
@@ -449,35 +455,46 @@ void IdleHelper::State::TraceEventIdlePeriodStateChange(
if (IsInIdlePeriod(new_state)) {
if (!idle_period_trace_event_started_) {
idle_period_trace_event_started_ = true;
- TRACE_EVENT_ASYNC_BEGIN1("renderer.scheduler", idle_period_tracing_name_,
- this, "idle_period_length_ms",
- (new_deadline - now).InMillisecondsF());
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "renderer.scheduler", idle_period_tracing_name_, TRACE_ID_LOCAL(this),
+ "idle_period_length_ms", (new_deadline - now).InMillisecondsF());
}
+ const char* new_sub_trace_event_name = nullptr;
+
if (new_running_idle_task) {
last_idle_task_trace_time_ = now;
running_idle_task_for_tracing_ = true;
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "RunningIdleTask");
+ new_sub_trace_event_name = "RunningIdleTask";
} else if (new_state == IdlePeriodState::kInShortIdlePeriod) {
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "ShortIdlePeriod");
+ new_sub_trace_event_name = "ShortIdlePeriod";
} else if (IsInLongIdlePeriod(new_state) &&
new_state != IdlePeriodState::kInLongIdlePeriodPaused) {
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "LongIdlePeriod");
+ new_sub_trace_event_name = "LongIdlePeriod";
} else if (new_state == IdlePeriodState::kInLongIdlePeriodPaused) {
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "LongIdlePeriodPaused");
+ new_sub_trace_event_name = "LongIdlePeriodPaused";
+ }
+
+ if (new_sub_trace_event_name) {
+ if (last_sub_trace_event_name_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+ last_sub_trace_event_name_,
+ TRACE_ID_LOCAL(this));
+ }
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+ "renderer.scheduler", new_sub_trace_event_name, TRACE_ID_LOCAL(this));
+ last_sub_trace_event_name_ = new_sub_trace_event_name;
}
} else if (idle_period_trace_event_started_) {
+ if (last_sub_trace_event_name_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+ last_sub_trace_event_name_,
+ TRACE_ID_LOCAL(this));
+ last_sub_trace_event_name_ = nullptr;
+ }
+ TRACE_EVENT_NESTABLE_ASYNC_END0(
+ "renderer.scheduler", idle_period_tracing_name_, TRACE_ID_LOCAL(this));
idle_period_trace_event_started_ = false;
- TRACE_EVENT_ASYNC_END0("renderer.scheduler", idle_period_tracing_name_,
- this);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
index aa80c6a2e39..51c7593d95e 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
@@ -195,6 +195,7 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
bool idle_period_trace_event_started_;
bool running_idle_task_for_tracing_;
const char* idle_period_tracing_name_;
+ const char* last_sub_trace_event_name_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(State);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
index 8d6f03efff5..5110c90ee31 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
@@ -172,26 +172,12 @@ class IdleHelperForTest : public IdleHelper, public IdleHelper::Delegate {
class BaseIdleHelperTest : public testing::Test {
public:
- BaseIdleHelperTest(
- std::unique_ptr<base::MessageLoop> message_loop,
+ explicit BaseIdleHelperTest(
base::TimeDelta required_quiescence_duration_before_long_idle_period)
- : message_loop_(std::move(message_loop)),
- test_task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ : test_task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::TestMockTimeTaskRunner::Type::kStandalone)) {
- if (!message_loop_) {
- sequence_manager_ =
- base::sequence_manager::SequenceManagerForTest::Create(
- nullptr, test_task_runner_,
- test_task_runner_->GetMockTickClock());
- } else {
- // It's okay to use |test_task_runner_| just as a mock clock because
- // it isn't bound to thread and all tasks will go through a MessageLoop.
- sequence_manager_ =
- base::sequence_manager::SequenceManagerForTest::CreateOnCurrentThread(
- base::sequence_manager::SequenceManager::Settings::Builder()
- .SetTickClock(test_task_runner_->GetMockTickClock())
- .Build());
- }
+ sequence_manager_ = base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock());
scheduler_helper_ = std::make_unique<NonMainThreadSchedulerHelper>(
sequence_manager_.get(), nullptr, TaskType::kInternalTest);
idle_helper_ = std::make_unique<IdleHelperForTest>(
@@ -275,7 +261,6 @@ class BaseIdleHelperTest : public testing::Test {
return idle_helper_->idle_queue_;
}
- std::unique_ptr<base::MessageLoop> message_loop_;
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
std::unique_ptr<SequenceManager> sequence_manager_;
std::unique_ptr<NonMainThreadSchedulerHelper> scheduler_helper_;
@@ -289,7 +274,7 @@ class BaseIdleHelperTest : public testing::Test {
class IdleHelperTest : public BaseIdleHelperTest {
public:
- IdleHelperTest() : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
+ IdleHelperTest() : BaseIdleHelperTest(base::TimeDelta()) {}
~IdleHelperTest() override = default;
@@ -400,7 +385,7 @@ TEST_F(IdleHelperTest, TestIdleTaskExceedsDeadline) {
class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest {
public:
IdleHelperTestWithIdlePeriodObserver()
- : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
+ : BaseIdleHelperTest(base::TimeDelta()) {}
~IdleHelperTestWithIdlePeriodObserver() override = default;
@@ -785,7 +770,6 @@ class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest {
IdleHelperWithQuiescencePeriodTest()
: BaseIdleHelperTest(
- nullptr,
base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs)) {}
~IdleHelperWithQuiescencePeriodTest() override = default;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc
index d26f6d7ac75..aab5cf3e5cf 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc
@@ -7,8 +7,6 @@
PollableThreadSafeFlag::PollableThreadSafeFlag(base::Lock* write_lock_)
: flag_(false), write_lock_(write_lock_) {}
-PollableThreadSafeFlag::~PollableThreadSafeFlag() = default;
-
void PollableThreadSafeFlag::SetWhileLocked(bool value) {
write_lock_->AssertAcquired();
base::subtle::Release_Store(&flag_, value);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
index a78dc2bb7ff..1fdd4a2eefb 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
@@ -21,7 +21,6 @@ class PollableThreadSafeFlag {
public:
explicit PollableThreadSafeFlag(base::Lock* write_lock);
- ~PollableThreadSafeFlag();
// Set the flag. May only be called if |write_lock| is held.
void SetWhileLocked(bool value);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
index ef55b44c5ee..c751d9ccc24 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -41,7 +41,7 @@ void SchedulerHelper::InitDefaultQueues(
DCHECK(sequence_manager_);
sequence_manager_->SetDefaultTaskRunner(default_task_runner_);
- blink_task_executor_.emplace(default_task_runner_, sequence_manager_);
+ simple_task_executor_.emplace(default_task_runner_);
}
SchedulerHelper::~SchedulerHelper() {
@@ -182,18 +182,5 @@ bool SchedulerHelper::HasCPUTimingForEachTask() const {
return false;
}
-SchedulerHelper::BlinkTaskExecutor::BlinkTaskExecutor(
- scoped_refptr<base::SingleThreadTaskRunner> default_task_queue,
- base::sequence_manager::SequenceManager* sequence_manager)
- : base::SimpleTaskExecutor(sequence_manager, std::move(default_task_queue)),
- sequence_manager_(sequence_manager) {}
-
-SchedulerHelper::BlinkTaskExecutor::~BlinkTaskExecutor() = default;
-
-const scoped_refptr<base::SequencedTaskRunner>&
-SchedulerHelper::BlinkTaskExecutor::GetContinuationTaskRunner() {
- return sequence_manager_->GetTaskRunnerForCurrentTask();
-}
-
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
index 52b84746c4b..3f2267ef8ec 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -130,29 +130,12 @@ class PLATFORM_EXPORT SchedulerHelper
private:
friend class SchedulerHelperTest;
- // Like SimpleTaskExecutor except it knows how to get the current task runner
- // from the SequenceManager to implement GetContinuationTaskRunner.
- class BlinkTaskExecutor : public base::SimpleTaskExecutor {
- public:
- BlinkTaskExecutor(
- scoped_refptr<base::SingleThreadTaskRunner> default_task_queue,
- base::sequence_manager::SequenceManager* sequence_manager);
-
- ~BlinkTaskExecutor() override;
-
- // base::TaskExecutor implementation.
- const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner()
- override;
-
- private:
- base::sequence_manager::SequenceManager* sequence_manager_; // NOT OWNED
- };
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
Observer* observer_; // NOT OWNED
UkmTaskSampler ukm_task_sampler_;
- base::Optional<BlinkTaskExecutor> blink_task_executor_;
+ base::Optional<base::SimpleTaskExecutor> simple_task_executor_;
DISALLOW_COPY_AND_ASSIGN(SchedulerHelper);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
index 24d577ddcd3..ca7327cff8f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
@@ -13,15 +13,18 @@ bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) {
case Feature::kWebSocket:
case Feature::kWebRTC:
case Feature::kDedicatedWorkerOrWorklet:
- case Feature::kOutstandingNetworkRequest:
+ case Feature::kOutstandingNetworkRequestFetch:
+ case Feature::kOutstandingNetworkRequestXHR:
+ case Feature::kOutstandingNetworkRequestOthers:
case Feature::kOutstandingIndexedDBTransaction:
- case Feature::kHasScriptableFramesInMultipleTabs:
case Feature::kBroadcastChannel:
case Feature::kIndexedDBConnection:
case Feature::kWebGL:
case Feature::kWebVR:
case Feature::kWebXR:
case Feature::kSharedWorker:
+ case Feature::kWebHID:
+ case Feature::kWebShare:
return false;
case Feature::kMainResourceHasCacheControlNoStore:
case Feature::kMainResourceHasCacheControlNoCache:
@@ -44,6 +47,10 @@ bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) {
case Feature::kRequestedBackForwardCacheBlockedSensors:
case Feature::kRequestedBackgroundWorkPermission:
case Feature::kWebLocks:
+ case Feature::kWakeLock:
+ case Feature::kRequestedStorageAccessGrant:
+ case Feature::kWebNfc:
+ case Feature::kWebFileSystem:
return true;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
index 920153dc8b1..97dbeaa9d3b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
@@ -61,6 +61,11 @@ SimpleThreadScheduler::DeprecatedDefaultTaskRunner() {
return base::ThreadTaskRunnerHandle::Get();
}
+scoped_refptr<base::SingleThreadTaskRunner>
+SimpleThreadScheduler::NonWakingTaskRunner() {
+ return base::ThreadTaskRunnerHandle::Get();
+}
+
std::unique_ptr<PageScheduler> SimpleThreadScheduler::CreatePageScheduler(
PageScheduler::Delegate* delegate) {
return nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
index 35c83b2c291..1111310914d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
@@ -55,6 +55,7 @@ class SimpleThreadScheduler : public ThreadScheduler {
scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner()
override;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
index c184e225ab1..655b96a1802 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
@@ -106,6 +106,9 @@ void ThreadCPUThrottler::ThrottlingThread::InstallSignalHandler() {
struct sigaction sa;
sa.sa_handler = &HandleSignal;
sigemptyset(&sa.sa_mask);
+ // Block SIGPROF while our handler is running so that the V8 CPU profiler
+ // doesn't try to sample the stack while our signal handler is active.
+ sigaddset(&sa.sa_mask, SIGPROF);
sa.sa_flags = SA_RESTART;
signal_handler_installed_ =
(sigaction(SIGUSR2, &sa, &old_signal_handler_) == 0);
@@ -164,15 +167,16 @@ void ThreadCPUThrottler::ThrottlingThread::Throttle() {
}
void ThreadCPUThrottler::ThrottlingThread::Start() {
-#ifdef USE_SIGNALS
+#if defined(USE_SIGNALS) || defined(OS_WIN)
+#if defined(USE_SIGNALS)
InstallSignalHandler();
-#elif !defined(OS_WIN)
- LOG(ERROR) << "CPU throttling is not supported.";
- return;
#endif
if (!base::PlatformThread::Create(0, this, &throttling_thread_handle_)) {
LOG(ERROR) << "Failed to create throttling thread.";
}
+#else
+ LOG(ERROR) << "CPU throttling is not supported.";
+#endif
}
void ThreadCPUThrottler::ThrottlingThread::Sleep(base::TimeDelta duration) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
index 0dc678298e4..9570477f5f0 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
@@ -602,9 +602,6 @@ bool TaskQueueThrottler::Metadata::DecrementRefCount() {
return false;
}
-void TaskQueueThrottler::Metadata::OnPostTask(base::Location from_here,
- base::TimeDelta delay) {}
-
void TaskQueueThrottler::Metadata::OnQueueNextWakeUpChanged(
base::TimeTicks wake_up) {
throttler_->OnQueueNextWakeUpChanged(queue_, wake_up);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
index 449e843172b..ad6775949d2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
@@ -143,7 +143,6 @@ class PLATFORM_EXPORT TaskQueueThrottler : public BudgetPoolController {
bool DecrementRefCount();
// TaskQueue::Observer implementation:
- void OnPostTask(base::Location from_here, base::TimeDelta delay) override;
void OnQueueNextWakeUpChanged(base::TimeTicks wake_up) override;
size_t throttling_ref_count() const { return throttling_ref_count_; }
@@ -157,6 +156,8 @@ class PLATFORM_EXPORT TaskQueueThrottler : public BudgetPoolController {
TaskQueueThrottler* const throttler_;
size_t throttling_ref_count_ = 0;
HashSet<BudgetPool*> budget_pools_;
+
+ DISALLOW_COPY_AND_ASSIGN(Metadata);
};
using TaskQueueMap =
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
index e957afa1292..d82b092c265 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
@@ -100,7 +100,7 @@ class StateTracer {
~StateTracer() {
if (slice_is_open_)
- TRACE_EVENT_ASYNC_END0(category, name_, object_);
+ TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(object_));
}
// String will be copied before leaving this function.
@@ -122,22 +122,19 @@ class StateTracer {
private:
void TraceImpl(const char* state, bool need_copy) {
if (slice_is_open_) {
- TRACE_EVENT_ASYNC_END0(category, name_, object_);
+ TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(object_));
slice_is_open_ = false;
}
if (!state || !is_enabled())
return;
- // Trace viewer logic relies on subslice starting at the exact same time
- // as the async event.
- base::TimeTicks now = TRACE_TIME_TICKS_NOW();
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category, name_, object_, now);
if (need_copy) {
- TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category, name_, object_,
- TRACE_STR_COPY(state), now);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category, name_,
+ TRACE_ID_LOCAL(object_), "state",
+ TRACE_STR_COPY(state));
} else {
- TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category, name_, object_,
- state, now);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ category, name_, TRACE_ID_LOCAL(object_), "state", state);
}
slice_is_open_ = true;
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
index ac27cae4d42..641f84cc4b8 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
@@ -10,6 +10,8 @@
#include "base/message_loop/message_pump_type.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "third_party/blink/public/common/input/web_input_event_attribution.h"
+#include "third_party/blink/public/platform/scheduler/web_widget_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
@@ -29,9 +31,6 @@ WebThreadScheduler::CreateMainThreadScheduler(
.SetMessagePumpType(base::MessagePumpType::DEFAULT)
.SetRandomisedSamplingEnabled(true)
.SetAddQueueTimeToTasks(true)
- .SetAntiStarvationLogicForPrioritiesDisabled(
- base::FeatureList::IsEnabled(
- kBlinkSchedulerDisableAntiStarvationForPriorities))
.Build();
auto sequence_manager =
message_pump
@@ -74,12 +73,6 @@ WebThreadScheduler::CompositorTaskRunner() {
}
scoped_refptr<base::SingleThreadTaskRunner>
-WebThreadScheduler::InputTaskRunner() {
- NOTREACHED();
- return nullptr;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
WebThreadScheduler::IPCTaskRunner() {
NOTREACHED();
return nullptr;
@@ -102,6 +95,12 @@ std::unique_ptr<Thread> WebThreadScheduler::CreateMainThread() {
return nullptr;
}
+std::unique_ptr<WebWidgetScheduler>
+WebThreadScheduler::CreateWidgetScheduler() {
+ NOTREACHED();
+ return nullptr;
+}
+
std::unique_ptr<WebRenderWidgetSchedulingState>
WebThreadScheduler::NewRenderWidgetSchedulingState() {
NOTREACHED();
@@ -131,12 +130,14 @@ void WebThreadScheduler::DidHandleInputEventOnCompositorThread(
}
void WebThreadScheduler::WillPostInputEventToMainThread(
- WebInputEvent::Type web_input_event_type) {
+ WebInputEvent::Type web_input_event_type,
+ const WebInputEventAttribution& attribution) {
NOTREACHED();
}
void WebThreadScheduler::WillHandleInputEventOnMainThread(
- WebInputEvent::Type web_input_event_type) {
+ WebInputEvent::Type web_input_event_type,
+ const WebInputEventAttribution& attribution) {
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/worker_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/worker_pool.cc
index 50634f1db7f..c5492c3f3cf 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/worker_pool.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/worker_pool.cc
@@ -5,24 +5,22 @@
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
#include "base/location.h"
-#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
namespace blink {
namespace worker_pool {
void PostTask(const base::Location& location, CrossThreadOnceClosure closure) {
- PostTask(
- location,
- {base::ThreadPool(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- std::move(closure));
+ PostTask(location, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ std::move(closure));
}
void PostTask(const base::Location& location,
const base::TaskTraits& traits,
CrossThreadOnceClosure closure) {
- base::PostTask(location, traits,
- ConvertToBaseOnceCallback(std::move(closure)));
+ base::ThreadPool::PostTask(location, traits,
+ ConvertToBaseOnceCallback(std::move(closure)));
}
} // namespace worker_pool
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
index 8564cbca5b1..f755622d8dc 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
@@ -15,17 +15,14 @@ CompositorPriorityExperiments::CompositorPriorityExperiments(
MainThreadSchedulerImpl* scheduler)
: scheduler_(scheduler),
experiment_(GetExperimentFromFeatureList()),
+ last_compositor_task_time_(scheduler_->GetTickClock()->NowTicks()),
prioritize_compositing_after_delay_length_(
base::TimeDelta::FromMilliseconds(kCompositingDelayLength.Get())),
stop_signal_(base::FeatureList::IsEnabled(
kPrioritizeCompositingUntilBeginMainFrame)
? StopSignalType::kBeginMainFrameTask
- : StopSignalType::kAnyCompositorTask) {
- do_prioritize_compositing_after_delay_callback_.Reset(base::BindRepeating(
- &CompositorPriorityExperiments::DoPrioritizeCompositingAfterDelay,
- base::Unretained(this)));
-}
-CompositorPriorityExperiments::~CompositorPriorityExperiments() {}
+ : StopSignalType::kAnyCompositorTask) {}
+CompositorPriorityExperiments::~CompositorPriorityExperiments() = default;
CompositorPriorityExperiments::Experiment
CompositorPriorityExperiments::GetExperimentFromFeatureList() {
@@ -38,11 +35,11 @@ CompositorPriorityExperiments::GetExperimentFromFeatureList() {
kVeryHighPriorityForCompositingAlternating)) {
return Experiment::kVeryHighPriorityForCompositingAlternating;
} else if (base::FeatureList::IsEnabled(
- kVeryHighPriorityForCompositingAfterDelay)) {
- return Experiment::kVeryHighPriorityForCompositingAfterDelay;
- } else if (base::FeatureList::IsEnabled(
kVeryHighPriorityForCompositingBudget)) {
return Experiment::kVeryHighPriorityForCompositingBudget;
+ } else if (base::FeatureList::IsEnabled(
+ kVeryHighPriorityForCompositingAfterDelay)) {
+ return Experiment::kVeryHighPriorityForCompositingAfterDelay;
} else {
return Experiment::kNone;
}
@@ -75,15 +72,7 @@ QueuePriority CompositorPriorityExperiments::GetCompositorPriority() const {
}
}
-void CompositorPriorityExperiments::DoPrioritizeCompositingAfterDelay() {
- delay_compositor_priority_ = QueuePriority::kVeryHighPriority;
- scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
-}
-
void CompositorPriorityExperiments::OnMainThreadSchedulerInitialized() {
- if (experiment_ == Experiment::kVeryHighPriorityForCompositingAfterDelay) {
- PostPrioritizeCompositingAfterDelayTask();
- }
if (experiment_ == Experiment::kVeryHighPriorityForCompositingBudget) {
budget_pool_controller_.reset(new CompositorBudgetPoolController(
this, scheduler_, scheduler_->CompositorTaskQueue().get(),
@@ -102,14 +91,6 @@ void CompositorPriorityExperiments::OnWillBeginMainFrame() {
will_begin_main_frame_ = true;
}
-void CompositorPriorityExperiments::PostPrioritizeCompositingAfterDelayTask() {
- DCHECK_EQ(experiment_, Experiment::kVeryHighPriorityForCompositingAfterDelay);
-
- scheduler_->ControlTaskRunner()->PostDelayedTask(
- FROM_HERE, do_prioritize_compositing_after_delay_callback_.GetCallback(),
- prioritize_compositing_after_delay_length_);
-}
-
void CompositorPriorityExperiments::OnTaskCompleted(
MainThreadTaskQueue* queue,
QueuePriority current_compositor_priority,
@@ -150,12 +131,15 @@ void CompositorPriorityExperiments::OnTaskCompleted(
case Experiment::kVeryHighPriorityForCompositingAfterDelay:
if (have_seen_stop_signal) {
delay_compositor_priority_ = QueuePriority::kNormalPriority;
- do_prioritize_compositing_after_delay_callback_.Cancel();
- PostPrioritizeCompositingAfterDelayTask();
-
- if (current_compositor_priority != delay_compositor_priority_)
- scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
+ last_compositor_task_time_ = task_timing->end_time();
+ } else {
+ if (task_timing->end_time() - last_compositor_task_time_ >=
+ prioritize_compositing_after_delay_length_) {
+ delay_compositor_priority_ = QueuePriority::kVeryHighPriority;
+ }
}
+ if (current_compositor_priority != delay_compositor_priority_)
+ scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
return;
case Experiment::kVeryHighPriorityForCompositingBudget:
budget_pool_controller_->OnTaskCompleted(queue, task_timing,
@@ -188,7 +172,7 @@ CompositorPriorityExperiments::CompositorBudgetPoolController::
TraceableVariableController* tracing_controller,
base::TimeDelta min_budget,
double budget_recovery_rate)
- : experiment_(experiment), tick_clock_(scheduler->GetTickClock()) {
+ : experiment_(experiment) {
DCHECK_EQ(compositor_queue->queue_type(),
MainThreadTaskQueue::QueueType::kCompositor);
base::TimeTicks now = scheduler->GetTickClock()->NowTicks();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h
index bb034bf4713..725d31d8f3f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h
@@ -93,16 +93,10 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
CompositorPriorityExperiments* experiment_;
std::unique_ptr<CPUTimeBudgetPool> compositor_budget_pool_;
bool is_exhausted_ = false;
-
- const base::TickClock* tick_clock_; // Not owned.
};
static Experiment GetExperimentFromFeatureList();
- void DoPrioritizeCompositingAfterDelay();
-
- void PostPrioritizeCompositingAfterDelayTask();
-
enum class StopSignalType { kAnyCompositorTask, kBeginMainFrameTask };
MainThreadSchedulerImpl* scheduler_; // Not owned.
@@ -113,7 +107,7 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
QueuePriority::kVeryHighPriority;
QueuePriority delay_compositor_priority_ = QueuePriority::kNormalPriority;
- CancelableClosureHolder do_prioritize_compositing_after_delay_callback_;
+ base::TimeTicks last_compositor_task_time_;
base::TimeDelta prioritize_compositing_after_delay_length_;
QueuePriority budget_compositor_priority_ = QueuePriority::kVeryHighPriority;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc
new file mode 100644
index 00000000000..3fc1cfd2f2b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc
@@ -0,0 +1,87 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h"
+
+#include "third_party/blink/renderer/platform/scheduler/common/features.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+// We will accumulate at most 1000ms for find-in-page budget.
+constexpr base::TimeDelta kFindInPageMaxBudget =
+ base::TimeDelta::FromSeconds(1);
+// At least 25% of the total CPU time will go to find-in-page tasks.
+// TODO(rakina): Experiment with this number to figure out the right percentage
+// for find-in-page. Currently this is following CompositorPriorityExperiments.
+const double kFindInPageBudgetRecoveryRate = 0.25;
+} // namespace
+
+const QueuePriority
+ FindInPageBudgetPoolController::kFindInPageBudgetNotExhaustedPriority;
+const QueuePriority
+ FindInPageBudgetPoolController::kFindInPageBudgetExhaustedPriority;
+
+FindInPageBudgetPoolController::FindInPageBudgetPoolController(
+ MainThreadSchedulerImpl* scheduler)
+ : scheduler_(scheduler),
+ best_effort_budget_experiment_enabled_(
+ base::FeatureList::IsEnabled(kBestEffortPriorityForFindInPage)) {
+ if (best_effort_budget_experiment_enabled_) {
+ task_priority_ = QueuePriority::kBestEffortPriority;
+ } else {
+ task_priority_ = kFindInPageBudgetNotExhaustedPriority;
+ }
+}
+
+FindInPageBudgetPoolController::~FindInPageBudgetPoolController() = default;
+
+void FindInPageBudgetPoolController::EnsureBudgetPoolInitialized() {
+ DCHECK(!best_effort_budget_experiment_enabled_);
+ if (find_in_page_budget_pool_)
+ return;
+ base::TimeTicks now = scheduler_->GetTickClock()->NowTicks();
+ find_in_page_budget_pool_.reset(new CPUTimeBudgetPool(
+ "FindInPageBudgetPool", this, &scheduler_->tracing_controller_, now));
+ // Set no minimum budget for find-in-page, so that we won't delay running
+ // find-in-page tasks when budget is available.
+ find_in_page_budget_pool_->SetMinBudgetLevelToRun(now, base::TimeDelta());
+ find_in_page_budget_pool_->SetMaxBudgetLevel(now, kFindInPageMaxBudget);
+ find_in_page_budget_pool_->SetTimeBudgetRecoveryRate(
+ now, kFindInPageBudgetRecoveryRate);
+}
+
+void FindInPageBudgetPoolController::OnTaskCompleted(
+ MainThreadTaskQueue* queue,
+ TaskQueue::TaskTiming* task_timing) {
+ if (!queue || best_effort_budget_experiment_enabled_)
+ return;
+ EnsureBudgetPoolInitialized();
+ if (queue->GetPrioritisationType() ==
+ MainThreadTaskQueue::QueueTraits::PrioritisationType::kFindInPage) {
+ find_in_page_budget_pool_->RecordTaskRunTime(
+ queue, task_timing->start_time(), task_timing->end_time());
+ }
+
+ bool is_exhausted = !find_in_page_budget_pool_->CanRunTasksAt(
+ task_timing->end_time(), false /* is_wake_up */);
+ QueuePriority task_priority = is_exhausted
+ ? kFindInPageBudgetExhaustedPriority
+ : kFindInPageBudgetNotExhaustedPriority;
+
+ if (task_priority != task_priority_) {
+ task_priority_ = task_priority;
+ // If the priority changed, we need to make sure all find-in-page task
+ // queues across all frames get updated. Note that UpdatePolicy will
+ // update all task queues for all frames, which is a bit overkill - this
+ // should probably be optimized in the future.
+ scheduler_->UpdatePolicy();
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h
new file mode 100644
index 00000000000..5fd8f296d48
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h
@@ -0,0 +1,67 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FIND_IN_PAGE_BUDGET_POOL_CONTROLLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FIND_IN_PAGE_BUDGET_POOL_CONTROLLER_H_
+
+#include "base/task/sequence_manager/task_queue.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+using TaskQueue = base::sequence_manager::TaskQueue;
+using QueuePriority = base::sequence_manager::TaskQueue::QueuePriority;
+
+class CPUTimeBudgetPool;
+class MainThreadSchedulerImpl;
+
+class PLATFORM_EXPORT FindInPageBudgetPoolController
+ : public BudgetPoolController {
+ public:
+ static constexpr auto kFindInPageBudgetNotExhaustedPriority =
+ QueuePriority::kVeryHighPriority;
+ static constexpr auto kFindInPageBudgetExhaustedPriority =
+ QueuePriority::kNormalPriority;
+
+ explicit FindInPageBudgetPoolController(MainThreadSchedulerImpl* scheduler);
+ ~FindInPageBudgetPoolController() override;
+
+ void OnTaskCompleted(MainThreadTaskQueue* queue,
+ MainThreadTaskQueue::TaskTiming* task_timing);
+
+ QueuePriority CurrentTaskPriority() { return task_priority_; }
+
+ // Unimplemented methods.
+ // TODO(crbug.com/1056512): Remove these functions once we factor out the
+ // budget calculating logic from BudgetPoolController.
+ void UpdateQueueSchedulingLifecycleState(base::TimeTicks now,
+ TaskQueue* queue) override {}
+ void AddQueueToBudgetPool(TaskQueue* queue,
+ BudgetPool* budget_pool) override {}
+ void RemoveQueueFromBudgetPool(TaskQueue* queue,
+ BudgetPool* budget_pool) override {}
+ void UnregisterBudgetPool(BudgetPool* budget_pool) override {}
+ bool IsThrottled(TaskQueue* queue) const override { return false; }
+
+ private:
+ // We need to call this from OnTaskCompleted, because PartitionAlloc might not
+ // be initialized yet when we got constructed.
+ // TODO(crbug.com/1058645): Initialize |find_in_page_budget_pool_| from the
+ // constructor and remove this function.
+ void EnsureBudgetPoolInitialized();
+
+ MainThreadSchedulerImpl* scheduler_; // Not owned.
+ std::unique_ptr<CPUTimeBudgetPool> find_in_page_budget_pool_;
+ QueuePriority task_priority_;
+ const bool best_effort_budget_experiment_enabled_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FIND_IN_PAGE_BUDGET_POOL_CONTROLLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc
index fa4f2fc7761..631724eda29 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc
@@ -16,10 +16,10 @@ FrameOriginType GetFrameOriginType(FrameScheduler* scheduler) {
if (scheduler->GetFrameType() == FrameScheduler::FrameType::kMainFrame)
return FrameOriginType::kMainFrame;
- if (scheduler->IsCrossOrigin()) {
- return FrameOriginType::kCrossOriginFrame;
+ if (scheduler->IsCrossOriginToMainFrame()) {
+ return FrameOriginType::kCrossOriginToMainFrame;
} else {
- return FrameOriginType::kSameOriginFrame;
+ return FrameOriginType::kSameOriginToMainFrame;
}
}
@@ -27,10 +27,10 @@ const char* FrameOriginTypeToString(FrameOriginType origin) {
switch (origin) {
case FrameOriginType::kMainFrame:
return "main-frame";
- case FrameOriginType::kSameOriginFrame:
- return "same-origin";
- case FrameOriginType::kCrossOriginFrame:
- return "cross-origin";
+ case FrameOriginType::kSameOriginToMainFrame:
+ return "same-origin-to-main-frame";
+ case FrameOriginType::kCrossOriginToMainFrame:
+ return "cross-origin-to-main-frame";
case FrameOriginType::kCount:
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h
index 4739e0e0fac..573ba2f4afd 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h
@@ -14,9 +14,10 @@ namespace scheduler {
// and should not be renumbered.
enum class FrameOriginType {
kMainFrame = 0,
- kSameOriginFrame = 1,
- kCrossOriginFrame = 2,
- kCount = 3
+ kSameOriginToMainFrame = 1,
+ kCrossOriginToMainFrame = 2,
+ // TODO(dcheng): Get rid of this and use the kMaxValue idiom.
+ kCount = 3,
};
FrameOriginType GetFrameOriginType(FrameScheduler* frame_scheduler);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 0e52953485d..2f15127c778 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -10,6 +10,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/blame_context.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -17,6 +18,7 @@
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
@@ -77,45 +79,6 @@ void UpdatePriority(MainThreadTaskQueue* task_queue) {
task_queue->SetQueuePriority(frame_scheduler->ComputePriority(task_queue));
}
-// Extract a substring from |source| from [start to end), trimming leading
-// whitespace.
-String ExtractAndTrimString(String source, size_t start, size_t end) {
- DCHECK(start < source.length());
- DCHECK(end <= source.length());
- DCHECK(start <= end);
- // Trim whitespace
- while (start < end && source[start] == ' ')
- ++start;
- if (start < end)
- return source.Substring(start, end - start);
- return "";
-}
-
-HashSet<String> TaskTypesFromFieldTrialParam(const char* param) {
- HashSet<String> result;
- String task_type_list =
- String::FromUTF8(base::GetFieldTrialParamValueByFeature(
- kThrottleAndFreezeTaskTypes, param));
- if (!task_type_list.length())
- return result;
- // Extract the individual names, separated by ",".
- size_t pos = 0, start = 0;
- while ((pos = task_type_list.find(',', start)) != kNotFound) {
- String task_type = ExtractAndTrimString(task_type_list, start, pos);
- // Not valid to start with "," or have ",," in the list.
- DCHECK(task_type.length());
- result.insert(task_type);
- start = pos + 1;
- }
- // Handle the last or only task type name.
- String task_type =
- ExtractAndTrimString(task_type_list, start, task_type_list.length());
- DCHECK(task_type.length());
- result.insert(task_type);
-
- return result;
-}
-
} // namespace
FrameSchedulerImpl::PauseSubresourceLoadingHandleImpl::
@@ -169,7 +132,7 @@ FrameSchedulerImpl::FrameSchedulerImpl(
PausedStateToString),
frame_origin_type_(frame_type == FrameType::kMainFrame
? FrameOriginType::kMainFrame
- : FrameOriginType::kSameOriginFrame,
+ : FrameOriginType::kSameOriginToMainFrame,
"FrameScheduler.Origin",
this,
&tracing_controller_,
@@ -321,16 +284,16 @@ bool FrameSchedulerImpl::IsFrameVisible() const {
return frame_visible_;
}
-void FrameSchedulerImpl::SetCrossOrigin(bool cross_origin) {
+void FrameSchedulerImpl::SetCrossOriginToMainFrame(bool cross_origin) {
DCHECK(parent_page_scheduler_);
if (frame_origin_type_ == FrameOriginType::kMainFrame) {
DCHECK(!cross_origin);
return;
}
if (cross_origin) {
- frame_origin_type_ = FrameOriginType::kCrossOriginFrame;
+ frame_origin_type_ = FrameOriginType::kCrossOriginToMainFrame;
} else {
- frame_origin_type_ = FrameOriginType::kSameOriginFrame;
+ frame_origin_type_ = FrameOriginType::kSameOriginToMainFrame;
}
UpdatePolicy();
}
@@ -344,8 +307,8 @@ bool FrameSchedulerImpl::IsAdFrame() const {
return is_ad_frame_;
}
-bool FrameSchedulerImpl::IsCrossOrigin() const {
- return frame_origin_type_ == FrameOriginType::kCrossOriginFrame;
+bool FrameSchedulerImpl::IsCrossOriginToMainFrame() const {
+ return frame_origin_type_ == FrameOriginType::kCrossOriginToMainFrame;
}
void FrameSchedulerImpl::TraceUrlChange(const String& url) {
@@ -370,42 +333,8 @@ FrameScheduler::FrameType FrameSchedulerImpl::GetFrameType() const {
return frame_type_;
}
-void FrameSchedulerImpl::InitializeTaskTypeQueueTraitsMap(
- FrameTaskTypeToQueueTraitsArray& frame_task_types_to_queue_traits) {
- DCHECK_EQ(frame_task_types_to_queue_traits.size(),
- static_cast<size_t>(TaskType::kCount));
- // Using std set and strings here because field trial parameters are std
- // strings, and we cannot use WTF strings as Blink is not yet initialized.
- HashSet<String> throttleable_task_type_names;
- HashSet<String> freezable_task_type_names;
- if (base::FeatureList::IsEnabled(kThrottleAndFreezeTaskTypes)) {
- throttleable_task_type_names =
- TaskTypesFromFieldTrialParam(kThrottleableTaskTypesListParam);
- freezable_task_type_names =
- TaskTypesFromFieldTrialParam(kFreezableTaskTypesListParam);
- }
- for (size_t i = 0; i < static_cast<size_t>(TaskType::kCount); i++) {
- TaskType type = static_cast<TaskType>(i);
- base::Optional<QueueTraits> queue_traits =
- CreateQueueTraitsForTaskType(type);
- if (queue_traits && (!throttleable_task_type_names.IsEmpty() ||
- !freezable_task_type_names.IsEmpty())) {
- const char* task_type_name = TaskTypeNames::TaskTypeToString(type);
- if (!throttleable_task_type_names.Take(task_type_name).IsEmpty())
- queue_traits->SetCanBeThrottled(true);
- if (freezable_task_type_names.Take(task_type_name).IsEmpty())
- queue_traits->SetCanBeFrozen(true);
- }
- frame_task_types_to_queue_traits[i] = queue_traits;
- }
- // Protect against configuration errors.
- DCHECK(throttleable_task_type_names.IsEmpty());
- DCHECK(freezable_task_type_names.IsEmpty());
-}
-
// static
-base::Optional<QueueTraits> FrameSchedulerImpl::CreateQueueTraitsForTaskType(
- TaskType type) {
+QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) {
// TODO(haraken): Optimize the mapping from TaskTypes to task runners.
// TODO(sreejakshetty): Clean up the PrioritisationType QueueTrait and
// QueueType for kInternalContinueScriptLoading and kInternalContentCapture.
@@ -464,13 +393,15 @@ base::Optional<QueueTraits> FrameSchedulerImpl::CreateQueueTraitsForTaskType(
case TaskType::kInternalUserInteraction:
case TaskType::kInternalIntersectionObserver:
return PausableTaskQueueTraits();
+ case TaskType::kInternalFindInPage:
+ return FindInPageTaskQueueTraits();
case TaskType::kInternalContinueScriptLoading:
return PausableTaskQueueTraits().SetPrioritisationType(
QueueTraits::PrioritisationType::kVeryHigh);
case TaskType::kDatabaseAccess:
if (base::FeatureList::IsEnabled(kHighPriorityDatabaseTaskType)) {
return PausableTaskQueueTraits().SetPrioritisationType(
- QueueTraits::PrioritisationType::kHigh);
+ QueueTraits::PrioritisationType::kExperimentalDatabase);
} else {
return PausableTaskQueueTraits();
}
@@ -508,19 +439,22 @@ base::Optional<QueueTraits> FrameSchedulerImpl::CreateQueueTraitsForTaskType(
case TaskType::kWorkerThreadTaskQueueDefault:
case TaskType::kWorkerThreadTaskQueueV8:
case TaskType::kWorkerThreadTaskQueueCompositor:
+ case TaskType::kMainThreadTaskQueueNonWaking:
// The web scheduling API task types are used by WebSchedulingTaskQueues.
// The associated TaskRunner should be obtained by creating a
// WebSchedulingTaskQueue with CreateWebSchedulingTaskQueue().
case TaskType::kExperimentalWebScheduling:
case TaskType::kCount:
// Not a valid frame-level TaskType.
- return base::nullopt;
+ NOTREACHED();
+ return QueueTraits();
}
// This method is called for all values between 0 and kCount. TaskType,
// however, has numbering gaps, so even though all enumerated TaskTypes are
// handled in the switch and return a value, we fall through for some values
// of |type|.
- return base::nullopt;
+ NOTREACHED();
+ return QueueTraits();
}
scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
@@ -532,17 +466,8 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::GetTaskQueue(
TaskType type) {
- DCHECK_LT(static_cast<size_t>(type),
- main_thread_scheduler_->scheduling_settings()
- .frame_task_types_to_queue_traits.size());
- base::Optional<QueueTraits> queue_traits =
- main_thread_scheduler_->scheduling_settings()
- .frame_task_types_to_queue_traits[static_cast<size_t>(type)];
- // We don't have a QueueTraits mapping for |task_type| if it is not a
- // frame-level task type.
- DCHECK(queue_traits);
- return frame_task_queue_controller_->GetTaskQueue(
- queue_traits.value());
+ QueueTraits queue_traits = CreateQueueTraitsForTaskType(type);
+ return frame_task_queue_controller_->GetTaskQueue(queue_traits);
}
std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
@@ -638,6 +563,13 @@ WebScopedVirtualTimePauser FrameSchedulerImpl::CreateWebScopedVirtualTimePauser(
void FrameSchedulerImpl::ResetForNavigation() {
document_bound_weak_factory_.InvalidateWeakPtrs();
+ for (const auto& it : back_forward_cache_opt_out_counts_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0(
+ "renderer.scheduler", "ActiveSchedulerTrackedFeature",
+ TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
+ static_cast<int>(it.first)));
+ }
+
back_forward_cache_opt_out_counts_.clear();
back_forward_cache_opt_outs_.reset();
last_uploaded_active_features_ = 0;
@@ -650,13 +582,20 @@ void FrameSchedulerImpl::OnStartedUsingFeature(
if (policy.disable_aggressive_throttling)
OnAddedAggressiveThrottlingOptOut();
- if (policy.disable_back_forward_cache)
+ if (policy.disable_back_forward_cache) {
OnAddedBackForwardCacheOptOut(feature);
+ }
uint64_t new_mask = GetActiveFeaturesTrackedForBackForwardCacheMetricsMask();
- if (old_mask != new_mask)
+ if (old_mask != new_mask) {
NotifyDelegateAboutFeaturesAfterCurrentTask();
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "renderer.scheduler", "ActiveSchedulerTrackedFeature",
+ TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
+ static_cast<int>(feature)),
+ "feature", FeatureToString(feature));
+ }
}
void FrameSchedulerImpl::OnStoppedUsingFeature(
@@ -671,8 +610,13 @@ void FrameSchedulerImpl::OnStoppedUsingFeature(
uint64_t new_mask = GetActiveFeaturesTrackedForBackForwardCacheMetricsMask();
- if (old_mask != new_mask)
+ if (old_mask != new_mask) {
NotifyDelegateAboutFeaturesAfterCurrentTask();
+ TRACE_EVENT_NESTABLE_ASYNC_END0(
+ "renderer.scheduler", "ActiveSchedulerTrackedFeature",
+ TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
+ static_cast<int>(feature)));
+ }
}
void FrameSchedulerImpl::NotifyDelegateAboutFeaturesAfterCurrentTask() {
@@ -743,7 +687,7 @@ void FrameSchedulerImpl::AsValueInto(
base::trace_event::TracedValue* state) const {
state->SetBoolean("frame_visible", frame_visible_);
state->SetBoolean("page_visible", parent_page_scheduler_->IsPageVisible());
- state->SetBoolean("cross_origin", IsCrossOrigin());
+ state->SetBoolean("cross_origin_to_main_frame", IsCrossOriginToMainFrame());
state->SetString("frame_type",
frame_type_ == FrameScheduler::FrameType::kMainFrame
? "MainFrame"
@@ -892,7 +836,7 @@ bool FrameSchedulerImpl::ShouldThrottleTaskQueues() const {
if (!parent_page_scheduler_->IsPageVisible())
return true;
return RuntimeEnabledFeatures::TimerThrottlingForHiddenFramesEnabled() &&
- !frame_visible_ && IsCrossOrigin();
+ !frame_visible_ && IsCrossOriginToMainFrame();
}
void FrameSchedulerImpl::UpdateTaskQueueThrottling(
@@ -938,16 +882,12 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
// and add a range of new priorities less than low.
if (task_queue->web_scheduling_priority()) {
switch (task_queue->web_scheduling_priority().value()) {
- case WebSchedulingPriority::kImmediatePriority:
- return TaskQueue::QueuePriority::kHighestPriority;
- case WebSchedulingPriority::kHighPriority:
+ case WebSchedulingPriority::kUserBlockingPriority:
return TaskQueue::QueuePriority::kHighPriority;
- case WebSchedulingPriority::kDefaultPriority:
+ case WebSchedulingPriority::kUserVisiblePriority:
return TaskQueue::QueuePriority::kNormalPriority;
- case WebSchedulingPriority::kLowPriority:
+ case WebSchedulingPriority::kBackgroundPriority:
return TaskQueue::QueuePriority::kLowPriority;
- case WebSchedulingPriority::kIdlePriority:
- return TaskQueue::QueuePriority::kBestEffortPriority;
}
}
@@ -1022,7 +962,7 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
}
// Frame origin type experiment.
- if (IsCrossOrigin()) {
+ if (IsCrossOriginToMainFrame()) {
if (main_thread_scheduler_->scheduling_settings()
.low_priority_cross_origin ||
(main_thread_scheduler_->scheduling_settings()
@@ -1046,6 +986,21 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
return main_thread_scheduler_->compositor_priority();
}
+ if (task_queue->GetPrioritisationType() ==
+ MainThreadTaskQueue::QueueTraits::PrioritisationType::kFindInPage) {
+ return main_thread_scheduler_->find_in_page_priority();
+ }
+
+ if (task_queue->GetPrioritisationType() ==
+ MainThreadTaskQueue::QueueTraits::PrioritisationType::
+ kExperimentalDatabase) {
+ // TODO(shaseley): This decision should probably be based on Agent
+ // visibility. Consider changing this before shipping anything.
+ return parent_page_scheduler_->IsPageVisible()
+ ? TaskQueue::QueuePriority::kHighPriority
+ : TaskQueue::QueuePriority::kNormalPriority;
+ }
+
return TaskQueue::QueuePriority::kNormalPriority;
}
@@ -1242,5 +1197,10 @@ FrameSchedulerImpl::LoadingControlTaskQueueTraits() {
QueueTraits::PrioritisationType::kLoadingControl);
}
+MainThreadTaskQueue::QueueTraits
+FrameSchedulerImpl::FindInPageTaskQueueTraits() {
+ return PausableTaskQueueTraits().SetPrioritisationType(
+ QueueTraits::PrioritisationType::kFindInPage);
+}
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index 860cd684172..cb6d72cf306 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -93,8 +93,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
void SetPaused(bool frame_paused) override;
void SetShouldReportPostedTasksWhenDisabled(bool should_report) override;
- void SetCrossOrigin(bool cross_origin) override;
- bool IsCrossOrigin() const override;
+ void SetCrossOriginToMainFrame(bool cross_origin) override;
+ bool IsCrossOriginToMainFrame() const override;
void SetIsAdFrame() override;
bool IsAdFrame() const override;
@@ -160,16 +160,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
MainThreadTaskQueue*,
base::sequence_manager::TaskQueue::QueueEnabledVoter*) override;
- using FrameTaskTypeToQueueTraitsArray =
- std::array<base::Optional<MainThreadTaskQueue::QueueTraits>,
- static_cast<size_t>(TaskType::kCount)>;
-
- // Initializes the mapping from TaskType to QueueTraits for frame-level tasks.
- // We control the policy and initialize this, but the map is stored with main
- // thread scheduling settings to avoid redundancy.
- static void InitializeTaskTypeQueueTraitsMap(
- FrameTaskTypeToQueueTraitsArray&);
-
// Returns the list of active features which currently tracked by the
// scheduler for back-forward cache metrics.
WTF::HashSet<SchedulingPolicy::Feature>
@@ -269,8 +259,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
// Create the QueueTraits for a specific TaskType. This returns base::nullopt
// for loading tasks and non-frame-level tasks.
- static base::Optional<MainThreadTaskQueue::QueueTraits>
- CreateQueueTraitsForTaskType(TaskType);
+ static MainThreadTaskQueue::QueueTraits CreateQueueTraitsForTaskType(
+ TaskType);
// Reset the state which should not persist across navigations.
void ResetForNavigation();
@@ -294,6 +284,7 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
DoesNotUseVirtualTimeTaskQueueTraits();
static MainThreadTaskQueue::QueueTraits LoadingTaskQueueTraits();
static MainThreadTaskQueue::QueueTraits LoadingControlTaskQueueTraits();
+ static MainThreadTaskQueue::QueueTraits FindInPageTaskQueueTraits();
const FrameScheduler::FrameType frame_type_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index 43efd83327e..6411d32f558 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -40,6 +40,11 @@ namespace scheduler {
namespace frame_scheduler_impl_unittest {
using FeatureHandle = FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle;
+using PrioritisationType = MainThreadTaskQueue::QueueTraits::PrioritisationType;
+
+void AppendToVectorTestTask(Vector<String>* vector, String value) {
+ vector->push_back(std::move(value));
+}
class FrameSchedulerDelegateForTesting : public FrameScheduler::Delegate {
public:
@@ -126,6 +131,49 @@ class FrameSchedulerImplTest : public testing::Test {
UseCase::kLoading);
}
+ // Helper for posting several tasks of specific prioritisation types for
+ // testing the relative order of tasks. |task_descriptor| is a string with
+ // space delimited task identifiers. The first letter of each task identifier
+ // specifies the prioritisation type:
+ // - 'R': Regular (normal priority)
+ // - 'V': Very high
+ // - 'B': Best-effort
+ // - 'D': Database
+ void PostTestTasksForPrioritisationType(Vector<String>* run_order,
+ const String& task_descriptor) {
+ std::istringstream stream(task_descriptor.Utf8());
+ PrioritisationType prioritisation_type;
+ while (!stream.eof()) {
+ std::string task;
+ stream >> task;
+ switch (task[0]) {
+ case 'R':
+ prioritisation_type = PrioritisationType::kRegular;
+ break;
+ case 'V':
+ prioritisation_type = PrioritisationType::kVeryHigh;
+ break;
+ case 'B':
+ prioritisation_type = PrioritisationType::kBestEffort;
+ break;
+ case 'D':
+ prioritisation_type = PrioritisationType::kExperimentalDatabase;
+ break;
+ default:
+ EXPECT_FALSE(true);
+ return;
+ }
+ auto queue_traits =
+ FrameSchedulerImpl::PausableTaskQueueTraits().SetPrioritisationType(
+ prioritisation_type);
+ GetTaskQueue(queue_traits)
+ ->task_runner()
+ ->PostTask(FROM_HERE,
+ base::BindOnce(&AppendToVectorTestTask, run_order,
+ String::FromUTF8(task)));
+ }
+ }
+
static void ResetForNavigation(FrameSchedulerImpl* frame_scheduler) {
frame_scheduler->ResetForNavigation();
}
@@ -306,19 +354,10 @@ void IncrementCounter(int* counter) {
++*counter;
}
-void ExpectAndIncrementCounter(int expected, int* actual) {
- EXPECT_EQ(expected, *actual);
- IncrementCounter(actual);
-}
-
void RecordQueueName(String name, Vector<String>* tasks) {
tasks->push_back(std::move(name));
}
-void AppendToVectorTestTask(Vector<String>* vector, String value) {
- vector->push_back(std::move(value));
-}
-
// Simulate running a task of a particular length by fast forwarding the task
// environment clock, which is used to determine the wall time of a task.
void RunTaskOfLength(base::test::TaskEnvironment* task_environment,
@@ -374,10 +413,10 @@ TEST_F(FrameSchedulerImplTest,
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
frame_scheduler_->SetFrameVisible(false);
- frame_scheduler_->SetCrossOrigin(true);
- frame_scheduler_->SetCrossOrigin(false);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(false);
EXPECT_FALSE(IsThrottled());
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
EXPECT_TRUE(IsThrottled());
frame_scheduler_->SetFrameVisible(true);
EXPECT_FALSE(IsThrottled());
@@ -388,7 +427,7 @@ TEST_F(FrameSchedulerImplTest,
TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_LazyInit) {
ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
frame_scheduler_->SetFrameVisible(false);
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
LazyInitThrottleableTaskQueue();
EXPECT_TRUE(IsThrottled());
}
@@ -399,14 +438,14 @@ TEST_F(FrameSchedulerImplTest,
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
frame_scheduler_->SetFrameVisible(false);
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
EXPECT_FALSE(IsThrottled());
}
TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_NoThrottling_LazyInit) {
ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
frame_scheduler_->SetFrameVisible(false);
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
}
@@ -433,14 +472,14 @@ TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_ExplicitInit) {
EXPECT_TRUE(throttleable_task_queue());
frame_scheduler_->SetFrameVisible(true);
EXPECT_FALSE(IsThrottled());
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
EXPECT_FALSE(IsThrottled());
}
TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_LazyInit) {
ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
frame_scheduler_->SetFrameVisible(true);
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
LazyInitThrottleableTaskQueue();
EXPECT_FALSE(IsThrottled());
}
@@ -1678,7 +1717,7 @@ class LowPriorityCrossOriginTaskExperimentTest : public FrameSchedulerImplTest {
};
TEST_F(LowPriorityCrossOriginTaskExperimentTest, FrameQueuesPriorities) {
- EXPECT_FALSE(frame_scheduler_->IsCrossOrigin());
+ EXPECT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame());
// Same Origin Task Queues.
EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
@@ -1694,8 +1733,8 @@ TEST_F(LowPriorityCrossOriginTaskExperimentTest, FrameQueuesPriorities) {
EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
TaskQueue::QueuePriority::kNormalPriority);
- frame_scheduler_->SetCrossOrigin(true);
- EXPECT_TRUE(frame_scheduler_->IsCrossOrigin());
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
+ EXPECT_TRUE(frame_scheduler_->IsCrossOriginToMainFrame());
EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
TaskQueue::QueuePriority::kLowPriority);
@@ -1737,8 +1776,8 @@ TEST_F(LowPriorityCrossOriginTaskDuringLoadingExperimentTest,
EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
TaskQueue::QueuePriority::kNormalPriority);
- frame_scheduler_->SetCrossOrigin(true);
- EXPECT_TRUE(frame_scheduler_->IsCrossOrigin());
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
+ EXPECT_TRUE(frame_scheduler_->IsCrossOriginToMainFrame());
EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
TaskQueue::QueuePriority::kLowPriority);
@@ -1787,191 +1826,6 @@ TEST_F(FrameSchedulerImplTest, TaskTypeToTaskQueueMapping) {
ForegroundOnlyTaskQueue());
}
-class ThrottleAndFreezeTaskTypesExperimentTest : public FrameSchedulerImplTest {
- public:
- ThrottleAndFreezeTaskTypesExperimentTest(const base::FieldTrialParams& params,
- const char* group_name) {
- scoped_feature_list().InitAndEnableFeatureWithParameters(
- kThrottleAndFreezeTaskTypes, params);
- }
-};
-
-class ThrottleableAndFreezableTaskTypesTest
- : public ThrottleAndFreezeTaskTypesExperimentTest {
- public:
- ThrottleableAndFreezableTaskTypesTest()
- : ThrottleAndFreezeTaskTypesExperimentTest(
- base::FieldTrialParams{
- // Leading spaces are allowed.
- {kThrottleableTaskTypesListParam, "PostedMessage"},
- {kFreezableTaskTypesListParam,
- "PostedMessage, MediaElementEvent,DOMManipulation"}},
- "Group1") {}
-};
-
-TEST_F(ThrottleableAndFreezableTaskTypesTest, QueueTraitsFromFieldTrialParams) {
- if (base::FeatureList::IsEnabled(blink::features::kStopNonTimersInBackground))
- return;
- // These tests will start to fail if the default task queues or queue traits
- // change for these task types.
-
- // Check that the overrides work.
- auto task_queue = GetTaskQueue(TaskType::kPostedMessage);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeThrottled(true)
- .SetCanBeFrozen(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeFrozen(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kDOMManipulation);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeFrozen(true)
- .SetCanBeDeferred(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- // Test some task types that were not configured through field trial
- // parameters.
- task_queue = GetTaskQueue(TaskType::kWebLocks);
- EXPECT_EQ(
- task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits().SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeDeferred(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-}
-
-
-class FreezableOnlyTaskTypesTest
- : public ThrottleAndFreezeTaskTypesExperimentTest {
- public:
- FreezableOnlyTaskTypesTest()
- : ThrottleAndFreezeTaskTypesExperimentTest(
- base::FieldTrialParams{
- {kThrottleableTaskTypesListParam, ""},
- {kFreezableTaskTypesListParam,
- "PostedMessage,MediaElementEvent,DOMManipulation"}},
- "Group2") {}
-};
-
-TEST_F(FreezableOnlyTaskTypesTest, QueueTraitsFromFieldTrialParams) {
- if (base::FeatureList::IsEnabled(blink::features::kStopNonTimersInBackground))
- return;
-
- // These tests will start to fail if the default task queues or queue traits
- // change for these task types.
-
- // Check that the overrides work.
- auto task_queue = GetTaskQueue(TaskType::kPostedMessage);
- EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetCanBeFrozen(true)
- .SetCanBePaused(true));
-
- task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
- EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetCanBeFrozen(true)
- .SetCanBePaused(true));
-
- task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
- EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetCanBePaused(true));
-
- task_queue = GetTaskQueue(TaskType::kDOMManipulation);
- EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetCanBeFrozen(true)
- .SetCanBeDeferred(true)
- .SetCanBePaused(true));
-
- // Test some task types that were not configured through field trial
- // parameters.
- task_queue = GetTaskQueue(TaskType::kWebLocks);
- EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits());
-
- task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
- EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetCanBeDeferred(true)
- .SetCanBePaused(true));
-}
-
-class ThrottleableOnlyTaskTypesTest
- : public ThrottleAndFreezeTaskTypesExperimentTest {
- public:
- ThrottleableOnlyTaskTypesTest()
- : ThrottleAndFreezeTaskTypesExperimentTest(
- base::FieldTrialParams{
- {kFreezableTaskTypesListParam, ""},
- {kThrottleableTaskTypesListParam, "PostedMessage"}},
- "Group3") {}
-};
-
-TEST_F(ThrottleableOnlyTaskTypesTest, QueueTraitsFromFieldTrialParams) {
- if (base::FeatureList::IsEnabled(blink::features::kStopNonTimersInBackground))
- return;
-
- // These tests will start to fail if the default task queues or queue traits
- // change for these task types.
-
- // Check that the overrides work.
- auto task_queue = GetTaskQueue(TaskType::kPostedMessage);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeThrottled(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kDOMManipulation);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeDeferred(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-
- // Test some task types that were not configured through field trial
- // parameters.
- task_queue = GetTaskQueue(TaskType::kWebLocks);
- EXPECT_EQ(
- task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits().SetCanRunWhenVirtualTimePaused(false));
-
- task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
- EXPECT_EQ(task_queue->GetQueueTraits(),
- MainThreadTaskQueue::QueueTraits()
- .SetCanBeDeferred(true)
- .SetCanBePaused(true)
- .SetCanRunWhenVirtualTimePaused(false));
-}
-
class FrameSchedulerImplDatabaseAccessWithoutHighPriority
: public FrameSchedulerImplTest {
public:
@@ -1980,37 +1834,11 @@ class FrameSchedulerImplDatabaseAccessWithoutHighPriority
};
TEST_F(FrameSchedulerImplDatabaseAccessWithoutHighPriority, QueueTraits) {
- // These tests will start to fail if the default task queues or queue traits
- // change for these task types.
-
- int counter = 0;
-
- auto loading_queue = GetTaskQueue(TaskType::kInternalContinueScriptLoading);
- EXPECT_EQ(loading_queue->GetQueuePriority(),
- TaskQueue::QueuePriority::kVeryHighPriority);
- loading_queue->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExpectAndIncrementCounter, 0,
- base::Unretained(&counter)));
-
auto da_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(da_queue->GetQueueTraits().prioritisation_type,
MainThreadTaskQueue::QueueTraits::PrioritisationType::kRegular);
EXPECT_EQ(da_queue->GetQueuePriority(),
TaskQueue::QueuePriority::kNormalPriority);
- da_queue->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExpectAndIncrementCounter, 1,
- base::Unretained(&counter)));
-
- auto content_queue = GetTaskQueue(TaskType::kInternalContentCapture);
- EXPECT_EQ(content_queue->GetQueuePriority(),
- TaskQueue::QueuePriority::kBestEffortPriority);
- content_queue->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExpectAndIncrementCounter, 2,
- base::Unretained(&counter)));
-
- EXPECT_EQ(0, counter);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3, counter);
}
class FrameSchedulerImplDatabaseAccessWithHighPriority
@@ -2021,37 +1849,31 @@ class FrameSchedulerImplDatabaseAccessWithHighPriority
};
TEST_F(FrameSchedulerImplDatabaseAccessWithHighPriority, QueueTraits) {
- // These tests will start to fail if the default task queues or queue traits
- // change for these task types.
-
- int counter = 0;
-
- auto loading_queue = GetTaskQueue(TaskType::kInternalContinueScriptLoading);
- EXPECT_EQ(loading_queue->GetQueuePriority(),
- TaskQueue::QueuePriority::kVeryHighPriority);
- loading_queue->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExpectAndIncrementCounter, 0,
- base::Unretained(&counter)));
-
auto da_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(da_queue->GetQueueTraits().prioritisation_type,
- MainThreadTaskQueue::QueueTraits::PrioritisationType::kHigh);
+ MainThreadTaskQueue::QueueTraits::PrioritisationType::
+ kExperimentalDatabase);
EXPECT_EQ(da_queue->GetQueuePriority(),
TaskQueue::QueuePriority::kHighPriority);
- da_queue->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExpectAndIncrementCounter, 1,
- base::Unretained(&counter)));
+}
- auto pausable_queue = PausableTaskQueue();
- EXPECT_EQ(pausable_queue->GetQueuePriority(),
- TaskQueue::QueuePriority::kNormalPriority);
- pausable_queue->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExpectAndIncrementCounter, 2,
- base::Unretained(&counter)));
+TEST_F(FrameSchedulerImplDatabaseAccessWithHighPriority, RunOrder) {
+ Vector<String> run_order;
+ PostTestTasksForPrioritisationType(&run_order, "D1 R1 D2 V1 B1");
- EXPECT_EQ(0, counter);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3, counter);
+ EXPECT_THAT(run_order, testing::ElementsAre("V1", "D1", "D2", "R1", "B1"));
+}
+
+TEST_F(FrameSchedulerImplDatabaseAccessWithHighPriority,
+ NormalPriorityInBackground) {
+ page_scheduler_->SetPageVisible(false);
+
+ Vector<String> run_order;
+ PostTestTasksForPrioritisationType(&run_order, "D1 R1 D2 V1 B1");
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_THAT(run_order, testing::ElementsAre("V1", "D1", "R1", "D2", "B1"));
}
TEST_F(FrameSchedulerImplTest, ContentCaptureHasIdleTaskQueue) {
@@ -2314,11 +2136,9 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
// Helper for posting tasks to a WebSchedulingTaskQueue. |task_descriptor| is
// a string with space delimited task identifiers. The first letter of each
// task identifier specifies the task queue priority:
- // - 'I': Immediate
- // - 'H': High
- // - 'D': Default
- // - 'L': Low
- // - 'E': Idle
+ // - 'U': UserBlocking
+ // - 'V': UserVisible
+ // - 'B': Background
void PostWebSchedulingTestTasks(Vector<String>* run_order,
const String& task_descriptor) {
std::istringstream stream(task_descriptor.Utf8());
@@ -2327,20 +2147,14 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
stream >> task;
WebSchedulingPriority priority;
switch (task[0]) {
- case 'I':
- priority = WebSchedulingPriority::kImmediatePriority;
- break;
- case 'H':
- priority = WebSchedulingPriority::kHighPriority;
+ case 'U':
+ priority = WebSchedulingPriority::kUserBlockingPriority;
break;
- case 'D':
- priority = WebSchedulingPriority::kDefaultPriority;
+ case 'V':
+ priority = WebSchedulingPriority::kUserVisiblePriority;
break;
- case 'L':
- priority = WebSchedulingPriority::kLowPriority;
- break;
- case 'E':
- priority = WebSchedulingPriority::kIdlePriority;
+ case 'B':
+ priority = WebSchedulingPriority::kBackgroundPriority;
break;
default:
EXPECT_FALSE(true);
@@ -2361,23 +2175,23 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
TEST_F(WebSchedulingTaskQueueTest, TasksRunInPriorityOrder) {
Vector<String> run_order;
- PostWebSchedulingTestTasks(&run_order, "E1 E2 L1 L2 D1 D2 H1 H2 I1 I2");
+ PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2");
base::RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, testing::ElementsAre("I1", "I2", "H1", "H2", "D1",
- "D2", "L1", "L2", "E1", "E2"));
+ EXPECT_THAT(run_order,
+ testing::ElementsAre("U1", "U2", "V1", "V2", "B1", "B2"));
}
TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) {
Vector<String> run_order;
- PostWebSchedulingTestTasks(&run_order, "E1 E2 D1 D2 I1 I2");
- task_queues_[static_cast<int>(WebSchedulingPriority::kImmediatePriority)]
- ->SetPriority(WebSchedulingPriority::kLowPriority);
+ PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2");
+ task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)]
+ ->SetPriority(WebSchedulingPriority::kBackgroundPriority);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
- testing::ElementsAre("D1", "D2", "I1", "I2", "E1", "E2"));
+ testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2"));
}
} // namespace frame_scheduler_impl_unittest
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_status.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_status.cc
index cfda104e005..d8a1c929c2b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_status.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_status.cc
@@ -26,9 +26,10 @@ enum class FrameThrottlingState {
enum class FrameOriginState {
kMainFrame = 0,
- kSameOrigin = 1,
- kCrossOrigin = 2,
+ kSameOriginToMainFrame = 1,
+ kCrossOriginToMainFrame = 2,
+ // TODO(dcheng): get rid of kCount here.
kCount = 3
};
@@ -60,9 +61,9 @@ FrameOriginState GetFrameOriginState(const FrameScheduler& frame_scheduler) {
if (frame_scheduler.GetFrameType() == FrameScheduler::FrameType::kMainFrame) {
return FrameOriginState::kMainFrame;
}
- if (frame_scheduler.IsCrossOrigin())
- return FrameOriginState::kCrossOrigin;
- return FrameOriginState::kSameOrigin;
+ if (frame_scheduler.IsCrossOriginToMainFrame())
+ return FrameOriginState::kCrossOriginToMainFrame;
+ return FrameOriginState::kSameOriginToMainFrame;
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
index 710f3d595b9..362b0e1b5f1 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -107,10 +107,6 @@ void FrameTaskQueueController::CreateTaskQueue(
queue_creation_params = queue_creation_params.SetFixedPriority(
TaskQueue::QueuePriority::kVeryHighPriority);
break;
- case QueueTraits::PrioritisationType::kHigh:
- queue_creation_params = queue_creation_params.SetFixedPriority(
- TaskQueue::QueuePriority::kHighPriority);
- break;
case QueueTraits::PrioritisationType::kBestEffort:
queue_creation_params = queue_creation_params.SetFixedPriority(
TaskQueue::QueuePriority::kBestEffortPriority);
@@ -179,7 +175,7 @@ bool FrameTaskQueueController::RemoveResourceLoadingTaskQueue(
void FrameTaskQueueController::AsValueInto(
base::trace_event::TracedValue* state) const {
state->BeginArray("task_queues");
- for (const auto it : task_queues_) {
+ for (const auto& it : task_queues_) {
state->AppendString(PointerToString(it.value.get()));
}
state->EndArray();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
index 18f4199534c..28f6af4d89a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -260,38 +260,24 @@ TEST_F(FrameTaskQueueControllerTest,
TEST_F(FrameTaskQueueControllerTest, AddWebSchedulingTaskQueues) {
scoped_refptr<MainThreadTaskQueue> task_queue =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kImmediatePriority);
+ QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
EXPECT_EQ(1u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kImmediatePriority,
+ EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
task_queue->web_scheduling_priority().value());
task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kHighPriority);
+ QueueTraits(), WebSchedulingPriority::kUserVisiblePriority);
EXPECT_EQ(2u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kHighPriority,
+ EXPECT_EQ(WebSchedulingPriority::kUserVisiblePriority,
task_queue->web_scheduling_priority().value());
task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kDefaultPriority);
+ QueueTraits(), WebSchedulingPriority::kBackgroundPriority);
EXPECT_EQ(3u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kDefaultPriority,
- task_queue->web_scheduling_priority().value());
-
- task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kLowPriority);
- EXPECT_EQ(4u,
- frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kLowPriority,
- task_queue->web_scheduling_priority().value());
-
- task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kIdlePriority);
- EXPECT_EQ(5u,
- frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kIdlePriority,
+ EXPECT_EQ(WebSchedulingPriority::kBackgroundPriority,
task_queue->web_scheduling_priority().value());
}
@@ -299,18 +285,18 @@ TEST_F(FrameTaskQueueControllerTest,
AddMultipleSamePriorityWebSchedulingTaskQueues) {
scoped_refptr<MainThreadTaskQueue> task_queue1 =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kImmediatePriority);
+ QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
EXPECT_EQ(1u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kImmediatePriority,
+ EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
task_queue1->web_scheduling_priority().value());
scoped_refptr<MainThreadTaskQueue> task_queue2 =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
- QueueTraits(), WebSchedulingPriority::kImmediatePriority);
+ QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
EXPECT_EQ(2u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
- EXPECT_EQ(WebSchedulingPriority::kImmediatePriority,
+ EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
task_queue2->web_scheduling_priority().value());
EXPECT_NE(task_queue1.get(), task_queue2.get());
@@ -338,11 +324,12 @@ INSTANTIATE_TEST_SUITE_P(
All,
TaskQueueCreationFromQueueTraitsTest,
::testing::Values(QueueTraits::PrioritisationType::kVeryHigh,
- QueueTraits::PrioritisationType::kHigh,
QueueTraits::PrioritisationType::kBestEffort,
QueueTraits::PrioritisationType::kRegular,
QueueTraits::PrioritisationType::kLoading,
- QueueTraits::PrioritisationType::kLoadingControl));
+ QueueTraits::PrioritisationType::kLoadingControl,
+ QueueTraits::PrioritisationType::kFindInPage,
+ QueueTraits::PrioritisationType::kExperimentalDatabase));
TEST_P(TaskQueueCreationFromQueueTraitsTest,
AddAndRetrieveAllTaskQueues) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
index 2adac49f386..9b7e85a92b6 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
@@ -191,38 +191,38 @@ class MainThreadMetricsHelperTest : public testing::Test {
break;
case FrameStatus::kCrossOriginVisible:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetIsPageVisible(true)
.SetIsFrameVisible(true);
break;
case FrameStatus::kCrossOriginVisibleService:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetPageScheduler(playing_view_.get())
.SetIsFrameVisible(true);
break;
case FrameStatus::kCrossOriginHidden:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetIsPageVisible(true);
break;
case FrameStatus::kCrossOriginHiddenService:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetPageScheduler(playing_view_.get());
break;
case FrameStatus::kCrossOriginBackground:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true);
+ .SetIsCrossOriginToMainFrame(true);
break;
case FrameStatus::kCrossOriginBackgroundExemptSelf:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetIsExemptFromThrottling(true);
break;
case FrameStatus::kCrossOriginBackgroundExemptOther:
builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetPageScheduler(throtting_exempt_view_.get());
break;
case FrameStatus::kCount:
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 1c1a13067ab..9bf6ae8538a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -22,10 +22,11 @@
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "services/metrics/public/cpp/ukm_builders.h"
+#include "third_party/blink/public/common/input/web_input_event_attribution.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
+#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/public/platform/scheduler/web_renderer_process_type.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-#include "third_party/blink/public/platform/web_touch_event.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -37,6 +38,7 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "v8/include/v8.h"
@@ -201,24 +203,15 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
.SetFixedPriority(
TaskQueue::QueuePriority::kBestEffortPriority))),
render_widget_scheduler_signals_(this),
+ find_in_page_budget_pool_controller_(
+ new FindInPageBudgetPoolController(this)),
control_task_queue_(helper_.ControlMainThreadTaskQueue()),
compositor_task_queue_(
helper_.NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(
MainThreadTaskQueue::QueueType::kCompositor)
.SetShouldMonitorQuiescence(true))),
- input_task_queue_(helper_.NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kInput)
- .SetShouldMonitorQuiescence(true)
- .SetFixedPriority(
- scheduling_settings_.high_priority_input
- ? base::make_optional(
- TaskQueue::QueuePriority::kHighestPriority)
- : base::nullopt))),
compositor_task_queue_enabled_voter_(
compositor_task_queue_->CreateQueueEnabledVoter()),
- input_task_queue_enabled_voter_(
- input_task_queue_->CreateQueueEnabledVoter()),
memory_purge_task_queue_(helper_.NewTaskQueue(
MainThreadTaskQueue::QueueCreationParams(
MainThreadTaskQueue::QueueType::kIdle)
@@ -226,6 +219,7 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
TaskQueue::QueuePriority::kBestEffortPriority))),
memory_purge_manager_(memory_purge_task_queue_->CreateTaskRunner(
TaskType::kMainThreadTaskQueueMemoryPurge)),
+ non_waking_time_domain_(tick_clock()),
delayed_update_policy_runner_(
base::BindRepeating(&MainThreadSchedulerImpl::UpdatePolicy,
base::Unretained(this)),
@@ -246,8 +240,8 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
task_runners_.emplace(helper_.DefaultMainThreadTaskQueue(), nullptr);
task_runners_.emplace(compositor_task_queue_,
compositor_task_queue_->CreateQueueEnabledVoter());
- task_runners_.emplace(input_task_queue_,
- input_task_queue_->CreateQueueEnabledVoter());
+
+ RegisterTimeDomain(&non_waking_time_domain_);
v8_task_queue_ = NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(
MainThreadTaskQueue::QueueType::kV8));
@@ -255,6 +249,10 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
MainThreadTaskQueue::QueueType::kIPC));
cleanup_task_queue_ = NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(
MainThreadTaskQueue::QueueType::kCleanup));
+ non_waking_task_queue_ =
+ NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(
+ MainThreadTaskQueue::QueueType::kNonWaking)
+ .SetTimeDomain(&non_waking_time_domain_));
v8_task_runner_ =
v8_task_queue_->CreateTaskRunner(TaskType::kMainThreadTaskQueueV8);
@@ -262,12 +260,12 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
TaskType::kMainThreadTaskQueueCompositor);
control_task_runner_ = helper_.ControlMainThreadTaskQueue()->CreateTaskRunner(
TaskType::kMainThreadTaskQueueControl);
- input_task_runner_ =
- input_task_queue_->CreateTaskRunner(TaskType::kMainThreadTaskQueueInput);
ipc_task_runner_ =
ipc_task_queue_->CreateTaskRunner(TaskType::kMainThreadTaskQueueIPC);
cleanup_task_runner_ = cleanup_task_queue_->CreateTaskRunner(
TaskType::kMainThreadTaskQueueCleanup);
+ non_waking_task_runner_ = non_waking_task_queue_->CreateTaskRunner(
+ TaskType::kMainThreadTaskQueueNonWaking);
// TaskQueueThrottler requires some task runners, then initialize
// TaskQueueThrottler after task queues/runners are initialized.
@@ -307,6 +305,9 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
main_thread_only()
.compositor_priority_experiments.OnMainThreadSchedulerInitialized();
+ main_thread_only().current_policy.find_in_page_priority() =
+ find_in_page_budget_pool_controller_->CurrentTaskPriority();
+
g_main_thread_scheduler = this;
}
@@ -319,6 +320,8 @@ MainThreadSchedulerImpl::~MainThreadSchedulerImpl() {
pair.first->ShutdownTaskQueue();
}
+ UnregisterTimeDomain(&non_waking_time_domain_);
+
if (virtual_time_domain_)
UnregisterTimeDomain(virtual_time_domain_.get());
@@ -552,9 +555,6 @@ MainThreadSchedulerImpl::AnyThread::AnyThread(
&main_thread_scheduler_impl->tracing_controller_) {}
MainThreadSchedulerImpl::SchedulingSettings::SchedulingSettings() {
- high_priority_input =
- base::FeatureList::IsEnabled(kHighPriorityInputOnMainThread);
-
low_priority_background_page =
base::FeatureList::IsEnabled(kLowPriorityForBackgroundPages);
best_effort_background_page =
@@ -607,9 +607,6 @@ MainThreadSchedulerImpl::SchedulingSettings::SchedulingSettings() {
}
}
}
-
- FrameSchedulerImpl::InitializeTaskTypeQueueTraitsMap(
- frame_task_types_to_queue_traits);
}
MainThreadSchedulerImpl::AnyThread::~AnyThread() = default;
@@ -662,6 +659,11 @@ std::unique_ptr<Thread> MainThreadSchedulerImpl::CreateMainThread() {
return std::make_unique<MainThread>(this);
}
+std::unique_ptr<WebWidgetScheduler>
+MainThreadSchedulerImpl::CreateWidgetScheduler() {
+ return std::make_unique<WidgetScheduler>(this);
+}
+
scoped_refptr<base::SingleThreadTaskRunner>
MainThreadSchedulerImpl::ControlTaskRunner() {
return control_task_runner_;
@@ -672,12 +674,6 @@ MainThreadSchedulerImpl::DefaultTaskRunner() {
return helper_.DefaultTaskRunner();
}
-scoped_refptr<base::SingleThreadTaskRunner>
-MainThreadSchedulerImpl::InputTaskRunner() {
- helper_.CheckOnValidThread();
- return input_task_runner_;
-}
-
scoped_refptr<SingleThreadIdleTaskRunner>
MainThreadSchedulerImpl::IdleTaskRunner() {
return idle_helper_.IdleTaskRunner();
@@ -709,11 +705,6 @@ MainThreadSchedulerImpl::CompositorTaskQueue() {
return compositor_task_queue_;
}
-scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::InputTaskQueue() {
- helper_.CheckOnValidThread();
- return input_task_queue_;
-}
-
scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::V8TaskQueue() {
helper_.CheckOnValidThread();
return v8_task_queue_;
@@ -1269,13 +1260,15 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
}
void MainThreadSchedulerImpl::WillPostInputEventToMainThread(
- WebInputEvent::Type web_input_event_type) {
+ WebInputEvent::Type web_input_event_type,
+ const WebInputEventAttribution& web_input_event_attribution) {
base::AutoLock lock(any_thread_lock_);
any_thread().pending_input_monitor.OnEnqueue(web_input_event_type);
}
void MainThreadSchedulerImpl::WillHandleInputEventOnMainThread(
- WebInputEvent::Type web_input_event_type) {
+ WebInputEvent::Type web_input_event_type,
+ const WebInputEventAttribution& web_input_event_attribution) {
helper_.CheckOnValidThread();
base::AutoLock lock(any_thread_lock_);
@@ -1484,7 +1477,7 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
break;
case UseCase::kNone:
- // It's only safe to block tasks that if we are expecting a compositor
+ // It's only safe to block tasks if we are expecting a compositor
// driven gesture.
if (main_thread_only().blocking_input_expected_soon &&
any_thread().last_gesture_was_compositor_driven) {
@@ -1549,6 +1542,9 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
new_policy.should_disable_throttling() = main_thread_only().use_virtual_time;
+ new_policy.find_in_page_priority() =
+ find_in_page_budget_pool_controller_->CurrentTaskPriority();
+
// Tracing is done before the early out check, because it's quite possible we
// will otherwise miss this information in traces.
CreateTraceEventObjectSnapshotLocked();
@@ -1810,6 +1806,9 @@ void MainThreadSchedulerImpl::DisableVirtualTimeForTesting() {
virtual_time_control_task_queue_ = nullptr;
ApplyVirtualTimePolicy();
+ main_thread_only().initial_virtual_time = base::Time();
+ main_thread_only().initial_virtual_time_ticks = base::TimeTicks();
+
// Reset the MetricsHelper because it gets confused by time going backwards.
base::TimeTicks now = tick_clock()->NowTicks();
main_thread_only().metrics_helper.ResetForTest(now);
@@ -1954,13 +1953,26 @@ void MainThreadSchedulerImpl::CreateTraceEventObjectSnapshotLocked() const {
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
MainThreadSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
+ auto state = std::make_unique<base::trace_event::TracedValue>();
+ AsValueIntoLocked(state.get(), optional_now);
+ return std::move(state);
+}
+
+std::string MainThreadSchedulerImpl::ToString() const {
+ base::AutoLock lock(any_thread_lock_);
+ base::trace_event::TracedValueJSON value;
+ AsValueIntoLocked(&value, base::TimeTicks());
+ return value.ToJSON();
+}
+
+void MainThreadSchedulerImpl::AsValueIntoLocked(
+ base::trace_event::TracedValue* state,
+ base::TimeTicks optional_now) const {
helper_.CheckOnValidThread();
any_thread_lock_.AssertAcquired();
if (optional_now.is_null())
optional_now = helper_.NowTicks();
- std::unique_ptr<base::trace_event::TracedValue> state(
- new base::trace_event::TracedValue());
state->SetBoolean(
"has_visible_render_widget_with_touch_handler",
main_thread_only().has_visible_render_widget_with_touch_handler);
@@ -2024,13 +2036,13 @@ MainThreadSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
state->BeginDictionary("page_schedulers");
for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) {
state->BeginDictionaryWithCopiedName(PointerToString(page_scheduler));
- page_scheduler->AsValueInto(state.get());
+ page_scheduler->AsValueInto(state);
state->EndDictionary();
}
state->EndDictionary();
state->BeginDictionary("policy");
- main_thread_only().current_policy.AsValueInto(state.get());
+ main_thread_only().current_policy.AsValueInto(state);
state->EndDictionary();
// TODO(skyostil): Can we somehow trace how accurate these estimates were?
@@ -2046,14 +2058,12 @@ MainThreadSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
.InMillisecondsF());
state->SetBoolean("in_idle_period", any_thread().in_idle_period);
- any_thread().user_model.AsValueInto(state.get());
- render_widget_scheduler_signals_.AsValueInto(state.get());
+ any_thread().user_model.AsValueInto(state);
+ render_widget_scheduler_signals_.AsValueInto(state);
state->BeginDictionary("task_queue_throttler");
- task_queue_throttler_->AsValueInto(state.get(), optional_now);
+ task_queue_throttler_->AsValueInto(state, optional_now);
state->EndDictionary();
-
- return std::move(state);
}
bool MainThreadSchedulerImpl::TaskQueuePolicy::IsQueueEnabled(
@@ -2090,6 +2100,8 @@ MainThreadSchedulerImpl::Policy::Policy()
should_prioritize_loading_with_compositing_(false),
compositor_priority_(
base::sequence_manager::TaskQueue::QueuePriority::kNormalPriority),
+ find_in_page_priority_(FindInPageBudgetPoolController::
+ kFindInPageBudgetNotExhaustedPriority),
use_case_(UseCase::kNone) {}
void MainThreadSchedulerImpl::Policy::AsValueInto(
@@ -2336,6 +2348,11 @@ MainThreadSchedulerImpl::CompositorTaskRunner() {
return compositor_task_runner_;
}
+scoped_refptr<base::SingleThreadTaskRunner>
+MainThreadSchedulerImpl::NonWakingTaskRunner() {
+ return non_waking_task_runner_;
+}
+
std::unique_ptr<PageScheduler> MainThreadSchedulerImpl::CreatePageScheduler(
PageScheduler::Delegate* delegate) {
return std::make_unique<PageSchedulerImpl>(delegate, this);
@@ -2482,6 +2499,9 @@ void MainThreadSchedulerImpl::OnTaskCompleted(
main_thread_only().compositor_priority_experiments.OnTaskCompleted(
queue.get(), main_thread_only().current_policy.compositor_priority(),
task_timing);
+
+ find_in_page_budget_pool_controller_->OnTaskCompleted(queue.get(),
+ task_timing);
}
void MainThreadSchedulerImpl::RecordTaskUkm(
@@ -2577,7 +2597,7 @@ TaskQueue::QueuePriority MainThreadSchedulerImpl::ComputePriority(
MainThreadTaskQueue* task_queue) const {
DCHECK(task_queue);
- // If |task_queue| is associated to a frame, the the frame scheduler computes
+ // If |task_queue| is associated to a frame, then the frame scheduler computes
// the priority.
FrameSchedulerImpl* frame_scheduler = task_queue->GetFrameScheduler();
@@ -2735,7 +2755,9 @@ bool MainThreadSchedulerImpl::ShouldUpdateTaskQueuePriorities(
return old_policy.use_case() !=
main_thread_only().current_policy.use_case() ||
old_policy.compositor_priority() !=
- main_thread_only().current_policy.compositor_priority();
+ main_thread_only().current_policy.compositor_priority() ||
+ old_policy.find_in_page_priority() !=
+ main_thread_only().current_policy.find_in_page_priority();
}
UseCase MainThreadSchedulerImpl::current_use_case() const {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index 612cd8ea852..5914b7f7175 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -32,11 +32,13 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h"
@@ -96,9 +98,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
struct SchedulingSettings {
SchedulingSettings();
- // High priority input experiment.
- bool high_priority_input;
-
// Background page priority experiment (crbug.com/848835).
bool low_priority_background_page;
bool best_effort_background_page;
@@ -137,14 +136,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
std::array<base::sequence_manager::TaskQueue::QueuePriority,
net::RequestPrioritySize::NUM_PRIORITIES>
net_to_blink_priority;
-
- using FrameTaskTypeToQueueTraitsArray =
- std::array<base::Optional<MainThreadTaskQueue::QueueTraits>,
- static_cast<size_t>(TaskType::kCount)>;
- // Array of QueueTraits indexed by TaskType, containing TaskType::kCount
- // entries. This is initialized early with all valid entries. Entries that
- // aren't valid task types, i.e. non-frame level, are base::nullopt.
- FrameTaskTypeToQueueTraitsArray frame_task_types_to_queue_traits;
};
static const char* UseCaseToString(UseCase use_case);
@@ -170,9 +161,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// WebThreadScheduler implementation:
std::unique_ptr<Thread> CreateMainThread() override;
+ std::unique_ptr<WebWidgetScheduler> CreateWidgetScheduler() override;
// Note: this is also shared by the ThreadScheduler interface.
scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> CleanupTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner()
override;
std::unique_ptr<WebRenderWidgetSchedulingState>
@@ -185,9 +178,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
const WebInputEvent& web_input_event,
InputEventState event_state) override;
void WillPostInputEventToMainThread(
- WebInputEvent::Type web_input_event_type) override;
+ WebInputEvent::Type web_input_event_type,
+ const WebInputEventAttribution& web_input_event_attribution) override;
void WillHandleInputEventOnMainThread(
- WebInputEvent::Type web_input_event_type) override;
+ WebInputEvent::Type web_input_event_type,
+ const WebInputEventAttribution& web_input_event_attribution) override;
void DidHandleInputEventOnMainThread(const WebInputEvent& web_input_event,
WebInputEventResult result) override;
void DidAnimateForInputOnCompositorThread() override;
@@ -240,7 +235,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// WebThreadScheduler implementation:
scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
// The following functions are defined in both WebThreadScheduler and
// ThreadScheduler, and have the same function signatures -- see above.
@@ -428,11 +422,14 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
return main_thread_only().main_thread_compositing_is_fast;
}
+ QueuePriority find_in_page_priority() const {
+ return main_thread_only().current_policy.find_in_page_priority();
+ }
+
protected:
scoped_refptr<MainThreadTaskQueue> ControlTaskQueue();
scoped_refptr<MainThreadTaskQueue> DefaultTaskQueue();
scoped_refptr<MainThreadTaskQueue> CompositorTaskQueue();
- scoped_refptr<MainThreadTaskQueue> InputTaskQueue();
scoped_refptr<MainThreadTaskQueue> V8TaskQueue();
// A control task queue which also respects virtual time. Only available if
// virtual time has been enabled.
@@ -459,6 +456,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest;
friend class CompositorPriorityExperiments;
+ friend class FindInPageBudgetPoolController;
FRIEND_TEST_ALL_PREFIXES(
main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest,
@@ -577,6 +575,14 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
return compositor_priority_;
}
+ base::sequence_manager::TaskQueue::QueuePriority& find_in_page_priority() {
+ return find_in_page_priority_;
+ }
+ base::sequence_manager::TaskQueue::QueuePriority find_in_page_priority()
+ const {
+ return find_in_page_priority_;
+ }
+
UseCase& use_case() { return use_case_; }
UseCase use_case() const { return use_case_; }
@@ -587,6 +593,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
should_prioritize_loading_with_compositing_ ==
other.should_prioritize_loading_with_compositing_ &&
compositor_priority_ == other.compositor_priority_ &&
+ find_in_page_priority_ == other.find_in_page_priority_ &&
use_case_ == other.use_case_;
}
@@ -602,6 +609,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// MainThread::QueueClass).
base::sequence_manager::TaskQueue::QueuePriority compositor_priority_;
+ base::sequence_manager::TaskQueue::QueuePriority find_in_page_priority_;
+
UseCase use_case_;
std::array<TaskQueuePolicy,
@@ -647,6 +656,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
base::TimeTicks optional_now) const;
void CreateTraceEventObjectSnapshotLocked() const;
+ std::string ToString() const;
+
static bool ShouldPrioritizeInputEvent(const WebInputEvent& web_input_event);
// The amount of time which idle periods can continue being scheduled when the
@@ -775,6 +786,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// task.
void DispatchOnTaskCompletionCallbacks();
+ void AsValueIntoLocked(base::trace_event::TracedValue*,
+ base::TimeTicks optional_now) const;
+
// Indicates that scheduler has been shutdown.
// It should be accessed only on the main thread, but couldn't be a member
// of MainThreadOnly struct because last might be destructed before we
@@ -799,14 +813,14 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
RenderWidgetSignals render_widget_scheduler_signals_;
+ std::unique_ptr<FindInPageBudgetPoolController>
+ find_in_page_budget_pool_controller_;
+
const scoped_refptr<MainThreadTaskQueue> control_task_queue_;
const scoped_refptr<MainThreadTaskQueue> compositor_task_queue_;
- const scoped_refptr<MainThreadTaskQueue> input_task_queue_;
scoped_refptr<MainThreadTaskQueue> virtual_time_control_task_queue_;
std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
compositor_task_queue_enabled_voter_;
- std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
- input_task_queue_enabled_voter_;
using TaskQueueVoterMap = std::map<
scoped_refptr<MainThreadTaskQueue>,
@@ -818,20 +832,22 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
scoped_refptr<MainThreadTaskQueue> ipc_task_queue_;
scoped_refptr<MainThreadTaskQueue> cleanup_task_queue_;
scoped_refptr<MainThreadTaskQueue> memory_purge_task_queue_;
+ scoped_refptr<MainThreadTaskQueue> non_waking_task_queue_;
scoped_refptr<base::SingleThreadTaskRunner> v8_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> cleanup_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> non_waking_task_runner_;
MemoryPurgeManager memory_purge_manager_;
// Note |virtual_time_domain_| is lazily created.
std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_;
+ NonWakingTimeDomain non_waking_time_domain_;
- base::Closure update_policy_closure_;
+ base::RepeatingClosure update_policy_closure_;
DeadlineTaskRunner delayed_update_policy_runner_;
CancelableClosureHolder end_renderer_hidden_idle_period_closure_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index 807506d92e1..1f4d240aa79 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
@@ -18,7 +19,6 @@
#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
#include "base/task/task_executor.h"
#include "base/test/bind_test_util.h"
-#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
@@ -27,12 +27,14 @@
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
+#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-#include "third_party/blink/public/platform/web_touch_event.h"
+#include "third_party/blink/public/platform/scheduler/web_widget_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h"
#include "third_party/blink/renderer/platform/scheduler/test/recording_task_time_observer.h"
@@ -46,40 +48,23 @@ namespace scheduler {
// To avoid symbol collisions in jumbo builds.
namespace main_thread_scheduler_impl_unittest {
-using testing::IsNull;
using testing::Mock;
using testing::NotNull;
using InputEventState = WebThreadScheduler::InputEventState;
using base::sequence_manager::FakeTask;
using base::sequence_manager::FakeTaskTiming;
-enum class AntiStarvationLogic {
- kEnabled,
- kDisabled,
-};
-
-std::string ToString(AntiStarvationLogic type) {
- switch (type) {
- case AntiStarvationLogic::kEnabled:
- return "AntiStarvationLogicEnabled";
- case AntiStarvationLogic::kDisabled:
- return "AntiStarvationLogicDisabled";
- }
-}
-
-std::string GetTestNameSuffix(
- const testing::TestParamInfo<AntiStarvationLogic>& info) {
- return "With" + ToString(info.param);
-}
-
class FakeInputEvent : public blink::WebInputEvent {
public:
explicit FakeInputEvent(blink::WebInputEvent::Type event_type,
int modifiers = WebInputEvent::kNoModifiers)
- : WebInputEvent(sizeof(FakeInputEvent),
- event_type,
+ : WebInputEvent(event_type,
modifiers,
WebInputEvent::GetStaticTimeStampForTests()) {}
+
+ std::unique_ptr<WebInputEvent> Clone() const override {
+ return std::make_unique<FakeInputEvent>(*this);
+ }
};
class FakeTouchEvent : public blink::WebTouchEvent {
@@ -254,7 +239,6 @@ class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
using MainThreadSchedulerImpl::ControlTaskQueue;
using MainThreadSchedulerImpl::DefaultTaskQueue;
using MainThreadSchedulerImpl::EstimateLongestJankFreeTaskDuration;
- using MainThreadSchedulerImpl::InputTaskQueue;
using MainThreadSchedulerImpl::OnIdlePeriodEnded;
using MainThreadSchedulerImpl::OnIdlePeriodStarted;
using MainThreadSchedulerImpl::OnPendingTasksChanged;
@@ -332,8 +316,7 @@ class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
return os << MainThreadSchedulerImpl::UseCaseToString(use_case);
}
-class MainThreadSchedulerImplTest
- : public testing::TestWithParam<AntiStarvationLogic> {
+class MainThreadSchedulerImplTest : public testing::Test {
public:
MainThreadSchedulerImplTest(std::vector<base::Feature> features_to_enable,
std::vector<base::Feature> features_to_disable) {
@@ -341,8 +324,7 @@ class MainThreadSchedulerImplTest
}
MainThreadSchedulerImplTest()
- : MainThreadSchedulerImplTest({kHighPriorityInputOnMainThread},
- {kPrioritizeCompositingAfterInput}) {}
+ : MainThreadSchedulerImplTest({}, {kPrioritizeCompositingAfterInput}) {}
~MainThreadSchedulerImplTest() override = default;
@@ -353,8 +335,6 @@ class MainThreadSchedulerImplTest
nullptr, test_task_runner_, test_task_runner_->GetMockTickClock(),
base::sequence_manager::SequenceManager::Settings::Builder()
.SetRandomisedSamplingEnabled(true)
- .SetAntiStarvationLogicForPrioritiesDisabled(
- GetParam() == AntiStarvationLogic::kDisabled)
.Build()),
base::nullopt));
if (initially_ensure_usecase_none_)
@@ -381,7 +361,6 @@ class MainThreadSchedulerImplTest
default_task_runner_ = scheduler_->DefaultTaskQueue()->task_runner();
compositor_task_runner_ = scheduler_->CompositorTaskQueue()->task_runner();
- input_task_runner_ = scheduler_->InputTaskQueue()->task_runner();
idle_task_runner_ = scheduler_->IdleTaskRunner();
v8_task_runner_ = scheduler_->V8TaskQueue()->task_runner();
@@ -391,12 +370,17 @@ class MainThreadSchedulerImplTest
FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr, nullptr,
FrameScheduler::FrameType::kMainFrame);
+ widget_scheduler_ = scheduler_->CreateWidgetScheduler();
+ input_task_runner_ = widget_scheduler_->InputTaskRunner();
+
loading_control_task_runner_ =
main_frame_scheduler_->FrameTaskQueueControllerForTest()
->GetTaskQueue(
main_frame_scheduler_->LoadingControlTaskQueueTraits())
->task_runner();
timer_task_runner_ = timer_task_queue()->task_runner();
+ find_in_page_task_runner_ = main_frame_scheduler_->GetTaskRunner(
+ blink::TaskType::kInternalFindInPage);
}
TaskQueue* loading_task_queue() {
@@ -414,7 +398,17 @@ class MainThreadSchedulerImplTest
.get();
}
+ MainThreadTaskQueue* find_in_page_task_queue() {
+ auto* frame_task_queue_controller =
+ main_frame_scheduler_->FrameTaskQueueControllerForTest();
+
+ return frame_task_queue_controller
+ ->GetTaskQueue(main_frame_scheduler_->FindInPageTaskQueueTraits())
+ .get();
+ }
+
void TearDown() override {
+ widget_scheduler_.reset();
main_frame_scheduler_.reset();
page_scheduler_.reset();
scheduler_->Shutdown();
@@ -768,6 +762,11 @@ class MainThreadSchedulerImplTest
FROM_HERE, base::BindOnce(&AppendToVectorTestTask, run_order,
String::FromUTF8(task)));
break;
+ case 'F':
+ find_in_page_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&AppendToVectorTestTask, run_order,
+ String::FromUTF8(task)));
+ break;
default:
NOTREACHED();
}
@@ -846,6 +845,7 @@ class MainThreadSchedulerImplTest
std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_;
std::unique_ptr<PageSchedulerImpl> page_scheduler_;
std::unique_ptr<FrameSchedulerImpl> main_frame_scheduler_;
+ std::unique_ptr<WebWidgetScheduler> widget_scheduler_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
@@ -854,6 +854,7 @@ class MainThreadSchedulerImplTest
scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> v8_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> find_in_page_task_runner_;
bool simulate_timer_task_ran_;
bool initially_ensure_usecase_none_ = true;
uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
@@ -861,13 +862,7 @@ class MainThreadSchedulerImplTest
DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplTest);
};
-INSTANTIATE_TEST_SUITE_P(All,
- MainThreadSchedulerImplTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(MainThreadSchedulerImplTest, TestPostDefaultTask) {
+TEST_F(MainThreadSchedulerImplTest, TestPostDefaultTask) {
Vector<String> run_order;
PostTestTasks(&run_order, "D1 D2 D3 D4");
@@ -875,7 +870,7 @@ TEST_P(MainThreadSchedulerImplTest, TestPostDefaultTask) {
EXPECT_THAT(run_order, testing::ElementsAre("D1", "D2", "D3", "D4"));
}
-TEST_P(MainThreadSchedulerImplTest, TestPostDefaultAndCompositor) {
+TEST_F(MainThreadSchedulerImplTest, TestPostDefaultAndCompositor) {
Vector<String> run_order;
PostTestTasks(&run_order, "D1 C1 P1");
base::RunLoop().RunUntilIdle();
@@ -884,7 +879,7 @@ TEST_P(MainThreadSchedulerImplTest, TestPostDefaultAndCompositor) {
EXPECT_THAT(run_order, testing::Contains("P1"));
}
-TEST_P(MainThreadSchedulerImplTest, TestRentrantTask) {
+TEST_F(MainThreadSchedulerImplTest, TestRentrantTask) {
int count = 0;
Vector<int> run_order;
default_task_runner_->PostTask(
@@ -896,7 +891,7 @@ TEST_P(MainThreadSchedulerImplTest, TestRentrantTask) {
EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4));
}
-TEST_P(MainThreadSchedulerImplTest, TestPostIdleTask) {
+TEST_F(MainThreadSchedulerImplTest, TestPostIdleTask) {
int run_count = 0;
base::TimeTicks expected_deadline =
Now() + base::TimeDelta::FromMilliseconds(2300);
@@ -935,7 +930,7 @@ TEST_P(MainThreadSchedulerImplTest, TestPostIdleTask) {
EXPECT_EQ(expected_deadline, deadline_in_task);
}
-TEST_P(MainThreadSchedulerImplTest, TestRepostingIdleTask) {
+TEST_F(MainThreadSchedulerImplTest, TestRepostingIdleTask) {
int run_count = 0;
g_max_idle_task_reposts = 2;
@@ -956,7 +951,7 @@ TEST_P(MainThreadSchedulerImplTest, TestRepostingIdleTask) {
EXPECT_EQ(2, run_count);
}
-TEST_P(MainThreadSchedulerImplTest, TestIdleTaskExceedsDeadline) {
+TEST_F(MainThreadSchedulerImplTest, TestIdleTaskExceedsDeadline) {
int run_count = 0;
// Post two UpdateClockToDeadlineIdleTestTask tasks.
@@ -978,7 +973,7 @@ TEST_P(MainThreadSchedulerImplTest, TestIdleTaskExceedsDeadline) {
EXPECT_EQ(2, run_count);
}
-TEST_P(MainThreadSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) {
+TEST_F(MainThreadSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) {
int run_count = 0;
base::TimeTicks deadline_in_task;
@@ -1018,7 +1013,7 @@ TEST_P(MainThreadSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) {
EXPECT_EQ(1, run_count); // We should still be in the new idle period.
}
-TEST_P(MainThreadSchedulerImplTest, TestDefaultPolicy) {
+TEST_F(MainThreadSchedulerImplTest, TestDefaultPolicy) {
EnsureUseCaseNone();
Vector<String> run_order;
@@ -1034,7 +1029,7 @@ TEST_P(MainThreadSchedulerImplTest, TestDefaultPolicy) {
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest, TestDefaultPolicyWithSlowCompositor) {
+TEST_F(MainThreadSchedulerImplTest, TestDefaultPolicyWithSlowCompositor) {
RunSlowCompositorTask();
Vector<String> run_order;
@@ -1048,7 +1043,7 @@ TEST_P(MainThreadSchedulerImplTest, TestDefaultPolicyWithSlowCompositor) {
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1062,7 +1057,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_MainThreadHandlesInput_WithoutScrollUpdates) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1076,7 +1071,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_MainThreadHandlesInput_WithoutPreventDefault) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1090,7 +1085,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_CompositorHandlesInput_LongGestureDuration) {
EnableIdleTasks();
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
@@ -1120,7 +1115,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_CompositorHandlesInput_WithoutTouchHandler) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1133,7 +1128,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_MainThreadHandlesInput_WithTouchHandler) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1151,7 +1146,7 @@ TEST_P(MainThreadSchedulerImplTest,
WebInputEventResult::kHandledSystem);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_MainThreadHandlesInput_WithoutTouchHandler) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1168,7 +1163,7 @@ TEST_P(MainThreadSchedulerImplTest,
WebInputEventResult::kHandledSystem);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_MainThreadHandlesInput_SingleEvent_PreventDefault) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
@@ -1189,7 +1184,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
}
-TEST_P(
+TEST_F(
MainThreadSchedulerImplTest,
TestCompositorPolicy_MainThreadHandlesInput_SingleEvent_NoPreventDefault) {
Vector<String> run_order;
@@ -1210,7 +1205,7 @@ TEST_P(
EXPECT_EQ(UseCase::kTouchstart, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
+TEST_F(MainThreadSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
@@ -1226,7 +1221,7 @@ TEST_P(MainThreadSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
+TEST_F(MainThreadSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
Vector<String> run_order;
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
@@ -1245,7 +1240,7 @@ TEST_P(MainThreadSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
EXPECT_THAT(run_order, testing::ElementsAre("C1", "T1"));
}
-TEST_P(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {
+TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 D1 C1 D2 C2 T1 T2");
@@ -1282,7 +1277,7 @@ TEST_P(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {
EXPECT_THAT(run_order, testing::ElementsAre("L1", "T1", "T2"));
}
-TEST_P(MainThreadSchedulerImplTest, TestTouchstartPolicy_MainThread) {
+TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_MainThread) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 D1 C1 D2 C2 T1 T2");
@@ -1336,13 +1331,7 @@ class DefaultUseCaseTest : public MainThreadSchedulerImplTest {
}
};
-INSTANTIATE_TEST_SUITE_P(All,
- DefaultUseCaseTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(DefaultUseCaseTest, InitiallyInEarlyLoadingUseCase) {
+TEST_F(DefaultUseCaseTest, InitiallyInEarlyLoadingUseCase) {
// Should be early loading by default.
EXPECT_EQ(UseCase::kEarlyLoading, ForceUpdatePolicyAndGetCurrentUseCase());
@@ -1362,7 +1351,7 @@ class PrioritizeCompositingAndLoadingInUseCaseLoadingTest
{}) {}
};
-TEST_P(PrioritizeCompositingAndLoadingInUseCaseLoadingTest, LoadingUseCase) {
+TEST_F(PrioritizeCompositingAndLoadingInUseCaseLoadingTest, LoadingUseCase) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
@@ -1386,15 +1375,8 @@ TEST_P(PrioritizeCompositingAndLoadingInUseCaseLoadingTest, LoadingUseCase) {
EnableIdleTasks();
base::RunLoop().RunUntilIdle();
- String default_order_expected[] = {"D1",
- "C1"
- "T1",
- "L1",
- "D2",
- "C2",
- "T2",
- "L2",
- "I1"};
+ String default_order_expected[] = {"D1", "C1", "T1", "L1", "D2",
+ "C2", "T2", "L2", "I1"};
EXPECT_THAT(run_order, testing::ElementsAreArray(default_order_expected));
EXPECT_EQ(UseCase::kLoading, CurrentUseCase());
@@ -1413,7 +1395,7 @@ TEST_P(PrioritizeCompositingAndLoadingInUseCaseLoadingTest, LoadingUseCase) {
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventConsumedOnCompositorThread_IgnoresMouseMove_WhenMouseUp) {
RunSlowCompositorTask();
@@ -1430,7 +1412,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_THAT(run_order, testing::ElementsAre("D1", "C1", "D2", "C2", "I1"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventForwardedToMainThread_IgnoresMouseMove_WhenMouseUp) {
RunSlowCompositorTask();
@@ -1447,7 +1429,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_THAT(run_order, testing::ElementsAre("D1", "C1", "D2", "C2", "I1"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventConsumedOnCompositorThread_MouseMove_WhenMouseDown) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
@@ -1465,7 +1447,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_THAT(run_order, testing::ElementsAre("D1", "D2", "C1", "C2", "I1"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventForwardedToMainThread_MouseMove_WhenMouseDown) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
@@ -1484,7 +1466,7 @@ TEST_P(MainThreadSchedulerImplTest,
WebInputEventResult::kHandledSystem);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventForwardedToMainThread_MouseMove_WhenMouseDown_AfterMouseWheel) {
// Simulate a main thread driven mouse wheel scroll gesture.
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
@@ -1515,7 +1497,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_THAT(run_order, testing::ElementsAre("C1", "C2", "D1", "D2", "I1"));
}
-TEST_P(MainThreadSchedulerImplTest, EventForwardedToMainThread_MouseClick) {
+TEST_F(MainThreadSchedulerImplTest, EventForwardedToMainThread_MouseClick) {
// A mouse click should be detected as main thread input handling, which means
// we won't try to defer expensive tasks because of one. We can, however,
// prioritize compositing/input handling.
@@ -1539,7 +1521,7 @@ TEST_P(MainThreadSchedulerImplTest, EventForwardedToMainThread_MouseClick) {
EXPECT_THAT(run_order, testing::ElementsAre("C1", "C2", "D1", "D2", "I1"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventConsumedOnCompositorThread_MouseWheel) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
@@ -1554,7 +1536,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventForwardedToMainThread_MouseWheel_PreventDefault) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
@@ -1569,7 +1551,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventForwardedToMainThread_NoPreventDefault) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2");
@@ -1593,7 +1575,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
}
-TEST_P(
+TEST_F(
MainThreadSchedulerImplTest,
EventForwardedToMainThreadAndBackToCompositor_MouseWheel_NoPreventDefault) {
Vector<String> run_order;
@@ -1618,7 +1600,7 @@ TEST_P(
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventConsumedOnCompositorThread_IgnoresKeyboardEvents) {
RunSlowCompositorTask();
@@ -1635,7 +1617,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EventForwardedToMainThread_IgnoresKeyboardEvents) {
RunSlowCompositorTask();
@@ -1656,7 +1638,7 @@ TEST_P(MainThreadSchedulerImplTest,
WebInputEventResult::kHandledSystem);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestMainthreadScrollingUseCaseDoesNotStarveDefaultTasks) {
SimulateMainThreadGestureStart(TouchEventPolicy::kDontSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
@@ -1675,21 +1657,10 @@ TEST_P(MainThreadSchedulerImplTest,
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
base::RunLoop().RunUntilIdle();
- switch (GetParam()) {
- case AntiStarvationLogic::kEnabled:
- // Ensure that the default D1 task gets to run at some point before the
- // final C2 compositor task.
- EXPECT_THAT(run_order, testing::ElementsAre("C1", "D1", "C2"));
- break;
- case AntiStarvationLogic::kDisabled:
- // Without anti-starvation logic, the default D1 task should get stuck at
- // the end.
- EXPECT_THAT(run_order, testing::ElementsAre("C1", "C2", "D1"));
- break;
- }
+ EXPECT_THAT(run_order, testing::ElementsAre("C1", "C2", "D1"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicyEnds_CompositorHandlesInput) {
SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
EXPECT_EQ(UseCase::kCompositorGesture,
@@ -1699,7 +1670,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicyEnds_MainThreadHandlesInput) {
SimulateMainThreadGestureStart(TouchEventPolicy::kDontSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
@@ -1710,7 +1681,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {
+TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 D1 C1 D2 C2");
@@ -1732,7 +1703,7 @@ TEST_P(MainThreadSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {
EXPECT_THAT(run_order, testing::ElementsAre("L1", "D1", "D2"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestTouchstartPolicyEndsAfterConsecutiveTouchmoves) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 D1 C1 D2 C2");
@@ -1761,7 +1732,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_THAT(run_order, testing::ElementsAre("L1"));
}
-TEST_P(MainThreadSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
+TEST_F(MainThreadSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
bool is_anticipated_before = false;
bool is_anticipated_after = false;
@@ -1829,7 +1800,7 @@ TEST_P(MainThreadSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
EXPECT_FALSE(is_anticipated_after);
}
-TEST_P(MainThreadSchedulerImplTest, TestShouldYield) {
+TEST_F(MainThreadSchedulerImplTest, TestShouldYield) {
bool should_yield_before = false;
bool should_yield_after = false;
@@ -1863,7 +1834,7 @@ TEST_P(MainThreadSchedulerImplTest, TestShouldYield) {
EXPECT_TRUE(should_yield_after);
}
-TEST_P(MainThreadSchedulerImplTest, TestShouldYield_TouchStart) {
+TEST_F(MainThreadSchedulerImplTest, TestShouldYield_TouchStart) {
// Receiving a touchstart should immediately trigger yielding, even if
// there's no immediately pending work in the compositor queue.
EXPECT_FALSE(scheduler_->ShouldYieldForHighPriorityWork());
@@ -1874,7 +1845,7 @@ TEST_P(MainThreadSchedulerImplTest, TestShouldYield_TouchStart) {
base::RunLoop().RunUntilIdle();
}
-TEST_P(MainThreadSchedulerImplTest, SlowMainThreadInputEvent) {
+TEST_F(MainThreadSchedulerImplTest, SlowMainThreadInputEvent) {
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
// An input event should bump us into input priority.
@@ -1903,7 +1874,7 @@ TEST_P(MainThreadSchedulerImplTest, SlowMainThreadInputEvent) {
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest, OnlyOnePendingUrgentPolicyUpdate) {
+TEST_F(MainThreadSchedulerImplTest, OnlyOnePendingUrgentPolicyUpdate) {
for (int i = 0; i < 4; i++) {
scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
}
@@ -1911,7 +1882,7 @@ TEST_P(MainThreadSchedulerImplTest, OnlyOnePendingUrgentPolicyUpdate) {
EXPECT_EQ(1, scheduler_->update_policy_count_);
}
-TEST_P(MainThreadSchedulerImplTest, OnePendingDelayedAndOneUrgentUpdatePolicy) {
+TEST_F(MainThreadSchedulerImplTest, OnePendingDelayedAndOneUrgentUpdatePolicy) {
scheduler_->ScheduleDelayedPolicyUpdate(Now(),
base::TimeDelta::FromMilliseconds(1));
scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
@@ -1921,7 +1892,7 @@ TEST_P(MainThreadSchedulerImplTest, OnePendingDelayedAndOneUrgentUpdatePolicy) {
EXPECT_EQ(2, scheduler_->update_policy_count_);
}
-TEST_P(MainThreadSchedulerImplTest, OneUrgentAndOnePendingDelayedUpdatePolicy) {
+TEST_F(MainThreadSchedulerImplTest, OneUrgentAndOnePendingDelayedUpdatePolicy) {
scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
scheduler_->ScheduleDelayedPolicyUpdate(Now(),
base::TimeDelta::FromMilliseconds(1));
@@ -1931,7 +1902,7 @@ TEST_P(MainThreadSchedulerImplTest, OneUrgentAndOnePendingDelayedUpdatePolicy) {
EXPECT_EQ(2, scheduler_->update_policy_count_);
}
-TEST_P(MainThreadSchedulerImplTest, UpdatePolicyCountTriggeredByOneInputEvent) {
+TEST_F(MainThreadSchedulerImplTest, UpdatePolicyCountTriggeredByOneInputEvent) {
// We expect DidHandleInputEventOnCompositorThread to post an urgent policy
// update.
scheduler_->DidHandleInputEventOnCompositorThread(
@@ -1952,7 +1923,7 @@ TEST_P(MainThreadSchedulerImplTest, UpdatePolicyCountTriggeredByOneInputEvent) {
EXPECT_EQ(2, scheduler_->update_policy_count_);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
UpdatePolicyCountTriggeredByThreeInputEvents) {
// We expect DidHandleInputEventOnCompositorThread to post
// an urgent policy update.
@@ -2002,7 +1973,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(3, scheduler_->update_policy_count_);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
UpdatePolicyCountTriggeredByTwoInputEventsWithALongSeparatingDelay) {
// We expect DidHandleInputEventOnCompositorThread to post an urgent policy
// update.
@@ -2040,7 +2011,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(4, scheduler_->update_policy_count_);
}
-TEST_P(MainThreadSchedulerImplTest, EnsureUpdatePolicyNotTriggeredTooOften) {
+TEST_F(MainThreadSchedulerImplTest, EnsureUpdatePolicyNotTriggeredTooOften) {
EXPECT_EQ(0, scheduler_->update_policy_count_);
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EXPECT_EQ(1, scheduler_->update_policy_count_);
@@ -2094,7 +2065,7 @@ TEST_P(MainThreadSchedulerImplTest, EnsureUpdatePolicyNotTriggeredTooOften) {
"none blocking input expected", "none"));
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
BlockingInputExpectedSoonWhenBlockInputEventSeen) {
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
EXPECT_TRUE(HaveSeenABlockingGesture());
@@ -2102,7 +2073,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_TRUE(BlockingInputExpectedSoon());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
BlockingInputNotExpectedSoonWhenNoBlockInputEventSeen) {
SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
EXPECT_FALSE(HaveSeenABlockingGesture());
@@ -2110,7 +2081,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_FALSE(BlockingInputExpectedSoon());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
GetTaskExecutorForCurrentThreadInPostedTask) {
base::TaskExecutor* task_executor = base::GetTaskExecutorForCurrentThread();
EXPECT_THAT(task_executor, NotNull());
@@ -2126,36 +2097,7 @@ TEST_P(MainThreadSchedulerImplTest,
run_loop.Run();
}
-TEST_P(MainThreadSchedulerImplTest, CurrentThread) {
- EXPECT_EQ(scheduler_->DeprecatedDefaultTaskRunner(),
- base::CreateSingleThreadTaskRunner({base::CurrentThread()}));
-
- // base::TaskPriority is currently ignored in blink.
- EXPECT_EQ(scheduler_->DeprecatedDefaultTaskRunner(),
- base::CreateSingleThreadTaskRunner(
- {base::CurrentThread(), base::TaskPriority::BEST_EFFORT}));
-}
-
-TEST_P(MainThreadSchedulerImplTest, GetContinuationTaskRunner) {
- scoped_refptr<MainThreadTaskQueue> timer_tq = scheduler_->NewTimerTaskQueue(
- MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr);
- auto task_runner = timer_tq->CreateTaskRunner(TaskType::kJavascriptTimer);
-
- base::RunLoop run_loop;
- task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
- EXPECT_EQ(task_runner,
- base::GetContinuationTaskRunner());
- run_loop.Quit();
- }));
- run_loop.Run();
-}
-
-TEST_P(MainThreadSchedulerImplTest,
- GetContinuationTaskRunnerWithNoTaskRunning) {
- EXPECT_DCHECK_DEATH(base::GetContinuationTaskRunner());
-}
-
-TEST_P(MainThreadSchedulerImplTest, TestBeginMainFrameNotExpectedUntil) {
+TEST_F(MainThreadSchedulerImplTest, TestBeginMainFrameNotExpectedUntil) {
base::TimeDelta ten_millis(base::TimeDelta::FromMilliseconds(10));
base::TimeTicks expected_deadline = Now() + ten_millis;
base::TimeTicks deadline_in_task;
@@ -2177,7 +2119,7 @@ TEST_P(MainThreadSchedulerImplTest, TestBeginMainFrameNotExpectedUntil) {
EXPECT_EQ(expected_deadline, deadline_in_task);
}
-TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriod) {
+TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriod) {
base::TimeTicks expected_deadline = Now() + maximum_idle_period_duration();
base::TimeTicks deadline_in_task;
int run_count = 0;
@@ -2194,7 +2136,7 @@ TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriod) {
EXPECT_EQ(expected_deadline, deadline_in_task);
}
-TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {
+TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {
base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30);
base::TimeTicks expected_deadline = Now() + pending_task_delay;
base::TimeTicks deadline_in_task;
@@ -2211,7 +2153,7 @@ TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {
EXPECT_EQ(expected_deadline, deadline_in_task);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestLongIdlePeriodWithLatePendingDelayedTask) {
base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(10);
base::TimeTicks deadline_in_task;
@@ -2238,7 +2180,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(1, run_count);
}
-TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriodRepeating) {
+TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodRepeating) {
Vector<base::TimeTicks> actual_deadlines;
int run_count = 0;
@@ -2277,7 +2219,7 @@ TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriodRepeating) {
EXPECT_EQ(4, run_count);
}
-TEST_P(MainThreadSchedulerImplTest, TestLongIdlePeriodInTouchStartPolicy) {
+TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodInTouchStartPolicy) {
base::TimeTicks deadline_in_task;
int run_count = 0;
@@ -2305,7 +2247,7 @@ void TestCanExceedIdleDeadlineIfRequiredTask(ThreadScheduler* scheduler,
(*run_count)++;
}
-TEST_P(MainThreadSchedulerImplTest, CanExceedIdleDeadlineIfRequired) {
+TEST_F(MainThreadSchedulerImplTest, CanExceedIdleDeadlineIfRequired) {
int run_count = 0;
bool can_exceed_idle_deadline = false;
@@ -2355,7 +2297,7 @@ TEST_P(MainThreadSchedulerImplTest, CanExceedIdleDeadlineIfRequired) {
EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired());
}
-TEST_P(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {
+TEST_F(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {
int run_count = 0;
g_max_idle_task_reposts = 2;
@@ -2387,14 +2329,14 @@ TEST_P(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {
EXPECT_EQ(2, run_count);
}
-TEST_P(MainThreadSchedulerImplTest, TimerQueueEnabledByDefault) {
+TEST_F(MainThreadSchedulerImplTest, TimerQueueEnabledByDefault) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 T2");
base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2"));
}
-TEST_P(MainThreadSchedulerImplTest, StopAndResumeRenderer) {
+TEST_F(MainThreadSchedulerImplTest, StopAndResumeRenderer) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 T2");
@@ -2407,7 +2349,7 @@ TEST_P(MainThreadSchedulerImplTest, StopAndResumeRenderer) {
EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2"));
}
-TEST_P(MainThreadSchedulerImplTest, StopAndThrottleTimerQueue) {
+TEST_F(MainThreadSchedulerImplTest, StopAndThrottleTimerQueue) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 T2");
@@ -2419,7 +2361,7 @@ TEST_P(MainThreadSchedulerImplTest, StopAndThrottleTimerQueue) {
EXPECT_THAT(run_order, testing::ElementsAre());
}
-TEST_P(MainThreadSchedulerImplTest, ThrottleAndPauseRenderer) {
+TEST_F(MainThreadSchedulerImplTest, ThrottleAndPauseRenderer) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 T2");
@@ -2431,7 +2373,7 @@ TEST_P(MainThreadSchedulerImplTest, ThrottleAndPauseRenderer) {
EXPECT_THAT(run_order, testing::ElementsAre());
}
-TEST_P(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) {
+TEST_F(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 T2");
@@ -2454,7 +2396,7 @@ TEST_P(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) {
EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2"));
}
-TEST_P(MainThreadSchedulerImplTest, PauseRenderer) {
+TEST_F(MainThreadSchedulerImplTest, PauseRenderer) {
// Tasks in some queues don't fire when the renderer is paused.
Vector<String> run_order;
PostTestTasks(&run_order, "D1 C1 L1 I1 T1");
@@ -2470,11 +2412,11 @@ TEST_P(MainThreadSchedulerImplTest, PauseRenderer) {
EXPECT_THAT(run_order, testing::ElementsAre("L1", "T1"));
}
-TEST_P(MainThreadSchedulerImplTest, UseCaseToString) {
+TEST_F(MainThreadSchedulerImplTest, UseCaseToString) {
CheckAllUseCaseToString();
}
-TEST_P(MainThreadSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) {
+TEST_F(MainThreadSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) {
// This should not DCHECK because there was no corresponding compositor side
// call to DidHandleInputEventOnCompositorThread with
// INPUT_EVENT_ACK_STATE_NOT_CONSUMED. There are legitimate reasons for the
@@ -2484,7 +2426,7 @@ TEST_P(MainThreadSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) {
WebInputEventResult::kHandledSystem);
}
-TEST_P(MainThreadSchedulerImplTest, BeginMainFrameOnCriticalPath) {
+TEST_F(MainThreadSchedulerImplTest, BeginMainFrameOnCriticalPath) {
ASSERT_FALSE(scheduler_->BeginMainFrameOnCriticalPath());
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
@@ -2499,7 +2441,7 @@ TEST_P(MainThreadSchedulerImplTest, BeginMainFrameOnCriticalPath) {
ASSERT_FALSE(scheduler_->BeginMainFrameOnCriticalPath());
}
-TEST_P(MainThreadSchedulerImplTest, ShutdownPreventsPostingOfNewTasks) {
+TEST_F(MainThreadSchedulerImplTest, ShutdownPreventsPostingOfNewTasks) {
main_frame_scheduler_.reset();
page_scheduler_.reset();
scheduler_->Shutdown();
@@ -2509,7 +2451,7 @@ TEST_P(MainThreadSchedulerImplTest, ShutdownPreventsPostingOfNewTasks) {
EXPECT_THAT(run_order, testing::ElementsAre());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_NONE) {
EnsureUseCaseNone();
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
@@ -2517,7 +2459,7 @@ TEST_P(MainThreadSchedulerImplTest,
scheduler_->EstimateLongestJankFreeTaskDuration());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_kCompositorGesture) {
SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
EXPECT_EQ(UseCase::kCompositorGesture,
@@ -2526,7 +2468,7 @@ TEST_P(MainThreadSchedulerImplTest,
scheduler_->EstimateLongestJankFreeTaskDuration());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_EarlyLoading) {
scheduler_->DidStartProvisionalLoad(true);
EXPECT_EQ(UseCase::kEarlyLoading, ForceUpdatePolicyAndGetCurrentUseCase());
@@ -2534,7 +2476,7 @@ TEST_P(MainThreadSchedulerImplTest,
scheduler_->EstimateLongestJankFreeTaskDuration());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_Loading) {
scheduler_->DidStartProvisionalLoad(true);
scheduler_->OnFirstContentfulPaint();
@@ -2543,7 +2485,7 @@ TEST_P(MainThreadSchedulerImplTest,
scheduler_->EstimateLongestJankFreeTaskDuration());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_MAIN_THREAD_GESTURE) {
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kGestureScrollUpdate);
@@ -2569,7 +2511,7 @@ TEST_P(MainThreadSchedulerImplTest,
scheduler_->EstimateLongestJankFreeTaskDuration());
}
-TEST_P(
+TEST_F(
MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
@@ -2594,7 +2536,7 @@ TEST_P(
scheduler_->EstimateLongestJankFreeTaskDuration());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_SYNCHRONIZED_GESTURE) {
SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
@@ -2654,7 +2596,7 @@ void SlowCountingTask(size_t* count,
}
} // namespace
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
SYNCHRONIZED_GESTURE_TimerTaskThrottling_TimersStopped) {
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
@@ -2711,7 +2653,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(2u, count);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
SYNCHRONIZED_GESTURE_TimerTaskThrottling_task_not_expensive) {
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
@@ -2749,7 +2691,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(500u, count);
}
-TEST_P(MainThreadSchedulerImplTest, DenyLongIdleDuringTouchStart) {
+TEST_F(MainThreadSchedulerImplTest, DenyLongIdleDuringTouchStart) {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
@@ -2769,7 +2711,7 @@ TEST_P(MainThreadSchedulerImplTest, DenyLongIdleDuringTouchStart) {
EXPECT_GE(next_time_to_check, base::TimeDelta());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_TouchStartDuringFling) {
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
scheduler_->DidAnimateForInputOnCompositorThread();
@@ -2785,7 +2727,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kTouchstart, ForceUpdatePolicyAndGetCurrentUseCase());
}
-TEST_P(MainThreadSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
+TEST_F(MainThreadSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
// With the compositor task taking 20ms, there is not enough time to run
@@ -2824,7 +2766,7 @@ TEST_P(MainThreadSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
EXPECT_EQ(1000u, run_order.size());
}
-TEST_P(MainThreadSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
+TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
@@ -2865,7 +2807,7 @@ TEST_P(MainThreadSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
EXPECT_EQ(1000u, run_order.size());
}
-TEST_P(MainThreadSchedulerImplTest, MAIN_THREAD_GESTURE) {
+TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_GESTURE) {
SimulateMainThreadGestureStart(TouchEventPolicy::kDontSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
@@ -2909,7 +2851,7 @@ class MockRAILModeObserver : public RAILModeObserver {
MOCK_METHOD1(OnRAILModeChanged, void(RAILMode rail_mode));
};
-TEST_P(MainThreadSchedulerImplTest, TestResponseRAILMode) {
+TEST_F(MainThreadSchedulerImplTest, TestResponseRAILMode) {
MockRAILModeObserver observer;
scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(RAILMode::kResponse));
@@ -2921,7 +2863,7 @@ TEST_P(MainThreadSchedulerImplTest, TestResponseRAILMode) {
scheduler_->RemoveRAILModeObserver(&observer);
}
-TEST_P(MainThreadSchedulerImplTest, TestAnimateRAILMode) {
+TEST_F(MainThreadSchedulerImplTest, TestAnimateRAILMode) {
MockRAILModeObserver observer;
scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(RAILMode::kAnimation)).Times(0);
@@ -2932,7 +2874,7 @@ TEST_P(MainThreadSchedulerImplTest, TestAnimateRAILMode) {
scheduler_->RemoveRAILModeObserver(&observer);
}
-TEST_P(MainThreadSchedulerImplTest, TestIdleRAILMode) {
+TEST_F(MainThreadSchedulerImplTest, TestIdleRAILMode) {
MockRAILModeObserver observer;
scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(RAILMode::kAnimation));
@@ -2947,7 +2889,7 @@ TEST_P(MainThreadSchedulerImplTest, TestIdleRAILMode) {
scheduler_->RemoveRAILModeObserver(&observer);
}
-TEST_P(MainThreadSchedulerImplTest, TestLoadRAILMode) {
+TEST_F(MainThreadSchedulerImplTest, TestLoadRAILMode) {
MockRAILModeObserver observer;
scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(RAILMode::kAnimation));
@@ -2964,7 +2906,7 @@ TEST_P(MainThreadSchedulerImplTest, TestLoadRAILMode) {
scheduler_->RemoveRAILModeObserver(&observer);
}
-TEST_P(MainThreadSchedulerImplTest, InputTerminatesLoadRAILMode) {
+TEST_F(MainThreadSchedulerImplTest, InputTerminatesLoadRAILMode) {
MockRAILModeObserver observer;
scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(RAILMode::kAnimation));
@@ -2985,7 +2927,7 @@ TEST_P(MainThreadSchedulerImplTest, InputTerminatesLoadRAILMode) {
scheduler_->RemoveRAILModeObserver(&observer);
}
-TEST_P(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {
+TEST_F(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {
// Ensure neither suspension nor timer task throttling affects an unthrottled
// task runner.
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
@@ -3030,7 +2972,7 @@ TEST_P(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {
EXPECT_EQ(500u, unthrottled_count);
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
VirtualTimePolicyDoesNotAffectNewTimerTaskQueueIfVirtualTimeNotEnabled) {
scheduler_->SetVirtualTimePolicy(
PageSchedulerImpl::VirtualTimePolicy::kPause);
@@ -3039,7 +2981,7 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_FALSE(timer_tq->HasActiveFence());
}
-TEST_P(MainThreadSchedulerImplTest, EnableVirtualTime) {
+TEST_F(MainThreadSchedulerImplTest, EnableVirtualTime) {
EXPECT_FALSE(scheduler_->IsVirtualTimeEnabled());
scheduler_->EnableVirtualTime(
MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
@@ -3101,7 +3043,7 @@ TEST_P(MainThreadSchedulerImplTest, EnableVirtualTime) {
scheduler_->GetVirtualTimeDomain());
}
-TEST_P(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
+TEST_F(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
std::unique_ptr<PageSchedulerImpl> page_scheduler =
base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get()));
scheduler_->AddPageScheduler(page_scheduler.get());
@@ -3112,7 +3054,7 @@ TEST_P(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
TaskQueue* timer_tq = ThrottleableTaskQueue(frame_scheduler.get()).get();
- frame_scheduler->SetCrossOrigin(true);
+ frame_scheduler->SetCrossOriginToMainFrame(true);
frame_scheduler->SetFrameVisible(false);
EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(timer_tq));
@@ -3122,7 +3064,7 @@ TEST_P(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled(timer_tq));
}
-TEST_P(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) {
+TEST_F(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) {
scheduler_->EnableVirtualTime(
MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
@@ -3148,7 +3090,7 @@ TEST_P(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) {
EXPECT_FALSE(scheduler_->VirtualTimeControlTaskQueue());
}
-TEST_P(MainThreadSchedulerImplTest, VirtualTimePauser) {
+TEST_F(MainThreadSchedulerImplTest, VirtualTimePauser) {
scheduler_->EnableVirtualTime(
MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
scheduler_->SetVirtualTimePolicy(
@@ -3169,7 +3111,7 @@ TEST_P(MainThreadSchedulerImplTest, VirtualTimePauser) {
EXPECT_EQ(after, before);
}
-TEST_P(MainThreadSchedulerImplTest, VirtualTimePauserNonInstantTask) {
+TEST_F(MainThreadSchedulerImplTest, VirtualTimePauserNonInstantTask) {
scheduler_->EnableVirtualTime(
MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE);
scheduler_->SetVirtualTimePolicy(
@@ -3186,7 +3128,7 @@ TEST_P(MainThreadSchedulerImplTest, VirtualTimePauserNonInstantTask) {
EXPECT_GT(after, before);
}
-TEST_P(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) {
+TEST_F(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) {
// This test ensures that we do not do anything strange like stopping
// processing task queues after we encountered one task queue with
// DoNotUseVirtualTime trait.
@@ -3232,7 +3174,7 @@ TEST_P(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) {
EXPECT_EQ(counter, kTaskQueueCount);
}
-TEST_P(MainThreadSchedulerImplTest, Tracing) {
+TEST_F(MainThreadSchedulerImplTest, Tracing) {
// This test sets renderer scheduler to some non-trivial state
// (by posting tasks, creating child schedulers, etc) and converts it into a
// traced value. This test checks that no internal checks fire during this.
@@ -3260,10 +3202,7 @@ TEST_P(MainThreadSchedulerImplTest, Tracing) {
FROM_HERE, base::BindOnce(NullTask),
base::TimeDelta::FromMilliseconds(10));
- std::unique_ptr<base::trace_event::ConvertableToTraceFormat> value =
- scheduler_->AsValue(base::TimeTicks());
- EXPECT_TRUE(value);
- EXPECT_FALSE(value->ToString().empty());
+ EXPECT_FALSE(scheduler_->ToString().empty());
}
void RecordingTimeTestTask(
@@ -3285,7 +3224,7 @@ void RecordingTimeTestTask(
//
// MaxEQT1 = 500ms is recorded and observed in histogram.
// MaxEQT2 is recorded but not yet in histogram for not being flushed.
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
MaxQueueingTimeMetricRecordedOnlyDuringNavigation) {
base::HistogramTester tester;
// Start with a long task whose queueing time will be ignored.
@@ -3305,7 +3244,7 @@ TEST_P(MainThreadSchedulerImplTest,
}
// Only the max of all the queueing times is recorded.
-TEST_P(MainThreadSchedulerImplTest, MaxQueueingTimeMetricRecordTheMax) {
+TEST_F(MainThreadSchedulerImplTest, MaxQueueingTimeMetricRecordTheMax) {
base::HistogramTester tester;
scheduler_->DidCommitProvisionalLoad(false, false, false);
// The smaller queuing time will be ignored.
@@ -3318,7 +3257,7 @@ TEST_P(MainThreadSchedulerImplTest, MaxQueueingTimeMetricRecordTheMax) {
tester.ExpectUniqueSample("RendererScheduler.MaxQueueingTime", 500, 1);
}
-TEST_P(MainThreadSchedulerImplTest, DidCommitProvisionalLoad) {
+TEST_F(MainThreadSchedulerImplTest, DidCommitProvisionalLoad) {
scheduler_->OnFirstMeaningfulPaint();
EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
@@ -3372,7 +3311,7 @@ TEST_P(MainThreadSchedulerImplTest, DidCommitProvisionalLoad) {
EXPECT_TRUE(scheduler_->waiting_for_meaningful_paint()); // State cleared.
}
-TEST_P(MainThreadSchedulerImplTest, LoadingControlTasks) {
+TEST_F(MainThreadSchedulerImplTest, LoadingControlTasks) {
// Expect control loading tasks (M) to jump ahead of any regular loading
// tasks (L).
Vector<String> run_order;
@@ -3382,7 +3321,7 @@ TEST_P(MainThreadSchedulerImplTest, LoadingControlTasks) {
"L4", "L5", "L6"));
}
-TEST_P(MainThreadSchedulerImplTest, RequestBeginMainFrameNotExpected) {
+TEST_F(MainThreadSchedulerImplTest, RequestBeginMainFrameNotExpected) {
std::unique_ptr<PageSchedulerImplForTest> page_scheduler =
std::make_unique<PageSchedulerImplForTest>(scheduler_.get());
scheduler_->AddPageScheduler(page_scheduler.get());
@@ -3404,7 +3343,7 @@ TEST_P(MainThreadSchedulerImplTest, RequestBeginMainFrameNotExpected) {
Mock::VerifyAndClearExpectations(page_scheduler.get());
}
-TEST_P(MainThreadSchedulerImplTest,
+TEST_F(MainThreadSchedulerImplTest,
RequestBeginMainFrameNotExpected_MultipleCalls) {
std::unique_ptr<PageSchedulerImplForTest> page_scheduler =
std::make_unique<PageSchedulerImplForTest>(scheduler_.get());
@@ -3422,7 +3361,7 @@ TEST_P(MainThreadSchedulerImplTest,
}
#if defined(OS_ANDROID)
-TEST_P(MainThreadSchedulerImplTest, PauseTimersForAndroidWebView) {
+TEST_F(MainThreadSchedulerImplTest, PauseTimersForAndroidWebView) {
// Tasks in some queues don't fire when the timers are paused.
Vector<String> run_order;
PostTestTasks(&run_order, "D1 C1 L1 I1 T1");
@@ -3448,20 +3387,12 @@ class MainThreadSchedulerImplWithInitalVirtualTimeTest
nullptr, test_task_runner_, test_task_runner_->GetMockTickClock(),
base::sequence_manager::SequenceManager::Settings::Builder()
.SetRandomisedSamplingEnabled(true)
- .SetAntiStarvationLogicForPrioritiesDisabled(
- GetParam() == AntiStarvationLogic::kDisabled)
.Build()),
base::Time::FromJsTime(1000000.0)));
}
};
-INSTANTIATE_TEST_SUITE_P(All,
- MainThreadSchedulerImplWithInitalVirtualTimeTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(MainThreadSchedulerImplWithInitalVirtualTimeTest, VirtualTimeOverride) {
+TEST_F(MainThreadSchedulerImplWithInitalVirtualTimeTest, VirtualTimeOverride) {
EXPECT_TRUE(scheduler_->IsVirtualTimeEnabled());
EXPECT_EQ(PageSchedulerImpl::VirtualTimePolicy::kPause,
scheduler_->virtual_time_policy());
@@ -3473,19 +3404,13 @@ class CompositingExperimentWithExplicitSignalsTest
public:
CompositingExperimentWithExplicitSignalsTest()
: MainThreadSchedulerImplTest(
- {kHighPriorityInputOnMainThread, kPrioritizeCompositingAfterInput,
+ {kPrioritizeCompositingAfterInput,
kUseExplicitSignalForTriggeringCompositingPrioritization,
kUseWillBeginMainFrameForCompositingPrioritization},
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(All,
- CompositingExperimentWithExplicitSignalsTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(CompositingExperimentWithExplicitSignalsTest, CompositingAfterInput) {
+TEST_F(CompositingExperimentWithExplicitSignalsTest, CompositingAfterInput) {
Vector<String> run_order;
PostTestTasks(&run_order, "P1 T1 C1");
base::RunLoop().RunUntilIdle();
@@ -3515,19 +3440,13 @@ class CompositingExperimentWithImplicitSignalsTest
public:
CompositingExperimentWithImplicitSignalsTest()
: MainThreadSchedulerImplTest(
- {kHighPriorityInputOnMainThread, kPrioritizeCompositingAfterInput},
+ {kPrioritizeCompositingAfterInput},
{kHighestPriorityForCompositingAfterInput,
kUseExplicitSignalForTriggeringCompositingPrioritization,
kUseWillBeginMainFrameForCompositingPrioritization}) {}
};
-INSTANTIATE_TEST_SUITE_P(All,
- CompositingExperimentWithImplicitSignalsTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(CompositingExperimentWithImplicitSignalsTest, CompositingAfterInput) {
+TEST_F(CompositingExperimentWithImplicitSignalsTest, CompositingAfterInput) {
Vector<String> run_order;
PostTestTasks(&run_order, "T1 C1 C2 P1 P2");
base::RunLoop().RunUntilIdle();
@@ -3535,7 +3454,7 @@ TEST_P(CompositingExperimentWithImplicitSignalsTest, CompositingAfterInput) {
EXPECT_THAT(run_order, testing::ElementsAre("P1", "P2", "C1", "T1", "C2"));
}
-TEST_P(MainThreadSchedulerImplTest, EQTWithNestedLoop) {
+TEST_F(MainThreadSchedulerImplTest, EQTWithNestedLoop) {
AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(100));
RunTask(base::BindLambdaForTesting([&] {
@@ -3574,7 +3493,7 @@ TEST_P(MainThreadSchedulerImplTest, EQTWithNestedLoop) {
base::TimeDelta::FromMicroseconds(400 + 50 + 50 + 1250)));
}
-TEST_P(MainThreadSchedulerImplTest, TaskQueueReferenceClearedOnShutdown) {
+TEST_F(MainThreadSchedulerImplTest, TaskQueueReferenceClearedOnShutdown) {
// Ensure that the scheduler clears its references to a task queue after
// |shutdown| and doesn't try to update its policies.
scoped_refptr<MainThreadTaskQueue> queue1 = scheduler_->NewTimerTaskQueue(
@@ -3596,7 +3515,7 @@ TEST_P(MainThreadSchedulerImplTest, TaskQueueReferenceClearedOnShutdown) {
EXPECT_EQ(queue2->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
}
-TEST_P(MainThreadSchedulerImplTest, MicrotaskCheckpointTiming) {
+TEST_F(MainThreadSchedulerImplTest, MicrotaskCheckpointTiming) {
base::RunLoop().RunUntilIdle();
base::TimeTicks start_time = Now();
@@ -3623,7 +3542,7 @@ TEST_P(MainThreadSchedulerImplTest, MicrotaskCheckpointTiming) {
observer.result().front().second);
}
-TEST_P(MainThreadSchedulerImplTest, IsBeginMainFrameScheduled) {
+TEST_F(MainThreadSchedulerImplTest, IsBeginMainFrameScheduled) {
EXPECT_FALSE(scheduler_->IsBeginMainFrameScheduled());
scheduler_->DidScheduleBeginMainFrame();
EXPECT_TRUE(scheduler_->IsBeginMainFrameScheduled());
@@ -3638,6 +3557,119 @@ TEST_P(MainThreadSchedulerImplTest, IsBeginMainFrameScheduled) {
EXPECT_FALSE(scheduler_->IsBeginMainFrameScheduled());
}
+TEST_F(MainThreadSchedulerImplTest, NonWakingTaskQueue) {
+ std::vector<std::pair<std::string, base::TimeTicks>> log;
+ base::TimeTicks start = scheduler_->GetTickClock()->NowTicks();
+
+ scheduler_->DefaultTaskQueue()->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](std::vector<std::pair<std::string, base::TimeTicks>>* log,
+ const base::TickClock* clock) {
+ log->emplace_back("regular (immediate)", clock->NowTicks());
+ },
+ &log, scheduler_->GetTickClock()));
+ scheduler_->NonWakingTaskRunner()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](std::vector<std::pair<std::string, base::TimeTicks>>* log,
+ const base::TickClock* clock) {
+ log->emplace_back("non-waking", clock->NowTicks());
+ },
+ &log, scheduler_->GetTickClock()),
+ base::TimeDelta::FromSeconds(3));
+ scheduler_->DefaultTaskQueue()->task_runner()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](std::vector<std::pair<std::string, base::TimeTicks>>* log,
+ const base::TickClock* clock) {
+ log->emplace_back("regular (delayed)", clock->NowTicks());
+ },
+ &log, scheduler_->GetTickClock()),
+ base::TimeDelta::FromSeconds(5));
+
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+
+ // Check that the non-waking task runner didn't generate an unnecessary
+ // wake-up.
+ // Note: the exact order of these tasks is not fixed and depends on the time
+ // domain iteration order.
+ EXPECT_THAT(
+ log,
+ testing::UnorderedElementsAre(
+ std::make_pair("regular (immediate)", start),
+ std::make_pair("non-waking", start + base::TimeDelta::FromSeconds(5)),
+ std::make_pair("regular (delayed)",
+ start + base::TimeDelta::FromSeconds(5))));
+}
+
+class BestEffortPriorityForFindInPageExperimentTest
+ : public MainThreadSchedulerImplTest {
+ public:
+ BestEffortPriorityForFindInPageExperimentTest()
+ : MainThreadSchedulerImplTest({kBestEffortPriorityForFindInPage}, {}) {}
+};
+
+TEST_F(BestEffortPriorityForFindInPageExperimentTest,
+ FindInPageTasksAreBestEffortPriorityUnderExperiment) {
+ Vector<String> run_order;
+ PostTestTasks(&run_order, "F1 D1 F2 D2 F3 D3");
+ EnableIdleTasks();
+ EXPECT_EQ(scheduler_->find_in_page_priority(),
+ QueuePriority::kBestEffortPriority);
+ base::RunLoop().RunUntilIdle();
+ // Find-in-page tasks have "best-effort" priority, so they will be done after
+ // the default tasks (which have normal priority).
+ EXPECT_THAT(run_order,
+ testing::ElementsAre("D1", "D2", "D3", "F1", "F2", "F3"));
+}
+
+TEST_F(MainThreadSchedulerImplTest, FindInPageTasksAreVeryHighPriority) {
+ Vector<String> run_order;
+ PostTestTasks(&run_order, "D1 D2 D3 F1 F2 F3");
+ EnableIdleTasks();
+ EXPECT_EQ(
+ scheduler_->find_in_page_priority(),
+ FindInPageBudgetPoolController::kFindInPageBudgetNotExhaustedPriority);
+ base::RunLoop().RunUntilIdle();
+ // Find-in-page tasks have very high task priority, so we will do them before
+ // the default tasks.
+ EXPECT_THAT(run_order,
+ testing::ElementsAre("F1", "F2", "F3", "D1", "D2", "D3"));
+}
+
+TEST_F(MainThreadSchedulerImplTest, FindInPageTasksChangeToNormalPriority) {
+ EXPECT_EQ(
+ scheduler_->find_in_page_priority(),
+ FindInPageBudgetPoolController::kFindInPageBudgetNotExhaustedPriority);
+ EnableIdleTasks();
+ // Simulate a really long find-in-page task that takes 30% of CPU time
+ // (300ms out of 1000 ms).
+ base::TimeTicks task_start_time = Now();
+ base::TimeTicks task_end_time =
+ task_start_time + base::TimeDelta::FromMilliseconds(300);
+ FakeTask fake_task;
+ fake_task.set_enqueue_order(
+ base::sequence_manager::EnqueueOrder::FromIntForTesting(42));
+ FakeTaskTiming task_timing(task_start_time, task_end_time);
+ scheduler_->OnTaskStarted(find_in_page_task_queue(), fake_task, task_timing);
+ AdvanceMockTickClockTo(task_start_time +
+ base::TimeDelta::FromMilliseconds(1000));
+ scheduler_->OnTaskCompleted(find_in_page_task_queue()->AsWeakPtr(), fake_task,
+ &task_timing, nullptr);
+
+ // Now the find-in-page tasks have normal priority (same priority as default
+ // tasks, so we will do them in order).
+ EXPECT_EQ(scheduler_->find_in_page_priority(),
+ FindInPageBudgetPoolController::kFindInPageBudgetExhaustedPriority);
+ Vector<String> run_order;
+ PostTestTasks(&run_order, "D1 D2 F1 F2 D3 F3");
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_THAT(run_order,
+ testing::ElementsAre("D1", "D2", "F1", "F2", "D3", "F3"));
+}
+
class VeryHighPriorityForCompositingAlwaysExperimentTest
: public MainThreadSchedulerImplTest {
public:
@@ -3646,13 +3678,7 @@ class VeryHighPriorityForCompositingAlwaysExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(All,
- VeryHighPriorityForCompositingAlwaysExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(VeryHighPriorityForCompositingAlwaysExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAlwaysExperimentTest,
TestCompositorPolicy) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
@@ -3672,13 +3698,7 @@ class VeryHighPriorityForCompositingWhenFastExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(All,
- VeryHighPriorityForCompositingWhenFastExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(VeryHighPriorityForCompositingWhenFastExperimentTest,
+TEST_F(VeryHighPriorityForCompositingWhenFastExperimentTest,
TestCompositorPolicy_FastCompositing) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
@@ -3690,7 +3710,7 @@ TEST_P(VeryHighPriorityForCompositingWhenFastExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingWhenFastExperimentTest,
+TEST_F(VeryHighPriorityForCompositingWhenFastExperimentTest,
TestCompositorPolicy_SlowCompositing) {
RunSlowCompositorTask();
Vector<String> run_order;
@@ -3703,7 +3723,7 @@ TEST_P(VeryHighPriorityForCompositingWhenFastExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingWhenFastExperimentTest,
+TEST_F(VeryHighPriorityForCompositingWhenFastExperimentTest,
TestCompositorPolicy_CompositingStaysAtHighest) {
Vector<String> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 P1 C2");
@@ -3727,14 +3747,7 @@ class VeryHighPriorityForCompositingAlternatingExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(
- All,
- VeryHighPriorityForCompositingAlternatingExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(VeryHighPriorityForCompositingAlternatingExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAlternatingExperimentTest,
TestCompositorPolicy_AlternatingCompositorTasks) {
Vector<String> run_order;
PostTestTasks(&run_order, "D1 D2 D3 C1 C2 C3");
@@ -3746,7 +3759,7 @@ TEST_P(VeryHighPriorityForCompositingAlternatingExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingAlternatingExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAlternatingExperimentTest,
TestCompositorPolicy_AlternatingCompositorStaysAtHighest) {
Vector<String> run_order;
PostTestTasks(&run_order, "D1 D2 D3 C1 C2 C3");
@@ -3769,13 +3782,7 @@ class VeryHighPriorityForCompositingAfterDelayExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(All,
- VeryHighPriorityForCompositingAfterDelayExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(VeryHighPriorityForCompositingAfterDelayExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAfterDelayExperimentTest,
TestCompositorPolicy_CompositorStaysAtNormalPriority) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
@@ -3787,7 +3794,7 @@ TEST_P(VeryHighPriorityForCompositingAfterDelayExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingAfterDelayExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAfterDelayExperimentTest,
TestCompositorPolicy_FirstCompositorTaskSetToVeryHighPriority) {
// 150ms task to complete the countdown and prioritze compositing.
AdvanceTimeWithTask(0.15);
@@ -3802,7 +3809,7 @@ TEST_P(VeryHighPriorityForCompositingAfterDelayExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingAfterDelayExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAfterDelayExperimentTest,
TestCompositorPolicy_FirstCompositorTaskStaysAtNormalPriority) {
// 0.5ms task should not prioritize compositing.
AdvanceTimeWithTask(0.05);
@@ -3825,13 +3832,7 @@ class VeryHighPriorityForCompositingBudgetExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(All,
- VeryHighPriorityForCompositingBudgetExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(VeryHighPriorityForCompositingBudgetExperimentTest,
+TEST_F(VeryHighPriorityForCompositingBudgetExperimentTest,
TestCompositorPolicy_CompositorPriorityVeryHighToNormal) {
Vector<String> run_order;
PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1");
@@ -3858,7 +3859,7 @@ TEST_P(VeryHighPriorityForCompositingBudgetExperimentTest,
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingBudgetExperimentTest,
+TEST_F(VeryHighPriorityForCompositingBudgetExperimentTest,
TestCompositorPolicy_CompositorPriorityNormalToVeryHigh) {
// 1000ms compositor task will exhaust the budget.
RunSlowCompositorTask();
@@ -3897,14 +3898,7 @@ class VeryHighPriorityForCompositingAlternatingBeginMainFrameExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(
- ,
- VeryHighPriorityForCompositingAlternatingBeginMainFrameExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(VeryHighPriorityForCompositingAlternatingBeginMainFrameExperimentTest,
+TEST_F(VeryHighPriorityForCompositingAlternatingBeginMainFrameExperimentTest,
TestCompositorPolicy_AlternatingCompositorTasks) {
Vector<String> run_order;
PostTestTasks(&run_order, "C1 D1 C2 D2");
@@ -3934,14 +3928,7 @@ class VeryHighPriorityForCompositingAfterDelayUntilBeginMainFrameExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(
- ,
- VeryHighPriorityForCompositingAfterDelayUntilBeginMainFrameExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(
+TEST_F(
VeryHighPriorityForCompositingAfterDelayUntilBeginMainFrameExperimentTest,
TestCompositorPolicy_FirstCompositorTaskSetToVeryHighPriority) {
// 150ms task to complete the countdown and prioritze compositing.
@@ -3973,14 +3960,7 @@ class VeryHighPriorityForCompositingBudgetBeginMainFrameExperimentTest
{}) {}
};
-INSTANTIATE_TEST_SUITE_P(
- ,
- VeryHighPriorityForCompositingBudgetBeginMainFrameExperimentTest,
- testing::Values(AntiStarvationLogic::kEnabled,
- AntiStarvationLogic::kDisabled),
- GetTestNameSuffix);
-
-TEST_P(
+TEST_F(
VeryHighPriorityForCompositingBudgetBeginMainFrameExperimentTest,
TestCompositorPolicy_CompositorPriorityNonBeginMainFrameDoesntExhaustBudget) {
// 1000ms compositor task will not exhaust the budget.
@@ -3994,7 +3974,7 @@ TEST_P(
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-TEST_P(VeryHighPriorityForCompositingBudgetBeginMainFrameExperimentTest,
+TEST_F(VeryHighPriorityForCompositingBudgetBeginMainFrameExperimentTest,
TestCompositorPolicy_CompositorPriorityBeginMainFrameExhaustsBudget) {
// 1000ms BeginMainFrame will exhaust the budget.
DoMainFrame();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
index d008643dc43..0d54d317672 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
@@ -63,6 +63,8 @@ const char* MainThreadTaskQueue::NameForQueueType(
return "other_tq";
case MainThreadTaskQueue::QueueType::kWebScheduling:
return "web_scheduling_tq";
+ case MainThreadTaskQueue::QueueType::kNonWaking:
+ return "non_waking_tq";
case MainThreadTaskQueue::QueueType::kCount:
NOTREACHED();
return nullptr;
@@ -95,6 +97,7 @@ bool MainThreadTaskQueue::IsPerFrameTaskQueue(
case MainThreadTaskQueue::QueueType::kInput:
case MainThreadTaskQueue::QueueType::kDetached:
case MainThreadTaskQueue::QueueType::kCleanup:
+ case MainThreadTaskQueue::QueueType::kNonWaking:
case MainThreadTaskQueue::QueueType::kOther:
return false;
case MainThreadTaskQueue::QueueType::kCount:
@@ -114,6 +117,7 @@ MainThreadTaskQueue::QueueClass MainThreadTaskQueue::QueueClassForQueueType(
case QueueType::kTest:
case QueueType::kV8:
case QueueType::kIPC:
+ case QueueType::kNonWaking:
case QueueType::kCleanup:
return QueueClass::kNone;
case QueueType::kFrameLoading:
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
index c1ea93cd184..b9c51d21ea8 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -76,10 +76,11 @@ class PLATFORM_EXPORT MainThreadTaskQueue
// 22 : kWebSchedulingBestEffort, obsolete.
kWebScheduling = 24,
+ kNonWaking = 25,
// Used to group multiple types when calculating Expected Queueing Time.
kOther = 23,
- kCount = 25
+ kCount = 26
};
// Returns name of the given queue type. Returned string has application
@@ -123,13 +124,14 @@ class PLATFORM_EXPORT MainThreadTaskQueue
// Separate enum class for handling prioritisation decisions in task queues.
enum class PrioritisationType {
kVeryHigh = 0,
- kHigh = 1,
- kBestEffort = 2,
- kRegular = 3,
- kLoading = 4,
- kLoadingControl = 5,
-
- kCount = 6
+ kBestEffort = 1,
+ kRegular = 2,
+ kLoading = 3,
+ kLoadingControl = 4,
+ kFindInPage = 5,
+ kExperimentalDatabase = 6,
+
+ kCount = 7
};
// kPrioritisationTypeWidthBits is the number of bits required
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
index 811cc0cb55f..07afb6e13a7 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
@@ -76,6 +76,10 @@ void MemoryPurgeManager::OnPageDestroyed(PageLifecycleState state) {
total_page_count_--;
if (state == PageLifecycleState::kFrozen)
frozen_page_count_--;
+
+ if (!CanPurge())
+ purge_timer_.Stop();
+
DCHECK_LE(frozen_page_count_, total_page_count_);
}
@@ -110,6 +114,10 @@ void MemoryPurgeManager::OnRendererBackgrounded() {
if (!base::FeatureList::IsEnabled(
features::kPurgeRendererMemoryWhenBackgrounded))
return;
+ // A spare renderer has no pages. We would like to avoid purging memory
+ // on a spare renderer.
+ if (total_page_count_ == 0)
+ return;
backgrounded_purge_pending_ = true;
RequestMemoryPurgeWithDelay(GetTimeToPurgeAfterBackgrounded());
@@ -145,6 +153,9 @@ void MemoryPurgeManager::PerformMemoryPurge() {
}
bool MemoryPurgeManager::CanPurge() const {
+ if (total_page_count_ == 0)
+ return false;
+
if (backgrounded_purge_pending_)
return true;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
index 3293c3151d3..3dea63c3bbb 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
@@ -25,8 +25,7 @@ class MemoryPurgeManagerTest : public testing::Test {
MemoryPurgeManagerTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::UI,
base::test::TaskEnvironment::TimeSource::MOCK_TIME),
- memory_purge_manager_(task_environment_.GetMainThreadTaskRunner()),
- observed_memory_pressure_(false) {}
+ memory_purge_manager_(task_environment_.GetMainThreadTaskRunner()) {}
void SetUp() override {
memory_pressure_listener_ =
@@ -49,34 +48,23 @@ class MemoryPurgeManagerTest : public testing::Test {
{features::kPurgeRendererMemoryWhenBackgrounded});
}
- void ExpectMemoryPressure(
- base::TimeDelta delay = base::TimeDelta::FromMinutes(0)) {
- FastForwardBy(delay);
- EXPECT_TRUE(observed_memory_pressure_);
- observed_memory_pressure_ = false;
- }
-
- void ExpectNoMemoryPressure(
- base::TimeDelta delay = base::TimeDelta::FromMinutes(0)) {
- FastForwardBy(delay);
- EXPECT_FALSE(observed_memory_pressure_);
- }
-
void FastForwardBy(base::TimeDelta delta) {
task_environment_.FastForwardBy(delta);
}
+ unsigned MemoryPressureCount() const { return memory_pressure_count_; }
+
base::test::ScopedFeatureList scoped_feature_list_;
base::test::TaskEnvironment task_environment_;
std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
MemoryPurgeManager memory_purge_manager_;
- bool observed_memory_pressure_;
+ unsigned memory_pressure_count_ = 0;
private:
void OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel) {
- observed_memory_pressure_ = true;
+ memory_pressure_count_++;
}
DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManagerTest);
@@ -92,7 +80,8 @@ TEST_F(MemoryPurgeManagerTest, PageFrozenInBackgroundedRenderer) {
memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive);
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(1U, MemoryPressureCount());
}
// Verify that OnPageFrozen() does not trigger a memory pressure notification in
@@ -105,7 +94,8 @@ TEST_F(MemoryPurgeManagerTest, PageFrozenInForegroundedRenderer) {
memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive);
memory_purge_manager_.SetRendererBackgrounded(false);
memory_purge_manager_.OnPageFrozen();
- ExpectNoMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(0U, MemoryPressureCount());
}
TEST_F(MemoryPurgeManagerTest, PageResumedUndoMemoryPressureSuppression) {
@@ -117,7 +107,9 @@ TEST_F(MemoryPurgeManagerTest, PageResumedUndoMemoryPressureSuppression) {
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(1U, MemoryPressureCount());
+
EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageResumed();
EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
@@ -139,15 +131,18 @@ TEST_F(MemoryPurgeManagerTest, PageFrozenPurgeMemoryAllPagesFrozenDisabled) {
memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive);
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(1U, MemoryPressureCount());
EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(2U, MemoryPressureCount());
EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(3U, MemoryPressureCount());
EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageResumed();
@@ -177,15 +172,18 @@ TEST_F(MemoryPurgeManagerTest, PageFrozenPurgeMemoryAllPagesFrozenEnabled) {
memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive);
memory_purge_manager_.OnPageFrozen();
- ExpectNoMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(0U, MemoryPressureCount());
EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageFrozen();
- ExpectNoMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(0U, MemoryPressureCount());
EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(1U, MemoryPressureCount());
EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed());
memory_purge_manager_.OnPageResumed();
@@ -211,10 +209,12 @@ TEST_F(MemoryPurgeManagerTest, MemoryPurgeWithDelay) {
memory_purge_manager_.OnPageFrozen();
// The memory pressure notification should not occur immediately
- ExpectNoMemoryPressure();
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(0U, MemoryPressureCount());
// The memory pressure notification should occur after 1 minute
- ExpectMemoryPressure(kDelayForPurgeAfterFreeze);
+ FastForwardBy(kDelayForPurgeAfterFreeze);
+ EXPECT_EQ(1U, MemoryPressureCount());
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
}
@@ -227,12 +227,13 @@ TEST_F(MemoryPurgeManagerTest, CancelMemoryPurgeWithDelay) {
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
FastForwardBy(base::TimeDelta::FromSeconds(40));
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
// If the page is resumed before the memory purge timer expires, the purge
// should be cancelled.
memory_purge_manager_.OnPageResumed();
- ExpectNoMemoryPressure(kDelayForPurgeAfterFreeze);
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(0U, MemoryPressureCount());
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive);
}
@@ -245,11 +246,12 @@ TEST_F(MemoryPurgeManagerTest, MemoryPurgeWithDelayNewActivePageCreated) {
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
FastForwardBy(base::TimeDelta::FromSeconds(40));
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
// All pages are no longer frozen, the memory purge should be cancelled.
memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive);
- ExpectNoMemoryPressure(kDelayForPurgeAfterFreeze);
+ FastForwardBy(kDelayForPurgeAfterFreeze);
+ EXPECT_EQ(0U, MemoryPressureCount());
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive);
@@ -263,11 +265,12 @@ TEST_F(MemoryPurgeManagerTest, MemoryPurgeWithDelayNewFrozenPageCreated) {
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
FastForwardBy(base::TimeDelta::FromSeconds(40));
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
// All pages are still frozen and the memory purge should occur.
memory_purge_manager_.OnPageCreated(PageLifecycleState::kFrozen);
- ExpectMemoryPressure(kDelayForPurgeAfterFreeze);
+ FastForwardBy(kDelayForPurgeAfterFreeze);
+ EXPECT_EQ(1U, MemoryPressureCount());
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
@@ -281,7 +284,8 @@ TEST_F(MemoryPurgeManagerTest, PurgeRendererMemoryWhenBackgroundedEnabled) {
memory_purge_manager_.SetRendererBackgrounded(true);
FastForwardBy(base::TimeDelta::FromMinutes(
MemoryPurgeManager::kDefaultMaxTimeToPurgeAfterBackgrounded));
- ExpectMemoryPressure();
+ // No page, no memory pressure.
+ EXPECT_EQ(0U, MemoryPressureCount());
}
TEST_F(MemoryPurgeManagerTest, PurgeRendererMemoryWhenBackgroundedDisabled) {
@@ -291,7 +295,7 @@ TEST_F(MemoryPurgeManagerTest, PurgeRendererMemoryWhenBackgroundedDisabled) {
memory_purge_manager_.SetRendererBackgrounded(true);
FastForwardBy(base::TimeDelta::Max());
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
}
TEST_F(MemoryPurgeManagerTest,
@@ -302,11 +306,11 @@ TEST_F(MemoryPurgeManagerTest,
memory_purge_manager_.SetRendererBackgrounded(true);
FastForwardBy(base::TimeDelta::FromSeconds(30));
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
memory_purge_manager_.SetRendererBackgrounded(false);
FastForwardBy(base::TimeDelta::Max());
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
}
TEST_F(MemoryPurgeManagerTest, PageFrozenAndResumedWhileBackgrounded) {
@@ -329,7 +333,8 @@ TEST_F(MemoryPurgeManagerTest, PageFrozenAndResumedWhileBackgrounded) {
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
FastForwardBy(kBeforeBackgroundPurgeDelay);
- ExpectNoMemoryPressure();
+ EXPECT_EQ(0U, MemoryPressureCount());
+
memory_purge_manager_.OnPageResumed();
FastForwardBy(
base::TimeDelta::FromMinutes(
@@ -337,7 +342,7 @@ TEST_F(MemoryPurgeManagerTest, PageFrozenAndResumedWhileBackgrounded) {
kBeforeBackgroundPurgeDelay);
// Since the renderer is still backgrounded, the memory purge should happen
// even though there are no frozen pages.
- ExpectMemoryPressure();
+ EXPECT_EQ(1U, MemoryPressureCount());
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive);
}
@@ -357,10 +362,12 @@ TEST_F(MemoryPurgeManagerTest,
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure(base::TimeDelta::FromMinutes(
+ FastForwardBy(base::TimeDelta::FromMinutes(
MemoryPurgeManager::kDefaultMaxTimeToPurgeAfterBackgrounded));
+ EXPECT_EQ(1U, MemoryPressureCount());
+
FastForwardBy(kFreezePurgeDelay);
- ExpectNoMemoryPressure();
+ EXPECT_EQ(1U, MemoryPressureCount());
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
}
@@ -380,11 +387,29 @@ TEST_F(MemoryPurgeManagerTest,
memory_purge_manager_.SetRendererBackgrounded(true);
memory_purge_manager_.OnPageFrozen();
- ExpectMemoryPressure(kFreezePurgeDelay);
+ FastForwardBy(kFreezePurgeDelay);
+ EXPECT_EQ(1U, MemoryPressureCount());
+
FastForwardBy(base::TimeDelta::Max());
- ExpectNoMemoryPressure();
+ EXPECT_EQ(1U, MemoryPressureCount());
+
+ memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
+}
+
+TEST_F(MemoryPurgeManagerTest, NoMemoryPurgeIfNoPage) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kFreezePurgeMemoryAllPagesFrozen} /* enabled */,
+ {features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */);
+ memory_purge_manager_.SetRendererBackgrounded(true);
+ memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive);
+
+ memory_purge_manager_.SetRendererBackgrounded(true);
+ memory_purge_manager_.OnPageFrozen();
memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen);
+
+ FastForwardBy(base::TimeDelta::FromMinutes(0));
+ EXPECT_EQ(0U, MemoryPressureCount());
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc
new file mode 100644
index 00000000000..13d6f4a9871
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc
@@ -0,0 +1,45 @@
+// 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 "third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h"
+
+namespace blink {
+namespace scheduler {
+
+NonWakingTimeDomain::NonWakingTimeDomain(const base::TickClock* tick_clock)
+ : tick_clock_(tick_clock) {}
+
+NonWakingTimeDomain::~NonWakingTimeDomain() = default;
+
+base::sequence_manager::LazyNow NonWakingTimeDomain::CreateLazyNow() const {
+ return base::sequence_manager::LazyNow(tick_clock_);
+}
+
+base::TimeTicks NonWakingTimeDomain::Now() const {
+ return tick_clock_->NowTicks();
+}
+
+base::Optional<base::TimeDelta> NonWakingTimeDomain::DelayTillNextTask(
+ base::sequence_manager::LazyNow* lazy_now) {
+ // NonWakingTimeDomain should never generate wakeups on its own.
+ return base::nullopt;
+}
+
+bool NonWakingTimeDomain::MaybeFastForwardToNextTask(
+ bool quit_when_idle_requested) {
+ return false;
+}
+
+const char* NonWakingTimeDomain::GetName() const {
+ return "non_waking_time_domain";
+}
+
+void NonWakingTimeDomain::SetNextDelayedDoWork(
+ base::sequence_manager::LazyNow* lazy_now,
+ base::TimeTicks run_time) {
+ // Do not request a wake-up, unlike a regular TimeDomain.
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h
new file mode 100644
index 00000000000..9641ed9aa1b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_NON_WAKING_TIME_DOMAIN_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_NON_WAKING_TIME_DOMAIN_H_
+
+#include "base/task/sequence_manager/time_domain.h"
+#include "base/time/tick_clock.h"
+
+namespace blink {
+namespace scheduler {
+
+// A time domain which never generates wake-ups on its own. Useful for tasks
+// which should run only when the system is non-idle.
+class NonWakingTimeDomain : public base::sequence_manager::TimeDomain {
+ public:
+ explicit NonWakingTimeDomain(const base::TickClock* tick_clock);
+ ~NonWakingTimeDomain() override;
+
+ // TimeDomain:
+ base::sequence_manager::LazyNow CreateLazyNow() const override;
+ base::TimeTicks Now() const override;
+ base::Optional<base::TimeDelta> DelayTillNextTask(
+ base::sequence_manager::LazyNow* lazy_now) override;
+ bool MaybeFastForwardToNextTask(bool quit_when_idle_requested) override;
+ const char* GetName() const override;
+ void SetNextDelayedDoWork(base::sequence_manager::LazyNow* lazy_now,
+ base::TimeTicks run_time) override;
+
+ private:
+ const base::TickClock* tick_clock_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_NON_WAKING_TIME_DOMAIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
index 64608d7eebb..62498217237 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
@@ -7,7 +7,7 @@
#include <array>
-#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
index 46cbd2b9c41..98927259f7b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -107,6 +107,8 @@ const char* TaskTypeNames::TaskTypeToString(TaskType task_type) {
return "MainThreadTaskQueueCleanup";
case TaskType::kMainThreadTaskQueueMemoryPurge:
return "MainThreadTaskQueueMemoryPurge";
+ case TaskType::kMainThreadTaskQueueNonWaking:
+ return "MainThreadTaskQueueNonWaking";
case TaskType::kInternalIntersectionObserver:
return "InternalIntersectionObserver";
case TaskType::kCompositorThreadTaskQueueDefault:
@@ -135,6 +137,8 @@ const char* TaskTypeNames::TaskTypeToString(TaskType task_type) {
return "ExperimentalWebScheduling";
case TaskType::kInternalFrameLifecycleControl:
return "InternalFrameLifecycleControl";
+ case TaskType::kInternalFindInPage:
+ return "InternalFindInPage";
case TaskType::kCount:
return "Count";
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc
index 361b57ef706..0b04962ea63 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc
@@ -11,7 +11,6 @@ UserModel::UserModel()
: pending_input_event_count_(0),
is_gesture_active_(false),
is_gesture_expected_(false) {}
-UserModel::~UserModel() = default;
void UserModel::DidStartProcessingInputEvent(blink::WebInputEvent::Type type,
const base::TimeTicks now) {
@@ -99,8 +98,7 @@ bool UserModel::IsGestureExpectedSoonImpl(
base::TimeDelta::FromMilliseconds(kExpectSubsequentGestureMillis);
return true;
} else {
- // If we've have a finished a gesture then a subsequent gesture is deemed
- // likely.
+ // If we have finished a gesture then a subsequent gesture is deemed likely.
base::TimeDelta expect_subsequent_gesture_for =
base::TimeDelta::FromMilliseconds(kExpectSubsequentGestureMillis);
if (last_continuous_gesture_time_.is_null() ||
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
index e29de4b9202..fb7d2b79468 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
@@ -8,8 +8,8 @@
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
-#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -21,7 +21,6 @@ class PLATFORM_EXPORT UserModel {
public:
UserModel();
- ~UserModel();
// Tells us that the system started processing an input event. Must be paired
// with a call to DidFinishProcessingInputEvent.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc
index c3c98447ec4..d680bb7669a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc
@@ -8,45 +8,33 @@ namespace blink {
namespace {
-const AtomicString& ImmediatePriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, immediate_priority, ("immediate"));
- return immediate_priority;
+const AtomicString& UserBlockingPriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, user_blocking_priority,
+ ("user-blocking"));
+ return user_blocking_priority;
}
-const AtomicString& HighPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, high_priority, ("high"));
- return high_priority;
+const AtomicString& UserVisiblePriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, user_visible_priority,
+ ("user-visible"));
+ return user_visible_priority;
}
-const AtomicString& DefaultPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, default_priority, ("default"));
- return default_priority;
-}
-
-const AtomicString& LowPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, low_priority, ("low"));
- return low_priority;
-}
-
-const AtomicString& IdlePriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, idle_priority, ("idle"));
- return idle_priority;
+const AtomicString& BackgroundPriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, background_priority, ("background"));
+ return background_priority;
}
} // namespace
AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
switch (priority) {
- case WebSchedulingPriority::kImmediatePriority:
- return ImmediatePriorityKeyword();
- case WebSchedulingPriority::kHighPriority:
- return HighPriorityKeyword();
- case WebSchedulingPriority::kDefaultPriority:
- return DefaultPriorityKeyword();
- case WebSchedulingPriority::kLowPriority:
- return LowPriorityKeyword();
- case WebSchedulingPriority::kIdlePriority:
- return IdlePriorityKeyword();
+ case WebSchedulingPriority::kUserBlockingPriority:
+ return UserBlockingPriorityKeyword();
+ case WebSchedulingPriority::kUserVisiblePriority:
+ return UserVisiblePriorityKeyword();
+ case WebSchedulingPriority::kBackgroundPriority:
+ return BackgroundPriorityKeyword();
}
NOTREACHED();
@@ -55,19 +43,14 @@ AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
WebSchedulingPriority WebSchedulingPriorityFromString(
const AtomicString& priority) {
- if (priority == ImmediatePriorityKeyword())
- return WebSchedulingPriority::kImmediatePriority;
- if (priority == HighPriorityKeyword())
- return WebSchedulingPriority::kHighPriority;
- if (priority == DefaultPriorityKeyword())
- return WebSchedulingPriority::kDefaultPriority;
- if (priority == LowPriorityKeyword())
- return WebSchedulingPriority::kLowPriority;
- if (priority == IdlePriorityKeyword())
- return WebSchedulingPriority::kIdlePriority;
-
+ if (priority == UserBlockingPriorityKeyword())
+ return WebSchedulingPriority::kUserBlockingPriority;
+ if (priority == UserVisiblePriorityKeyword())
+ return WebSchedulingPriority::kUserVisiblePriority;
+ if (priority == BackgroundPriorityKeyword())
+ return WebSchedulingPriority::kBackgroundPriority;
NOTREACHED();
- return WebSchedulingPriority::kDefaultPriority;
+ return WebSchedulingPriority::kUserVisiblePriority;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.cc
new file mode 100644
index 00000000000..0e7bc1f23a5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.cc
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h"
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+
+namespace blink {
+namespace scheduler {
+
+WidgetScheduler::WidgetScheduler(
+ MainThreadSchedulerImpl* main_thread_scheduler) {
+ input_task_queue_ = main_thread_scheduler->NewTaskQueue(
+ MainThreadTaskQueue::QueueCreationParams(
+ MainThreadTaskQueue::QueueType::kInput)
+ .SetShouldMonitorQuiescence(true)
+ .SetFixedPriority(
+ base::make_optional(TaskQueue::QueuePriority::kHighestPriority)));
+ input_task_runner_ =
+ input_task_queue_->CreateTaskRunner(TaskType::kMainThreadTaskQueueInput);
+ input_task_queue_enabled_voter_ =
+ input_task_queue_->CreateQueueEnabledVoter();
+}
+
+WidgetScheduler::~WidgetScheduler() {
+ input_task_queue_->ShutdownTaskQueue();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> WidgetScheduler::InputTaskRunner() {
+ return input_task_runner_;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h
new file mode 100644
index 00000000000..83a5fdecb26
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WIDGET_SCHEDULER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WIDGET_SCHEDULER_H_
+
+#include <memory>
+
+#include "base/task/sequence_manager/task_queue.h"
+#include "third_party/blink/public/platform/scheduler/web_widget_scheduler.h"
+
+namespace blink {
+namespace scheduler {
+
+class MainThreadSchedulerImpl;
+class MainThreadTaskQueue;
+
+class WidgetScheduler : public WebWidgetScheduler {
+ public:
+ WidgetScheduler(MainThreadSchedulerImpl*);
+ ~WidgetScheduler() override;
+ scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
+
+ private:
+ scoped_refptr<MainThreadTaskQueue> input_task_queue_;
+ scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
+ std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
+ input_task_queue_enabled_voter_;
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetScheduler);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WIDGET_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
index 7aec66e6e0f..c9f33ee112b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
@@ -89,8 +89,8 @@ class FrameScheduler : public FrameOrWorkerScheduler {
// Set whether this frame is cross origin w.r.t. the top level frame. Cross
// origin frames may use a different scheduling policy from same origin
// frames.
- virtual void SetCrossOrigin(bool) = 0;
- virtual bool IsCrossOrigin() const = 0;
+ virtual void SetCrossOriginToMainFrame(bool) = 0;
+ virtual bool IsCrossOriginToMainFrame() const = 0;
virtual void SetIsAdFrame() = 0;
virtual bool IsAdFrame() const = 0;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h b/chromium/third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h
index 17c9a3baa13..ab1b52d776a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_PENDING_USER_INPUT_TYPE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_PENDING_USER_INPUT_TYPE_H_
+#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
index 9eb6426a100..20e3e743837 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
@@ -9,8 +9,8 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
-#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
@@ -89,6 +89,11 @@ class PLATFORM_EXPORT ThreadScheduler {
// Returns a task runner for kV8 tasks. Can be called from any thread.
virtual scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() = 0;
+ // Returns a task runner which does not generate system wakeups on its own.
+ // This means that if a delayed task is posted to it, it will run when
+ // the delay expires AND another task runs.
+ virtual scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() = 0;
+
// Returns a task runner for compositor tasks. This is intended only to be
// used by specific animation and rendering related tasks (e.g. animated GIFS)
// and should not generally be used.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
index fde66f54035..049ecb25117 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
@@ -13,13 +13,11 @@ namespace blink {
// Priorities for the experimental scheduling API (see
// https://github.com/WICG/main-thread-scheduling).
enum class WebSchedulingPriority {
- kImmediatePriority = 0,
- kHighPriority = 1,
- kDefaultPriority = 2,
- kLowPriority = 3,
- kIdlePriority = 4,
+ kUserBlockingPriority = 0,
+ kUserVisiblePriority = 1,
+ kBackgroundPriority = 2,
- kLastPriority = kIdlePriority
+ kLastPriority = kBackgroundPriority
};
PLATFORM_EXPORT AtomicString
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/worker_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_pool.h
index e801685efad..ca7c72f301f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/worker_pool.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_pool.h
@@ -15,9 +15,9 @@ namespace blink {
namespace worker_pool {
-// These are a thin wrapper around base::ThreadPoolInstance to ensure that all
-// callers use CrossThreadBindOnce instead of base::Bind to ensure that
-// all non-thread-safe objects are copied properly.
+// These are a thin wrapper around base::ThreadPool to ensure that all callers
+// use CrossThreadBindOnce instead of base::Bind to ensure that all
+// non-thread-safe objects are copied properly.
//
// All tasks that do not care about which thread they are running on
// (e.g. compressing/uncompressing tasks) use this API.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
index ef04e64744c..0bc371afa11 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
@@ -33,21 +33,7 @@ CompositorThreadScheduler::CompositorThreadScheduler(
base::sequence_manager::SequenceManager* sequence_manager)
: NonMainThreadSchedulerImpl(sequence_manager,
TaskType::kCompositorThreadTaskQueueDefault),
- input_task_queue_(
- base::FeatureList::IsEnabled(kHighPriorityInputOnCompositorThread)
- ? helper()->NewTaskQueue(
- base::sequence_manager::TaskQueue::Spec("input_tq")
- .SetShouldMonitorQuiescence(true))
- : nullptr),
- input_task_runner_(input_task_queue_
- ? input_task_queue_->CreateTaskRunner(
- TaskType::kCompositorThreadTaskQueueInput)
- : nullptr),
compositor_metrics_helper_(helper()->HasCPUTimingForEachTask()) {
- if (input_task_queue_) {
- input_task_queue_->SetQueuePriority(
- base::sequence_manager::TaskQueue::QueuePriority::kHighestPriority);
- }
DCHECK(!g_compositor_thread_scheduler);
g_compositor_thread_scheduler = this;
}
@@ -85,26 +71,30 @@ CompositorThreadScheduler::IdleTaskRunner() {
}
scoped_refptr<base::SingleThreadTaskRunner>
-CompositorThreadScheduler::InputTaskRunner() {
- if (input_task_runner_)
- return input_task_runner_;
+CompositorThreadScheduler::V8TaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+CompositorThreadScheduler::DefaultTaskRunner() {
return helper()->DefaultTaskRunner();
}
scoped_refptr<base::SingleThreadTaskRunner>
-CompositorThreadScheduler::V8TaskRunner() {
+CompositorThreadScheduler::CompositorTaskRunner() {
NOTREACHED();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
-CompositorThreadScheduler::CompositorTaskRunner() {
+CompositorThreadScheduler::IPCTaskRunner() {
NOTREACHED();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
-CompositorThreadScheduler::IPCTaskRunner() {
+CompositorThreadScheduler::NonWakingTaskRunner() {
NOTREACHED();
return nullptr;
}
@@ -128,7 +118,6 @@ void CompositorThreadScheduler::RemoveTaskObserver(
}
void CompositorThreadScheduler::Shutdown() {
- input_task_queue_->ShutdownTaskQueue();
}
void CompositorThreadScheduler::OnIdleTaskPosted() {}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
index 984cb2d01cc..3c808170630 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
@@ -40,9 +40,10 @@ class PLATFORM_EXPORT CompositorThreadScheduler
// WebThreadScheduler:
scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
bool ShouldYieldForHighPriorityWork() override;
bool CanExceedIdleDeadlineIfRequired() const override;
void AddTaskObserver(base::TaskObserver* task_observer) override;
@@ -66,9 +67,6 @@ class PLATFORM_EXPORT CompositorThreadScheduler
void InitImpl() override;
private:
- scoped_refptr<NonMainThreadTaskQueue> input_task_queue_;
- scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
-
CompositorMetricsHelper compositor_metrics_helper_;
DISALLOW_COPY_AND_ASSIGN(CompositorThreadScheduler);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc
deleted file mode 100644
index 55385f02784..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h"
-#include <algorithm>
-#include <memory>
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/common/features.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-using testing::ElementsAre;
-using testing::ElementsAreArray;
-
-namespace blink {
-namespace scheduler {
-// To avoid symbol collisions in jumbo builds.
-namespace compositor_thread_scheduler_unittest {
-
-class CompositorThreadSchedulerTest : public testing::Test {
- public:
- CompositorThreadSchedulerTest(
- std::vector<base::Feature> features_to_enable,
- std::vector<base::Feature> features_to_disable) {
- feature_list_.InitWithFeatures(features_to_enable, features_to_disable);
- }
-
- CompositorThreadSchedulerTest() : CompositorThreadSchedulerTest({}, {}) {}
-
- ~CompositorThreadSchedulerTest() override = default;
-
- void SetUp() override {
- mock_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- mock_task_runner_->AdvanceMockTickClock(
- base::TimeDelta::FromMicroseconds(5000));
- sequence_manager_ = base::sequence_manager::SequenceManagerForTest::Create(
- nullptr, mock_task_runner_, mock_task_runner_->GetMockTickClock());
- scheduler_ =
- std::make_unique<CompositorThreadScheduler>(sequence_manager_.get());
- scheduler_->Init();
- }
-
- void TearDown() override {}
-
- protected:
- base::test::ScopedFeatureList feature_list_;
-
- scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
- std::unique_ptr<base::sequence_manager::SequenceManagerForTest>
- sequence_manager_;
- std::unique_ptr<CompositorThreadScheduler> scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorThreadSchedulerTest);
-};
-
-class CompositorThreadInputPriorityTest : public CompositorThreadSchedulerTest {
- public:
- CompositorThreadInputPriorityTest()
- : CompositorThreadSchedulerTest(
- {kHighPriorityInputOnCompositorThread} /* features_to_enable */,
- {} /* features_to_disable */) {}
- ~CompositorThreadInputPriorityTest() override = default;
-};
-
-namespace {
-
-void RunTestTask(String name, Vector<String>* log) {
- log->push_back(name);
-}
-
-} // namespace
-
-TEST_F(CompositorThreadInputPriorityTest, HighestPriorityInput) {
- Vector<String> run_order;
-
- scheduler_->DefaultTaskQueue()->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RunTestTask, "default", base::Unretained(&run_order)));
- scheduler_->InputTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RunTestTask, "input", base::Unretained(&run_order)));
-
- mock_task_runner_->RunUntilIdle();
-
- EXPECT_THAT(run_order, testing::ElementsAre("input", "default"));
-}
-
-class CompositorThreadNoInputPriorityTest
- : public CompositorThreadSchedulerTest {
- public:
- CompositorThreadNoInputPriorityTest()
- : CompositorThreadSchedulerTest(
- {} /* features_to_enable */,
- {kHighPriorityInputOnCompositorThread} /* features_to_disable */) {}
- ~CompositorThreadNoInputPriorityTest() override = default;
-};
-
-TEST_F(CompositorThreadNoInputPriorityTest, InputNotPrioritized) {
- Vector<String> run_order;
-
- scheduler_->DefaultTaskQueue()->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RunTestTask, "default", base::Unretained(&run_order)));
- scheduler_->InputTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RunTestTask, "input", base::Unretained(&run_order)));
-
- mock_task_runner_->RunUntilIdle();
-
- EXPECT_THAT(run_order, testing::ElementsAre("default", "input"));
-}
-} // namespace compositor_thread_scheduler_unittest
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
index b9a44ecca6e..d63485495f5 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -197,6 +197,7 @@ scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner(
case TaskType::kMainThreadTaskQueueControl:
case TaskType::kMainThreadTaskQueueCleanup:
case TaskType::kMainThreadTaskQueueMemoryPurge:
+ case TaskType::kMainThreadTaskQueueNonWaking:
case TaskType::kCompositorThreadTaskQueueDefault:
case TaskType::kCompositorThreadTaskQueueInput:
case TaskType::kWorkerThreadTaskQueueDefault:
@@ -207,6 +208,7 @@ scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner(
case TaskType::kInternalContentCapture:
case TaskType::kExperimentalWebScheduling:
case TaskType::kInternalFrameLifecycleControl:
+ case TaskType::kInternalFindInPage:
case TaskType::kCount:
NOTREACHED();
break;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
index 478c3cb030f..4434805d26a 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
@@ -21,7 +21,6 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/process_state.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
@@ -156,6 +155,12 @@ WorkerThreadScheduler::IPCTaskRunner() {
return nullptr;
}
+scoped_refptr<base::SingleThreadTaskRunner>
+WorkerThreadScheduler::NonWakingTaskRunner() {
+ NOTREACHED() << "Not implemented";
+ return nullptr;
+}
+
bool WorkerThreadScheduler::CanExceedIdleDeadlineIfRequired() const {
DCHECK(initialized_);
return idle_helper_.CanExceedIdleDeadlineIfRequired();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
index fb26754d227..130a125f9fb 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
@@ -50,6 +50,7 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl,
scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
bool ShouldYieldForHighPriorityWork() override;
bool CanExceedIdleDeadlineIfRequired() const override;
void AddTaskObserver(base::TaskObserver* task_observer) override;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
index d4142d207c2..76cce482184 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
@@ -490,10 +490,10 @@ class WorkerThreadSchedulerWithProxyTest : public testing::Test {
frame_scheduler_ = FakeFrameScheduler::Builder()
.SetIsPageVisible(false)
.SetFrameType(FrameScheduler::FrameType::kSubframe)
- .SetIsCrossOrigin(true)
+ .SetIsCrossOriginToMainFrame(true)
.SetDelegate(frame_scheduler_delegate_.get())
.Build();
- frame_scheduler_->SetCrossOrigin(true);
+ frame_scheduler_->SetCrossOriginToMainFrame(true);
worker_scheduler_proxy_ =
std::make_unique<WorkerSchedulerProxy>(frame_scheduler_.get());
diff --git a/chromium/third_party/blink/renderer/platform/supplementable.h b/chromium/third_party/blink/renderer/platform/supplementable.h
index ff971f12334..dbbd63044f5 100644
--- a/chromium/third_party/blink/renderer/platform/supplementable.h
+++ b/chromium/third_party/blink/renderer/platform/supplementable.h
@@ -147,9 +147,7 @@ class Supplement : public GarbageCollectedMixin {
: nullptr;
}
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(supplementable_);
- }
+ void Trace(Visitor* visitor) override { visitor->Trace(supplementable_); }
private:
Member<T> supplementable_;
@@ -201,7 +199,7 @@ class Supplementable : public GarbageCollectedMixin {
#endif
}
- void Trace(blink::Visitor* visitor) override { visitor->Trace(supplements_); }
+ void Trace(Visitor* visitor) override { visitor->Trace(supplements_); }
protected:
using SupplementMap =
diff --git a/chromium/third_party/blink/renderer/platform/testing/DEPS b/chromium/third_party/blink/renderer/platform/testing/DEPS
index 19b3458859d..63b1f17bcd4 100644
--- a/chromium/third_party/blink/renderer/platform/testing/DEPS
+++ b/chromium/third_party/blink/renderer/platform/testing/DEPS
@@ -13,10 +13,12 @@ include_rules = [
"+base/process",
"+base/run_loop.h",
"+base/metrics/statistics_recorder.h",
+ "+base/strings/string_number_conversions.h",
"+base/task/single_thread_task_executor.h",
"+base/test/test_io_thread.h",
"+cc",
"+mojo/core/embedder",
+ "+services/network/public",
'+testing',
"+third_party/blink/renderer/platform/exported",
diff --git a/chromium/third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.cc b/chromium/third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.cc
index a01f3006487..1a8a8a1a5f0 100644
--- a/chromium/third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.cc
@@ -10,7 +10,6 @@
#include "base/test/test_timeouts.h"
#include "content/public/test/blink_test_environment.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
-#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
namespace blink {
@@ -30,8 +29,6 @@ BlinkFuzzerTestSupport::BlinkFuzzerTestSupport(int argc, char** argv) {
TestTimeouts::Initialize();
content::SetUpBlinkTestEnvironment();
-
- blink::SchemeRegistry::Initialize();
}
BlinkFuzzerTestSupport::~BlinkFuzzerTestSupport() {
diff --git a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc
index 76f39b5545e..119e0ff710d 100644
--- a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc
@@ -22,12 +22,12 @@ WebTimeRanges EmptyWebMediaPlayer::Seekable() const {
return WebTimeRanges();
}
-WebSize EmptyWebMediaPlayer::NaturalSize() const {
- return WebSize(0, 0);
+gfx::Size EmptyWebMediaPlayer::NaturalSize() const {
+ return gfx::Size();
}
-WebSize EmptyWebMediaPlayer::VisibleRect() const {
- return WebSize();
+gfx::Size EmptyWebMediaPlayer::VisibleSize() const {
+ return gfx::Size();
}
WebString EmptyWebMediaPlayer::GetErrorMessage() const {
diff --git a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h
index 1322171e57a..e6692af38be 100644
--- a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h
+++ b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h
@@ -30,6 +30,7 @@ class EmptyWebMediaPlayer : public WebMediaPlayer {
void SetVolume(double) override {}
void SetLatencyHint(double) override {}
void OnRequestPictureInPicture() override {}
+ void OnPictureInPictureAvailabilityChanged(bool available) override {}
SurfaceLayerMode GetVideoSurfaceLayerMode() const override {
return SurfaceLayerMode::kNever;
}
@@ -39,13 +40,14 @@ class EmptyWebMediaPlayer : public WebMediaPlayer {
WebSetSinkIdCompleteCallback) override {}
bool HasVideo() const override { return false; }
bool HasAudio() const override { return false; }
- WebSize NaturalSize() const override;
- WebSize VisibleRect() const override;
+ gfx::Size NaturalSize() const override;
+ gfx::Size VisibleSize() const override;
bool Paused() const override { return false; }
bool Seeking() const override { return false; }
double Duration() const override { return 0.0; }
double CurrentTime() const override { return 0.0; }
- NetworkState GetNetworkState() const override { return kNetworkStateEmpty; }
+ bool IsEnded() const override { return false; }
+ NetworkState GetNetworkState() const override { return kNetworkStateIdle; }
ReadyState GetReadyState() const override { return kReadyStateHaveNothing; }
WebString GetErrorMessage() const override;
bool DidLoadingProgress() override { return false; }
diff --git a/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc b/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc
index 08dc5f8c1b5..1272d0fb9fc 100644
--- a/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc
@@ -61,6 +61,8 @@ class TestFontSelector : public FontSelector {
const AtomicString& font_family_name) override {}
void ReportFailedFontFamilyMatch(
const AtomicString& font_family_name) override {}
+ void ReportSuccessfulLocalFontMatch(const AtomicString& font_name) override {}
+ void ReportFailedLocalFontMatch(const AtomicString& font_name) override {}
ExecutionContext* GetExecutionContext() const override { return nullptr; }
FontFaceCache* GetFontFaceCache() override { return nullptr; }
@@ -93,9 +95,7 @@ Font CreateTestFont(const AtomicString& family_name,
if (ligatures)
font_description.SetVariantLigatures(*ligatures);
- Font font(font_description);
- font.Update(TestFontSelector::Create(font_path));
- return font;
+ return Font(font_description, TestFontSelector::Create(font_path));
}
} // namespace test
diff --git a/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h b/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
index 9738516ca21..6da9d8037a9 100644
--- a/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
@@ -23,6 +23,10 @@ inline const EffectPaintPropertyNode& e0() {
return EffectPaintPropertyNode::Root();
}
+constexpr int c0_id = 1;
+constexpr int e0_id = 1;
+constexpr int t0_id = 1;
+
inline scoped_refptr<EffectPaintPropertyNode> CreateOpacityEffect(
const EffectPaintPropertyNode& parent,
const TransformPaintPropertyNode& local_transform_space,
@@ -111,14 +115,13 @@ inline scoped_refptr<EffectPaintPropertyNode> CreateBackdropFilterEffect(
const TransformPaintPropertyNode& local_transform_space,
const ClipPaintPropertyNode* output_clip,
CompositorFilterOperations backdrop_filter,
- const FloatPoint& filters_origin = FloatPoint(),
- CompositingReasons compositing_reasons = CompositingReason::kNone) {
+ const FloatPoint& filters_origin = FloatPoint()) {
EffectPaintPropertyNode::State state;
state.local_transform_space = &local_transform_space;
state.output_clip = output_clip;
state.backdrop_filter = std::move(backdrop_filter);
state.filters_origin = filters_origin;
- state.direct_compositing_reasons = compositing_reasons;
+ state.direct_compositing_reasons = CompositingReason::kBackdropFilter;
state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
NewUniqueObjectId(), CompositorElementIdNamespace::kPrimary);
return EffectPaintPropertyNode::Create(parent, std::move(state));
@@ -127,12 +130,10 @@ inline scoped_refptr<EffectPaintPropertyNode> CreateBackdropFilterEffect(
inline scoped_refptr<EffectPaintPropertyNode> CreateBackdropFilterEffect(
const EffectPaintPropertyNode& parent,
CompositorFilterOperations backdrop_filter,
- const FloatPoint& paint_offset = FloatPoint(),
- CompositingReasons compositing_reasons = CompositingReason::kNone) {
+ const FloatPoint& paint_offset = FloatPoint()) {
return CreateBackdropFilterEffect(
parent, parent.Unalias().LocalTransformSpace(),
- parent.Unalias().OutputClip(), backdrop_filter, paint_offset,
- compositing_reasons);
+ parent.Unalias().OutputClip(), backdrop_filter, paint_offset);
}
inline scoped_refptr<EffectPaintPropertyNode>
@@ -156,9 +157,17 @@ inline scoped_refptr<ClipPaintPropertyNode> CreateClip(
const ClipPaintPropertyNode& parent,
const TransformPaintPropertyNode& local_transform_space,
const FloatRoundedRect& clip_rect) {
- ClipPaintPropertyNode::State state;
- state.local_transform_space = &local_transform_space;
- state.clip_rect = clip_rect;
+ ClipPaintPropertyNode::State state(&local_transform_space, clip_rect);
+ return ClipPaintPropertyNode::Create(parent, std::move(state));
+}
+
+inline scoped_refptr<ClipPaintPropertyNode> CreateClip(
+ const ClipPaintPropertyNode& parent,
+ const TransformPaintPropertyNode& local_transform_space,
+ const FloatRoundedRect& clip_rect,
+ const FloatRoundedRect& pixel_snapped_clip_rect) {
+ ClipPaintPropertyNode::State state(&local_transform_space, clip_rect,
+ pixel_snapped_clip_rect);
return ClipPaintPropertyNode::Create(parent, std::move(state));
}
@@ -166,9 +175,7 @@ inline scoped_refptr<ClipPaintPropertyNode> CreateClipPathClip(
const ClipPaintPropertyNode& parent,
const TransformPaintPropertyNode& local_transform_space,
const FloatRoundedRect& clip_rect) {
- ClipPaintPropertyNode::State state;
- state.local_transform_space = &local_transform_space;
- state.clip_rect = clip_rect;
+ ClipPaintPropertyNode::State state(&local_transform_space, clip_rect);
state.clip_path = base::AdoptRef(new RefCountedPath);
return ClipPaintPropertyNode::Create(parent, std::move(state));
}
@@ -186,8 +193,7 @@ inline scoped_refptr<TransformPaintPropertyNode> CreateTransform(
const TransformationMatrix& matrix,
const FloatPoint3D& origin = FloatPoint3D(),
CompositingReasons compositing_reasons = CompositingReason::kNone) {
- TransformPaintPropertyNode::State state{
- TransformPaintPropertyNode::TransformAndOrigin(matrix, origin)};
+ TransformPaintPropertyNode::State state{{matrix, origin}};
state.direct_compositing_reasons = compositing_reasons;
return TransformPaintPropertyNode::Create(parent, std::move(state));
}
@@ -196,8 +202,7 @@ inline scoped_refptr<TransformPaintPropertyNode> CreateAnimatingTransform(
const TransformPaintPropertyNode& parent,
const TransformationMatrix& matrix = TransformationMatrix(),
const FloatPoint3D& origin = FloatPoint3D()) {
- TransformPaintPropertyNode::State state{
- TransformPaintPropertyNode::TransformAndOrigin(matrix, origin)};
+ TransformPaintPropertyNode::State state{{matrix, origin}};
state.direct_compositing_reasons =
CompositingReason::kActiveTransformAnimation;
state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
diff --git a/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h b/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
index 00b0da0c002..f5b9d63ee7b 100644
--- a/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
+++ b/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
@@ -11,24 +11,17 @@
namespace blink {
-enum {
- kCompositeAfterPaint = 1 << 0,
- kUnderInvalidationChecking = 1 << 1,
- kFastBorderRadius = 1 << 2,
- kDoNotCompositeTrivial3D = 1 << 3,
-};
+enum { kCompositeAfterPaint = 1 << 0, kUnderInvalidationChecking = 1 << 1 };
class PaintTestConfigurations
: public testing::WithParamInterface<unsigned>,
private ScopedCompositeAfterPaintForTest,
- private ScopedPaintUnderInvalidationCheckingForTest,
- private ScopedFastBorderRadiusForTest {
+ private ScopedPaintUnderInvalidationCheckingForTest {
public:
PaintTestConfigurations()
: ScopedCompositeAfterPaintForTest(GetParam() & kCompositeAfterPaint),
- ScopedPaintUnderInvalidationCheckingForTest(GetParam() &
- kUnderInvalidationChecking),
- ScopedFastBorderRadiusForTest(GetParam() & kFastBorderRadius) {}
+ ScopedPaintUnderInvalidationCheckingForTest(
+ GetParam() & kUnderInvalidationChecking) {}
~PaintTestConfigurations() {
// Must destruct all objects before toggling back feature flags.
WebHeap::CollectAllGarbageForTesting();
@@ -43,21 +36,6 @@ class PaintTestConfigurations
INSTANTIATE_TEST_SUITE_P(All, test_class, \
::testing::Values(kCompositeAfterPaint))
-#define INSTANTIATE_LAYER_LIST_TEST_SUITE_P(test_class) \
- INSTANTIATE_TEST_SUITE_P( \
- All, test_class, \
- ::testing::Values(0, kCompositeAfterPaint, kFastBorderRadius))
-
-#define INSTANTIATE_SCROLL_HIT_TEST_SUITE_P(test_class) \
- INSTANTIATE_TEST_SUITE_P(All, test_class, \
- ::testing::Values(0, kCompositeAfterPaint))
-
-#define INSTANTIATE_DO_NOT_COMPOSITE_TRIVIAL_3D_P(test_class) \
- INSTANTIATE_TEST_SUITE_P( \
- All, test_class, \
- ::testing::Values(0, kCompositeAfterPaint, kDoNotCompositeTrivial3D, \
- kCompositeAfterPaint | kDoNotCompositeTrivial3D))
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_PAINT_TEST_CONFIGURATIONS_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc b/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
index 2e35ebbb57b..32e03c72ae4 100644
--- a/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/timer/lap_timer.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
+#include "testing/perf/perf_result_reporter.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
@@ -21,6 +22,14 @@ static const int kTimeLimitMillis = 3000;
static const int kWarmupRuns = 10000;
static const int kTimeCheckInterval = 1000000;
+namespace {
+
+constexpr char kMetricPrefixOffsetForPosition[] = "OffsetForPosition.";
+constexpr char kMetricPrefixCharacterRange[] = "CharacterRange.";
+constexpr char kMetricThroughput[] = "throughput";
+
+} // namespace
+
class ShapeResultPerfTest {
USING_FAST_MALLOC(ShapeResultPerfTest);
@@ -52,6 +61,14 @@ class ShapeResultPerfTest {
ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
}
+ void ReportResult(const std::string& metric_prefix,
+ const std::string& story_prefix) {
+ std::string story = story_prefix + "_" + param_string;
+ perf_test::PerfResultReporter reporter(metric_prefix, story);
+ reporter.RegisterImportantMetric(kMetricThroughput, "runs/s");
+ reporter.AddResult(kMetricThroughput, timer.LapsPerSecond());
+ }
+
Font font;
HashMap<FontName, String, WTF::IntHash<FontName>> font_path = {
@@ -62,6 +79,7 @@ class ShapeResultPerfTest {
};
base::LapTimer timer;
+ std::string param_string;
};
class OffsetForPositionPerfTest : public ShapeResultPerfTest,
@@ -72,11 +90,18 @@ class OffsetForPositionPerfTest : public ShapeResultPerfTest,
BreakGlyphsOption breakopt) {
timer.Reset();
float position = GetParam();
+ param_string = base::NumberToString(position);
do {
font.OffsetForPosition(run, position, partial, breakopt);
timer.NextLap();
} while (!timer.HasTimeLimitExpired());
}
+
+ protected:
+ void ReportResult(const std::string& story_prefix) {
+ ShapeResultPerfTest::ReportResult(kMetricPrefixOffsetForPosition,
+ story_prefix);
+ }
};
class CharacterRangePerfTest : public ShapeResultPerfTest,
@@ -85,67 +110,66 @@ class CharacterRangePerfTest : public ShapeResultPerfTest,
void GetCharacter(TextRun& run) {
timer.Reset();
int endpos = GetParam();
+ param_string = base::NumberToString(endpos);
do {
font.SelectionRectForText(run, FloatPoint(), 100, 0, endpos);
timer.NextLap();
} while (!timer.HasTimeLimitExpired());
}
+
+ protected:
+ void ReportResult(const std::string& story_prefix) {
+ ShapeResultPerfTest::ReportResult(kMetricPrefixCharacterRange,
+ story_prefix);
+ }
};
TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullBreak) {
TextRun run = SetupFont(ahem, "FURACOLO", true);
OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " LTR full break", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("LTR_full_break");
}
TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullDontBreak) {
TextRun run = SetupFont(ahem, "FURACOLO", true);
OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " LTR full", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("LTR_full");
}
TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialBreak) {
TextRun run = SetupFont(ahem, "FURACOLO", true);
OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " LTR partial break", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("LTR_partial_break");
}
TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialDontBreak) {
TextRun run = SetupFont(ahem, "FURACOLO", true);
OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " LTR partial", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("LTR_partial");
}
TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullBreak) {
TextRun run = SetupFont(ahem, "OLOCARUF", false);
OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " RTL full break", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("RTL_full_break");
}
TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullDontBreak) {
TextRun run = SetupFont(ahem, "OLOCARUF", false);
OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " RTL full", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("RTL_full");
}
TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialBreak) {
TextRun run = SetupFont(ahem, "OLOCARUF", false);
OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " RTL partial break", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("RTL_partial_break");
}
TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialDontBreak) {
TextRun run = SetupFont(ahem, "OLOCARUF", false);
OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
- perf_test::PrintResult("OffsetForPositionPerfTest", " RTL partial", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("RTL_partial");
}
INSTANTIATE_TEST_SUITE_P(OffsetForPosition,
@@ -155,15 +179,13 @@ INSTANTIATE_TEST_SUITE_P(OffsetForPosition,
TEST_P(CharacterRangePerfTest, LTRCharacterForPosition) {
TextRun run = SetupFont(ahem, "FURACOLO", true);
GetCharacter(run);
- perf_test::PrintResult("CharacterRangePerfTest", " LTR", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("LTR");
}
TEST_P(CharacterRangePerfTest, RTLCharacterForPosition) {
TextRun run = SetupFont(ahem, "OLOCARUF", false);
GetCharacter(run);
- perf_test::PrintResult("CharacterRangePerfTest", " RTL", "",
- timer.LapsPerSecond(), "runs/s", true);
+ ReportResult("RTL");
}
INSTANTIATE_TEST_SUITE_P(CharacterRange,
diff --git a/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc b/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
index c265e21a38e..4fb43e6a2cb 100644
--- a/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
@@ -17,7 +17,7 @@
#include "third_party/blink/renderer/platform/text/text_run.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
+#include "testing/perf/perf_result_reporter.h"
namespace blink {
namespace {
@@ -26,6 +26,16 @@ static const int kTimeLimitMillis = 2000;
static const int kWarmupRuns = 5;
static const int kTimeCheckInterval = 10;
+constexpr char kMetricPrefixShapingLineBreaker[] = "ShapingLineBreaker.";
+constexpr char kMetricThroughput[] = "throughput";
+
+perf_test::PerfResultReporter SetUpReporter(const std::string& story) {
+ perf_test::PerfResultReporter reporter(kMetricPrefixShapingLineBreaker,
+ story);
+ reporter.RegisterImportantMetric(kMetricThroughput, "runs/s");
+ return reporter;
+}
+
struct HarfBuzzShaperCallbackContext {
const HarfBuzzShaper* shaper;
const Font* font;
@@ -67,7 +77,6 @@ class ShapingLineBreakerPerfTest : public testing::Test {
void SetUp() override {
font_description.SetComputedSize(12.0);
font = Font(font_description);
- font.Update(nullptr);
}
void TearDown() override {}
@@ -164,8 +173,8 @@ TEST_F(ShapingLineBreakerPerfTest, ShapeLatinText) {
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
- perf_test::PrintResult("ShapingLineBreakerPerfTest", "shape latin text", "",
- timer_.LapsPerSecond(), "runs/s", true);
+ SetUpReporter("latin_text")
+ .AddResult(kMetricThroughput, timer_.LapsPerSecond());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h b/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h
index 36ccdd9b42d..9d3841aa77b 100644
--- a/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h
+++ b/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h
@@ -11,7 +11,6 @@ class StubGraphicsLayerClient : public GraphicsLayerClient {
~StubGraphicsLayerClient() override = default;
// GraphicsLayerClient implementation.
- void InvalidateTargetElementForTesting() override {}
IntRect ComputeInterestRect(
const GraphicsLayer*,
const IntRect& previous_interest_rect) const override {
diff --git a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
index 1f0238b9157..badc81ac3fe 100644
--- a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
@@ -13,38 +13,34 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
-class TestPaintArtifact::DummyRectClient : public FakeDisplayItemClient {
- public:
- IntRect VisualRect() const final { return rect_; }
- void SetVisualRect(const IntRect& rect) { rect_ = rect; }
-
- sk_sp<PaintRecord> MakeRecord(const FloatRect& rect, Color color) {
- rect_ = EnclosingIntRect(rect);
- PaintRecorder recorder;
- cc::PaintCanvas* canvas = recorder.beginRecording(rect);
- PaintFlags flags;
- flags.setColor(color.Rgb());
- canvas->drawRect(rect, flags);
- return recorder.finishRecordingAsPicture();
- }
-
- private:
- IntRect rect_;
-};
+sk_sp<PaintRecord> DummyRectClient::MakeRecord(const IntRect& rect,
+ Color color) {
+ rect_ = rect;
+ PaintRecorder recorder;
+ cc::PaintCanvas* canvas = recorder.beginRecording(rect);
+ PaintFlags flags;
+ flags.setColor(color.Rgb());
+ canvas->drawRect(rect, flags);
+ return recorder.finishRecordingAsPicture();
+}
TestPaintArtifact::TestPaintArtifact() : display_item_list_(0) {}
TestPaintArtifact::~TestPaintArtifact() = default;
-TestPaintArtifact& TestPaintArtifact::Chunk(int id) {
+static DummyRectClient& StaticDummyClient() {
DEFINE_STATIC_LOCAL(DummyRectClient, client, ());
- Chunk(client,
+ client.Validate();
+ return client;
+}
+
+TestPaintArtifact& TestPaintArtifact::Chunk(int id) {
+ Chunk(StaticDummyClient(),
static_cast<DisplayItem::Type>(DisplayItem::kDrawingFirst + id));
// The default bounds with magic numbers make the chunks have different bounds
// from each other, for e.g. RasterInvalidatorTest to check the tracked raster
@@ -55,13 +51,11 @@ TestPaintArtifact& TestPaintArtifact::Chunk(int id) {
return *this;
}
-TestPaintArtifact& TestPaintArtifact::Chunk(FakeDisplayItemClient& client,
+TestPaintArtifact& TestPaintArtifact::Chunk(DummyRectClient& client,
DisplayItem::Type type) {
- if (!paint_chunks_.IsEmpty())
- paint_chunks_.back().end_index = display_item_list_.size();
- paint_chunks_.push_back(PaintChunk(display_item_list_.size(), 0,
- PaintChunk::Id(client, type),
- PropertyTreeState::Root()));
+ paint_chunks_.push_back(
+ PaintChunk(display_item_list_.size(), display_item_list_.size(),
+ PaintChunk::Id(client, type), PropertyTreeState::Root()));
// Assume PaintController has processed this chunk.
paint_chunks_.back().client_is_just_created = false;
return *this;
@@ -73,7 +67,7 @@ TestPaintArtifact& TestPaintArtifact::Properties(
return *this;
}
-TestPaintArtifact& TestPaintArtifact::RectDrawing(const FloatRect& bounds,
+TestPaintArtifact& TestPaintArtifact::RectDrawing(const IntRect& bounds,
Color color) {
return RectDrawing(NewClient(), bounds, color);
}
@@ -84,15 +78,6 @@ TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
return ScrollHitTest(NewClient(), scroll_offset, scroll_container_bounds);
}
-TestPaintArtifact& TestPaintArtifact::RectDrawing(FakeDisplayItemClient& client,
- const FloatRect& bounds,
- Color color) {
- display_item_list_.AllocateAndConstruct<DrawingDisplayItem>(
- client, DisplayItem::kDrawingFirst,
- static_cast<DummyRectClient&>(client).MakeRecord(bounds, color));
- return *this;
-}
-
TestPaintArtifact& TestPaintArtifact::ForeignLayer(
scoped_refptr<cc::Layer> layer,
const FloatPoint& offset) {
@@ -100,16 +85,25 @@ TestPaintArtifact& TestPaintArtifact::ForeignLayer(
display_item_list_.AllocateAndConstruct<ForeignLayerDisplayItem>(
client, DisplayItem::kForeignLayerFirst, std::move(layer), offset,
nullptr);
+ DidAddDisplayItem();
+ return *this;
+}
+
+TestPaintArtifact& TestPaintArtifact::RectDrawing(DummyRectClient& client,
+ const IntRect& bounds,
+ Color color) {
+ display_item_list_.AllocateAndConstruct<DrawingDisplayItem>(
+ client, DisplayItem::kDrawingFirst, client.MakeRecord(bounds, color));
+ DidAddDisplayItem();
return *this;
}
TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
- FakeDisplayItemClient& client,
- const TransformPaintPropertyNode* scroll_offset,
+ DummyRectClient& client,
+ const TransformPaintPropertyNode* scroll_translation,
const IntRect& scroll_container_bounds) {
- display_item_list_.AllocateAndConstruct<ScrollHitTestDisplayItem>(
- client, DisplayItem::kScrollHitTest, scroll_offset,
- scroll_container_bounds);
+ paint_chunks_.back().EnsureHitTestData().scroll_translation =
+ scroll_translation;
return *this;
}
@@ -125,6 +119,14 @@ TestPaintArtifact& TestPaintArtifact::KnownToBeOpaque() {
TestPaintArtifact& TestPaintArtifact::Bounds(const IntRect& bounds) {
paint_chunks_.back().bounds = bounds;
+ paint_chunks_.back().drawable_bounds = bounds;
+ return *this;
+}
+
+TestPaintArtifact& TestPaintArtifact::DrawableBounds(
+ const IntRect& drawable_bounds) {
+ paint_chunks_.back().drawable_bounds = drawable_bounds;
+ DCHECK(paint_chunks_.back().bounds.Contains(drawable_bounds));
return *this;
}
@@ -134,19 +136,27 @@ TestPaintArtifact& TestPaintArtifact::Uncacheable() {
}
scoped_refptr<PaintArtifact> TestPaintArtifact::Build() {
- if (!paint_chunks_.IsEmpty())
- paint_chunks_.back().end_index = display_item_list_.size();
return PaintArtifact::Create(std::move(display_item_list_),
std::move(paint_chunks_));
}
-FakeDisplayItemClient& TestPaintArtifact::NewClient() {
+DummyRectClient& TestPaintArtifact::NewClient() {
dummy_clients_.push_back(std::make_unique<DummyRectClient>());
return *dummy_clients_.back();
}
-FakeDisplayItemClient& TestPaintArtifact::Client(wtf_size_t i) const {
+DummyRectClient& TestPaintArtifact::Client(wtf_size_t i) const {
return *dummy_clients_[i];
}
+void TestPaintArtifact::DidAddDisplayItem() {
+ auto& chunk = paint_chunks_.back();
+ DCHECK_EQ(chunk.end_index, display_item_list_.size() - 1);
+ const auto& item = display_item_list_.Last();
+ chunk.bounds.Unite(item.VisualRect());
+ if (item.DrawsContent())
+ chunk.drawable_bounds.Unite(item.VisualRect());
+ chunk.end_index++;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h
index 838ab969e8d..2e7a1f1108d 100644
--- a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h
+++ b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h
@@ -22,10 +22,20 @@ namespace blink {
class ClipPaintPropertyNode;
class EffectPaintPropertyNode;
-class FloatRect;
class PaintArtifact;
class TransformPaintPropertyNode;
+class DummyRectClient : public FakeDisplayItemClient {
+ public:
+ IntRect VisualRect() const final { return rect_; }
+ void SetVisualRect(const IntRect& rect) { rect_ = rect; }
+
+ sk_sp<PaintRecord> MakeRecord(const IntRect& rect, Color color);
+
+ private:
+ IntRect rect_;
+};
+
// Useful for quickly making a paint artifact in unit tests.
//
// If any method that automatically creates display item client is called, the
@@ -58,7 +68,7 @@ class TestPaintArtifact {
TestPaintArtifact& Chunk() { return Chunk(NewClient()); }
// Add a chunk with the specified client.
- TestPaintArtifact& Chunk(FakeDisplayItemClient&,
+ TestPaintArtifact& Chunk(DummyRectClient&,
DisplayItem::Type = DisplayItem::kDrawingFirst);
// This is for RasterInvalidatorTest, to create a chunk with specific id and
@@ -92,7 +102,7 @@ class TestPaintArtifact {
// Add display item in the chunk. Each display item will have a different
// automatically created client.
- TestPaintArtifact& RectDrawing(const FloatRect& bounds, Color color);
+ TestPaintArtifact& RectDrawing(const IntRect& bounds, Color color);
TestPaintArtifact& ScrollHitTest(
const TransformPaintPropertyNode* scroll_offset,
const IntRect& scroll_container_bounds);
@@ -101,18 +111,20 @@ class TestPaintArtifact {
const FloatPoint& offset);
// Add display item with the specified client in the chunk.
- TestPaintArtifact& RectDrawing(FakeDisplayItemClient&,
- const FloatRect& bounds,
- Color);
+ TestPaintArtifact& RectDrawing(DummyRectClient&,
+ const IntRect& bounds,
+ Color color);
TestPaintArtifact& ScrollHitTest(
- FakeDisplayItemClient&,
+ DummyRectClient&,
const TransformPaintPropertyNode* scroll_offset,
const IntRect& scroll_container_bounds);
// Sets fake bounds for the last paint chunk. Note that the bounds will be
// overwritten when the PaintArtifact is constructed if the chunk has any
- // display items.
+ // display items. Bounds() sets both bounds and drawable_bounds, while
+ // DrawableBounds() sets drawable_bounds only.
TestPaintArtifact& Bounds(const IntRect&);
+ TestPaintArtifact& DrawableBounds(const IntRect&);
TestPaintArtifact& OutsetForRasterEffects(float);
TestPaintArtifact& KnownToBeOpaque();
@@ -124,12 +136,13 @@ class TestPaintArtifact {
scoped_refptr<PaintArtifact> Build();
// Create a new display item client which is owned by this TestPaintArtifact.
- FakeDisplayItemClient& NewClient();
+ DummyRectClient& NewClient();
- FakeDisplayItemClient& Client(wtf_size_t) const;
+ DummyRectClient& Client(wtf_size_t) const;
private:
- class DummyRectClient;
+ void DidAddDisplayItem();
+
Vector<std::unique_ptr<DummyRectClient>> dummy_clients_;
DisplayItemList display_item_list_;
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc
index 70a486d1bcb..7464c9cd52f 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -39,8 +39,7 @@
#include "base/test/icu_test_util.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -55,23 +54,24 @@
namespace blink {
-class TestingPlatformSupport::TestingInterfaceProvider
- : public blink::InterfaceProvider {
+class TestingPlatformSupport::TestingBrowserInterfaceBroker
+ : public ThreadSafeBrowserInterfaceBrokerProxy {
public:
- TestingInterfaceProvider() = default;
- virtual ~TestingInterfaceProvider() = default;
+ TestingBrowserInterfaceBroker() = default;
+ ~TestingBrowserInterfaceBroker() override = default;
- void GetInterface(const char* name,
- mojo::ScopedMessagePipeHandle handle) override {
+ void GetInterfaceImpl(mojo::GenericPendingReceiver receiver) override {
auto& override_callback = GetOverrideCallback();
+ auto interface_name = receiver.interface_name().value_or("");
if (!override_callback.is_null()) {
- override_callback.Run(name, std::move(handle));
+ override_callback.Run(interface_name.c_str(), receiver.PassPipe());
return;
}
- if (std::string(name) == mojom::blink::MimeRegistry::Name_) {
+ if (interface_name == mojom::blink::MimeRegistry::Name_) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<MockMimeRegistry>(),
- mojo::PendingReceiver<mojom::blink::MimeRegistry>(std::move(handle)));
+ mojo::PendingReceiver<mojom::blink::MimeRegistry>(
+ receiver.PassPipe()));
return;
}
}
@@ -86,7 +86,7 @@ class TestingPlatformSupport::TestingInterfaceProvider
TestingPlatformSupport::ScopedOverrideMojoInterface::
ScopedOverrideMojoInterface(GetInterfaceCallback callback)
- : auto_reset_(&TestingInterfaceProvider::GetOverrideCallback(),
+ : auto_reset_(&TestingBrowserInterfaceBroker::GetOverrideCallback(),
std::move(callback)) {}
TestingPlatformSupport::ScopedOverrideMojoInterface::
@@ -94,7 +94,7 @@ TestingPlatformSupport::ScopedOverrideMojoInterface::
TestingPlatformSupport::TestingPlatformSupport()
: old_platform_(Platform::Current()),
- interface_provider_(new TestingInterfaceProvider) {
+ interface_broker_(base::MakeRefCounted<TestingBrowserInterfaceBroker>()) {
DCHECK(old_platform_);
DCHECK(WTF::IsMainThread());
}
@@ -129,11 +129,13 @@ WebData TestingPlatformSupport::UncompressDataResource(int resource_id) {
: WebData();
}
-InterfaceProvider* TestingPlatformSupport::GetInterfaceProvider() {
- return interface_provider_.get();
+ThreadSafeBrowserInterfaceBrokerProxy*
+TestingPlatformSupport::GetBrowserInterfaceBroker() {
+ return interface_broker_.get();
}
void TestingPlatformSupport::RunUntilIdle() {
+ ThreadState::HeapPointersOnStackScope scan_stack(ThreadState::Current());
base::RunLoop().RunUntilIdle();
}
@@ -169,7 +171,7 @@ ScopedUnittestsEnvironmentSetup::ScopedUnittestsEnvironmentSetup(int argc,
Platform::SetCurrentPlatformForTesting(dummy_platform_.get());
WTF::Partitions::Initialize();
- WTF::Initialize(nullptr);
+ WTF::Initialize();
// This must be called after WTF::Initialize(), because ThreadSpecific<>
// used in this function depends on WTF::IsMainThread().
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h
index eb1f8a94884..17ea8b4e183 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h
@@ -37,6 +37,7 @@
#include "base/auto_reset.h"
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/testing/code_cache_loader_mock.h"
@@ -69,7 +70,7 @@ class TestingPlatformSupport : public Platform {
WebData GetDataResource(int resource_id,
ui::ScaleFactor scale_factor) override;
WebData UncompressDataResource(int resource_id) override;
- InterfaceProvider* GetInterfaceProvider() override;
+ ThreadSafeBrowserInterfaceBrokerProxy* GetBrowserInterfaceBroker() override;
bool IsThreadedAnimationEnabled() override;
virtual void RunUntilIdle();
@@ -90,10 +91,10 @@ class TestingPlatformSupport : public Platform {
};
protected:
- class TestingInterfaceProvider;
+ class TestingBrowserInterfaceBroker;
Platform* const old_platform_;
- std::unique_ptr<TestingInterfaceProvider> interface_provider_;
+ scoped_refptr<TestingBrowserInterfaceBroker> interface_broker_;
private:
bool is_threaded_animation_enabled_ = false;
diff --git a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
index f78ee319d2c..1215543c54b 100644
--- a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
@@ -64,9 +64,9 @@ void RunPendingTasks() {
Thread::Current()->GetTaskRunner()->PostTask(FROM_HERE,
WTF::Bind(&ExitRunLoop));
- // We forbid GC in the tasks. Otherwise the registered GCTaskObserver tries
- // to run GC with NoHeapPointerOnStack.
- ThreadState::GCForbiddenScope gc_forbidden(ThreadState::Current());
+ // The following runloop can execute non-nested tasks with heap pointers
+ // living on stack, so we force both Oilpan and Unified GC to visit the stack.
+ ThreadState::HeapPointersOnStackScope scan_stack(ThreadState::Current());
EnterRunLoop();
}
@@ -131,6 +131,13 @@ scoped_refptr<SharedBuffer> ReadFromFile(const String& path) {
return SharedBuffer::Create(buffer.data(), buffer.size());
}
+String BlinkWebTestsFontsTestDataPath(const String& relative_path) {
+ return FilePathToWebString(
+ WebTestsFilePath()
+ .Append(FILE_PATH_LITERAL("external/wpt/fonts"))
+ .Append(WebStringToFilePath(relative_path)));
+}
+
LineReader::LineReader(const String& text) : text_(text), index_(0) {}
bool LineReader::GetNextLine(String* line) {
diff --git a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h
index 87d71599901..a964623e478 100644
--- a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.h
@@ -75,6 +75,12 @@ String PlatformTestDataPath(const String& relative_path = String());
// specified.
String AccessibilityTestDataPath(const String& relative_path = String());
+// Returns Blink web_tests fonts as an absolute path, i.e.
+// <blinkRootDir>/src/third_party/blink/web_tests/external/wpt/fonts/<relative_path>.
+// It returns the top fonts test directory if |relative_path| was not
+// specified.
+String BlinkWebTestsFontsTestDataPath(const String& relative_path = String());
+
scoped_refptr<SharedBuffer> ReadFromFile(const String& path);
class LineReader {
diff --git a/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc b/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc
index 653acd538f2..e07b21c2cf3 100644
--- a/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/url_test_helpers.cc
@@ -33,10 +33,10 @@
#include <string>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "services/network/public/mojom/load_timing_info.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_error.h"
-#include "third_party/blink/public/platform/web_url_load_timing.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
@@ -64,27 +64,27 @@ WebURL RegisterMockedURLLoadFromBase(const WebString& base_url,
void RegisterMockedURLLoad(const WebURL& full_url,
const WebString& file_path,
const WebString& mime_type) {
- WebURLLoadTiming timing;
- timing.Initialize();
+ network::mojom::LoadTimingInfoPtr timing =
+ network::mojom::LoadTimingInfo::New();
WebURLResponse response(full_url);
response.SetMimeType(mime_type);
response.SetHttpHeaderField(http_names::kContentType, mime_type);
response.SetHttpStatusCode(200);
- response.SetLoadTiming(timing);
+ response.SetLoadTiming(*timing);
RegisterMockedURLLoadWithCustomResponse(full_url, file_path, response);
}
void RegisterMockedErrorURLLoad(const WebURL& full_url) {
- WebURLLoadTiming timing;
- timing.Initialize();
+ network::mojom::LoadTimingInfoPtr timing =
+ network::mojom::LoadTimingInfo::New();
WebURLResponse response;
response.SetMimeType("image/png");
response.SetHttpHeaderField(http_names::kContentType, "image/png");
response.SetHttpStatusCode(404);
- response.SetLoadTiming(timing);
+ response.SetLoadTiming(*timing);
ResourceError error = ResourceError::Failure(full_url);
Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
index a58efcf47f6..a4bf13cebbe 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
@@ -6,6 +6,8 @@
#include <utility>
+#include "net/cookies/site_for_cookies.h"
+#include "services/network/public/cpp/resource_request.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_security_origin.h"
@@ -70,7 +72,7 @@ void WebURLLoaderMock::ServeAsynchronousRequest(
}
WebURL WebURLLoaderMock::ServeRedirect(
- const WebURLRequest& request,
+ const WebString& method,
const WebURLResponse& redirect_response) {
KURL redirect_url(redirect_response.HttpHeaderField("Location"));
@@ -78,9 +80,9 @@ WebURL WebURLLoaderMock::ServeRedirect(
bool report_raw_headers = false;
bool follow = client_->WillFollowRedirect(
- redirect_url, redirect_url, WebString(),
- network::mojom::ReferrerPolicy::kDefault, request.HttpMethod(),
- redirect_response, report_raw_headers);
+ redirect_url, net::SiteForCookies::FromUrl(redirect_url), WebString(),
+ network::mojom::ReferrerPolicy::kDefault, method, redirect_response,
+ report_raw_headers);
// |this| might be deleted in willFollowRedirect().
if (!self)
return redirect_url;
@@ -92,7 +94,13 @@ WebURL WebURLLoaderMock::ServeRedirect(
}
void WebURLLoaderMock::LoadSynchronously(
- const WebURLRequest& request,
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
WebURLLoaderClient* client,
WebURLResponse& response,
base::Optional<WebURLError>& error,
@@ -100,17 +108,22 @@ void WebURLLoaderMock::LoadSynchronously(
int64_t& encoded_data_length,
int64_t& encoded_body_length,
blink::WebBlobInfo& downloaded_blob) {
- DCHECK(factory_->IsMockedURL(request.Url()));
- factory_->LoadSynchronously(request, &response, &error, &data,
+ DCHECK(factory_->IsMockedURL(WebURL(KURL(request->url)))) << request->url;
+ factory_->LoadSynchronously(std::move(request), &response, &error, &data,
&encoded_data_length);
}
-void WebURLLoaderMock::LoadAsynchronously(const WebURLRequest& request,
- WebURLLoaderClient* client) {
+void WebURLLoaderMock::LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool no_mime_sniffing,
+ WebURLLoaderClient* client) {
DCHECK(client);
- DCHECK(factory_->IsMockedURL(request.Url())) << request.Url();
+ DCHECK(factory_->IsMockedURL(WebURL(KURL(request->url)))) << request->url;
client_ = client;
- factory_->LoadAsynchronouly(request, this);
+ factory_->LoadAsynchronouly(std::move(request), this);
}
void WebURLLoaderMock::Cancel() {
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
index 45d418e8766..0181a0889f9 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
@@ -39,20 +39,32 @@ class WebURLLoaderMock : public WebURLLoader {
const base::Optional<WebURLError>& error);
// Simulates the redirect being served.
- WebURL ServeRedirect(const WebURLRequest& request,
+ WebURL ServeRedirect(const WebString& method,
const WebURLResponse& redirect_response);
// WebURLLoader methods:
- void LoadSynchronously(const WebURLRequest&,
- WebURLLoaderClient* client,
- WebURLResponse&,
- base::Optional<WebURLError>&,
- WebData&,
- int64_t& encoded_data_length,
- int64_t& encoded_body_length,
- blink::WebBlobInfo& downloaded_blob) override;
- void LoadAsynchronously(const WebURLRequest& request,
- WebURLLoaderClient* client) override;
+ void LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient* client,
+ WebURLResponse&,
+ base::Optional<WebURLError>&,
+ WebData&,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ blink::WebBlobInfo& downloaded_blob) override;
+ void LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequest::ExtraData> request_extra_data,
+ int requestor_id,
+ bool download_to_network_cache_only,
+ bool no_mime_sniffing,
+ WebURLLoaderClient* client) override;
void SetDefersLoading(bool defer) override;
void DidChangePriority(WebURLRequest::Priority new_priority,
int intra_priority_value) override;
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
index 71d4ab676d5..c8d802cd025 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
@@ -118,17 +118,18 @@ void WebURLLoaderMockFactoryImpl::ServeAsynchronousRequests() {
while (!pending_loaders_.IsEmpty()) {
LoaderToRequestMap::iterator iter = pending_loaders_.begin();
base::WeakPtr<WebURLLoaderMock> loader(iter->key->GetWeakPtr());
- const WebURLRequest request = iter->value;
+ std::unique_ptr<network::ResourceRequest> request = std::move(iter->value);
pending_loaders_.erase(loader.get());
WebURLResponse response;
base::Optional<WebURLError> error;
WebData data;
- LoadRequest(request.Url(), &response, &error, &data);
+ LoadRequest(WebURL(KURL(request->url)), &response, &error, &data);
// Follow any redirects while the loader is still active.
while (response.HttpStatusCode() >= 300 &&
response.HttpStatusCode() < 400) {
- WebURL new_url = loader->ServeRedirect(request, response);
+ WebURL new_url = loader->ServeRedirect(
+ WebString::FromLatin1(request->method), response);
RunUntilIdle();
if (!loader || loader->is_cancelled() || loader->is_deferred())
break;
@@ -204,20 +205,20 @@ void WebURLLoaderMockFactoryImpl::CancelLoad(WebURLLoaderMock* loader) {
}
void WebURLLoaderMockFactoryImpl::LoadSynchronously(
- const WebURLRequest& request,
+ std::unique_ptr<network::ResourceRequest> request,
WebURLResponse* response,
base::Optional<WebURLError>* error,
WebData* data,
int64_t* encoded_data_length) {
- LoadRequest(request.Url(), response, error, data);
+ LoadRequest(WebURL(KURL(request->url)), response, error, data);
*encoded_data_length = data->size();
}
void WebURLLoaderMockFactoryImpl::LoadAsynchronouly(
- const WebURLRequest& request,
+ std::unique_ptr<network::ResourceRequest> request,
WebURLLoaderMock* loader) {
DCHECK(!pending_loaders_.Contains(loader));
- pending_loaders_.Set(loader, request);
+ pending_loaders_.Set(loader, std::move(request));
}
void WebURLLoaderMockFactoryImpl::RunUntilIdle() {
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
index 2af483ea74d..3fdebfd5142 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
@@ -18,6 +18,10 @@
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+namespace network {
+struct ResourceRequest;
+} // namespace network
+
namespace blink {
class TestingPlatformSupport;
@@ -58,12 +62,12 @@ class WebURLLoaderMockFactoryImpl : public WebURLLoaderMockFactory {
bool IsMockedURL(const WebURL& url);
// Called by the loader to load a resource.
- void LoadSynchronously(const WebURLRequest& request,
+ void LoadSynchronously(std::unique_ptr<network::ResourceRequest> request,
WebURLResponse* response,
base::Optional<WebURLError>* error,
WebData* data,
int64_t* encoded_data_length);
- void LoadAsynchronouly(const WebURLRequest& request,
+ void LoadAsynchronouly(std::unique_ptr<network::ResourceRequest> request,
WebURLLoaderMock* loader);
// Removes the loader from the list of pending loaders.
@@ -101,7 +105,8 @@ class WebURLLoaderMockFactoryImpl : public WebURLLoaderMockFactory {
WebURLLoaderTestDelegate* delegate_ = nullptr;
// The loaders that have not being served data yet.
- using LoaderToRequestMap = HashMap<WebURLLoaderMock*, WebURLRequest>;
+ using LoaderToRequestMap =
+ HashMap<WebURLLoaderMock*, std::unique_ptr<network::ResourceRequest>>;
LoaderToRequestMap pending_loaders_;
// All values must be valid, but we use Optional because HashMap requires
diff --git a/chromium/third_party/blink/renderer/platform/text/DEPS b/chromium/third_party/blink/renderer/platform/text/DEPS
index e6709d4f7a1..8cfc5a48108 100644
--- a/chromium/third_party/blink/renderer/platform/text/DEPS
+++ b/chromium/third_party/blink/renderer/platform/text/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+third_party/blink/renderer/platform/text",
# Dependencies.
+ "+base/i18n/rtl.h",
"+base/mac",
"+third_party/blink/renderer/platform/text/date_components.h",
"+third_party/blink/renderer/platform/heap",
@@ -16,4 +17,5 @@ include_rules = [
"+third_party/blink/renderer/platform/web_test_support.h",
"+third_party/blink/renderer/platform/weborigin",
"+third_party/blink/renderer/platform/wtf",
+ "+ui/base/ui_base_features.h",
]
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
index abe78aa5062..4d24ad93a59 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
@@ -12,8 +12,8 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/hyphenation/hyphenation.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h"
@@ -51,7 +51,7 @@ using Hyphenator = android::Hyphenator;
static mojo::Remote<mojom::blink::Hyphenation> ConnectToRemoteService() {
mojo::Remote<mojom::blink::Hyphenation> service;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
service.BindNewPipeAndPassReceiver());
return service;
}
diff --git a/chromium/third_party/blink/renderer/platform/text/icu_error.cc b/chromium/third_party/blink/renderer/platform/text/icu_error.cc
index 1aad8529944..ec72aac3447 100644
--- a/chromium/third_party/blink/renderer/platform/text/icu_error.cc
+++ b/chromium/third_party/blink/renderer/platform/text/icu_error.cc
@@ -11,7 +11,7 @@ namespace blink {
// Distinguish memory allocation failures from other errors.
// https://groups.google.com/a/chromium.org/d/msg/platform-architecture-dev/MP0k9WGnCjA/zIBiJtilBwAJ
static NOINLINE void ICUOutOfMemory() {
- OOM_CRASH();
+ OOM_CRASH(0);
}
void ICUError::HandleFailure() {
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_icu.cc b/chromium/third_party/blink/renderer/platform/text/locale_icu.cc
index 514931f881c..92fb99e0cc0 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_icu.cc
+++ b/chromium/third_party/blink/renderer/platform/text/locale_icu.cc
@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "ui/base/ui_base_features.h"
namespace blink {
@@ -249,7 +250,7 @@ void LocaleICU::InitializeCalendar() {
UCAL_FIRST_DAY_OF_WEEK) -
UCAL_SUNDAY;
- if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+ if (features::IsFormControlsRefreshEnabled()) {
week_day_short_labels_ = CreateLabelVector(
short_date_format_, UDAT_NARROW_WEEKDAYS, UCAL_SUNDAY, 7);
} else {
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_mac.mm b/chromium/third_party/blink/renderer/platform/text/locale_mac.mm
index 5f721423e39..c72f103fa1a 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/text/locale_mac.mm
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "ui/base/ui_base_features.h"
namespace blink {
@@ -136,7 +137,7 @@ const Vector<String>& LocaleMac::WeekDayShortLabels() {
if (!week_day_short_labels_.IsEmpty())
return week_day_short_labels_;
week_day_short_labels_.ReserveCapacity(7);
- NSArray* array = RuntimeEnabledFeatures::FormControlsRefreshEnabled()
+ NSArray* array = features::IsFormControlsRefreshEnabled()
? [ShortDateFormatter() veryShortWeekdaySymbols]
: [ShortDateFormatter() shortWeekdaySymbols];
if ([array count] == 7) {
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_mac_test.mm b/chromium/third_party/blink/renderer/platform/text/locale_mac_test.mm
index 5daadce443d..588ebb56372 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_mac_test.mm
+++ b/chromium/third_party/blink/renderer/platform/text/locale_mac_test.mm
@@ -291,13 +291,13 @@ TEST_F(LocaleMacTest, monthLabels) {
}
TEST_F(LocaleMacTest, weekDayShortLabels) {
- EXPECT_EQ("Sun", WeekDayShortLabel("en_US", kSunday));
- EXPECT_EQ("Wed", WeekDayShortLabel("en_US", kWednesday));
- EXPECT_EQ("Sat", WeekDayShortLabel("en_US", kSaturday));
+ EXPECT_EQ("S", WeekDayShortLabel("en_US", kSunday));
+ EXPECT_EQ("W", WeekDayShortLabel("en_US", kWednesday));
+ EXPECT_EQ("S", WeekDayShortLabel("en_US", kSaturday));
- EXPECT_EQ("dim.", WeekDayShortLabel("fr_FR", kSunday));
- EXPECT_EQ("mer.", WeekDayShortLabel("fr_FR", kWednesday));
- EXPECT_EQ("sam.", WeekDayShortLabel("fr_FR", kSaturday));
+ EXPECT_EQ("D", WeekDayShortLabel("fr_FR", kSunday));
+ EXPECT_EQ("M", WeekDayShortLabel("fr_FR", kWednesday));
+ EXPECT_EQ("S", WeekDayShortLabel("fr_FR", kSaturday));
EXPECT_EQ("\xE6\x97\xA5", WeekDayShortLabel("ja_JP", kSunday).Utf8());
EXPECT_EQ("\xE6\xB0\xB4", WeekDayShortLabel("ja_JP", kWednesday).Utf8());
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_win.cc b/chromium/third_party/blink/renderer/platform/text/locale_win.cc
index 2464478de20..3c86b59300d 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_win.cc
+++ b/chromium/third_party/blink/renderer/platform/text/locale_win.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "ui/base/ui_base_features.h"
namespace blink {
@@ -304,7 +305,7 @@ void LocaleWin::EnsureWeekDayShortLabels() {
LOCALE_SSHORTESTDAYNAME6};
week_day_short_labels_.ReserveCapacity(base::size(kTypes));
for (unsigned i = 0; i < base::size(kTypes); ++i) {
- if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+ if (features::IsFormControlsRefreshEnabled()) {
week_day_short_labels_.push_back(GetLocaleInfoString(kTypesRefresh[i]));
} else {
week_day_short_labels_.push_back(GetLocaleInfoString(kTypes[i]));
diff --git a/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc b/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc
index d614168111c..2b132b226c7 100644
--- a/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/locale_win_test.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/platform/text/date_components.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "ui/base/ui_base_features.h"
namespace blink {
@@ -188,14 +189,23 @@ TEST_F(LocaleWinTest, monthLabels) {
}
TEST_F(LocaleWinTest, weekDayShortLabels) {
- EXPECT_EQ("Sun", WeekDayShortLabel(kEnglishUS, kSunday));
- EXPECT_EQ("Wed", WeekDayShortLabel(kEnglishUS, kWednesday));
- EXPECT_EQ("Sat", WeekDayShortLabel(kEnglishUS, kSaturday));
-
- EXPECT_EQ("dim.", WeekDayShortLabel(kFrenchFR, kSunday));
- EXPECT_EQ("mer.", WeekDayShortLabel(kFrenchFR, kWednesday));
- EXPECT_EQ("sam.", WeekDayShortLabel(kFrenchFR, kSaturday));
-
+ if (features::IsFormControlsRefreshEnabled()) {
+ EXPECT_EQ("Su", WeekDayShortLabel(kEnglishUS, kSunday));
+ EXPECT_EQ("We", WeekDayShortLabel(kEnglishUS, kWednesday));
+ EXPECT_EQ("Sa", WeekDayShortLabel(kEnglishUS, kSaturday));
+
+ EXPECT_EQ("di", WeekDayShortLabel(kFrenchFR, kSunday));
+ EXPECT_EQ("me", WeekDayShortLabel(kFrenchFR, kWednesday));
+ EXPECT_EQ("sa", WeekDayShortLabel(kFrenchFR, kSaturday));
+ } else {
+ EXPECT_EQ("Sun", WeekDayShortLabel(kEnglishUS, kSunday));
+ EXPECT_EQ("Wed", WeekDayShortLabel(kEnglishUS, kWednesday));
+ EXPECT_EQ("Sat", WeekDayShortLabel(kEnglishUS, kSaturday));
+
+ EXPECT_EQ("dim.", WeekDayShortLabel(kFrenchFR, kSunday));
+ EXPECT_EQ("mer.", WeekDayShortLabel(kFrenchFR, kWednesday));
+ EXPECT_EQ("sam.", WeekDayShortLabel(kFrenchFR, kSaturday));
+ }
EXPECT_EQ("\xE6\x97\xA5", WeekDayShortLabel(kJapaneseJP, kSunday).Utf8());
EXPECT_EQ("\xE6\xB0\xB4", WeekDayShortLabel(kJapaneseJP, kWednesday).Utf8());
EXPECT_EQ("\xE5\x9C\x9F", WeekDayShortLabel(kJapaneseJP, kSaturday).Utf8());
diff --git a/chromium/third_party/blink/renderer/platform/text/text_direction.h b/chromium/third_party/blink/renderer/platform/text/text_direction.h
index a3f71b81b58..e92eed0ad8a 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_direction.h
+++ b/chromium/third_party/blink/renderer/platform/text/text_direction.h
@@ -28,6 +28,8 @@
#include <cstdint>
#include <iosfwd>
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
@@ -57,6 +59,17 @@ inline TextDirection DirectionFromLevel(unsigned level) {
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, TextDirection);
+inline base::i18n::TextDirection ToBaseTextDirection(TextDirection direction) {
+ switch (direction) {
+ case TextDirection::kLtr:
+ return base::i18n::TextDirection::LEFT_TO_RIGHT;
+ case TextDirection::kRtl:
+ return base::i18n::TextDirection::RIGHT_TO_LEFT;
+ }
+ NOTREACHED();
+ return base::i18n::TextDirection::UNKNOWN_DIRECTION;
+}
+
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_TEXT_DIRECTION_H_
diff --git a/chromium/third_party/blink/renderer/platform/theme_types.h b/chromium/third_party/blink/renderer/platform/theme_types.h
index 76f20d1e953..b5ed8c14e6e 100644
--- a/chromium/third_party/blink/renderer/platform/theme_types.h
+++ b/chromium/third_party/blink/renderer/platform/theme_types.h
@@ -45,8 +45,10 @@ enum ControlState {
typedef unsigned ControlStates;
// Must follow css_value_keywords.json5 order
+// kAutoPart is never returned by ComputedStyle::EffectiveAppearance()
enum ControlPart {
kNoControlPart,
+ kAutoPart,
kCheckboxPart,
kRadioPart,
kPushButtonPart,
diff --git a/chromium/third_party/blink/renderer/platform/timer_test.cc b/chromium/third_party/blink/renderer/platform/timer_test.cc
index 0511f0f9bda..54e9b1c6792 100644
--- a/chromium/third_party/blink/renderer/platform/timer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/timer_test.cc
@@ -119,7 +119,7 @@ class OnHeapTimerOwner final : public GarbageCollected<OnHeapTimerOwner> {
timer_.StartOneShot(interval, caller);
}
- void Trace(blink::Visitor* visitor) {}
+ void Trace(Visitor* visitor) {}
private:
void Fired(TimerBase*) {
@@ -655,8 +655,8 @@ TEST_F(TimerTest, MarkOnHeapTimerAsUnreachable) {
owner = nullptr;
// Explicit regular GC call to allow lazy sweeping.
ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping,
+ BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+ BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kForcedGCForTesting);
// Since the heap is laziy swept, owner is not yet destructed.
EXPECT_FALSE(record->OwnerIsDestructed());
@@ -667,6 +667,7 @@ TEST_F(TimerTest, MarkOnHeapTimerAsUnreachable) {
platform_->RunUntilIdle();
EXPECT_FALSE(record->TimerHasFired());
EXPECT_FALSE(record->OwnerIsDestructed());
+ ThreadState::Current()->CompleteSweep();
}
}
diff --git a/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc
index 1ee49fe627f..2d8da85b813 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc
@@ -35,7 +35,7 @@ namespace blink {
scoped_refptr<TransformOperation> Matrix3DTransformOperation::Accumulate(
const TransformOperation& other_op) {
DCHECK(other_op.IsSameType(*this));
- const auto& other = ToMatrix3DTransformOperation(other_op);
+ const auto& other = To<Matrix3DTransformOperation>(other_op);
// If either matrix is non-invertible, fail and fallback to replace.
if (!matrix_.IsInvertible() || !other.matrix_.IsInvertible())
diff --git a/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h
index 9c61b1265e2..81d3fd814f5 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_MATRIX_3D_TRANSFORM_OPERATION_H_
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -81,7 +82,13 @@ class PLATFORM_EXPORT Matrix3DTransformOperation final
TransformationMatrix matrix_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(Matrix3DTransformOperation);
+template <>
+struct DowncastTraits<Matrix3DTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return Matrix3DTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc
index 7ac6a31d386..ba42dc2947a 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc
@@ -28,7 +28,7 @@ namespace blink {
scoped_refptr<TransformOperation> MatrixTransformOperation::Accumulate(
const TransformOperation& other_op) {
DCHECK(other_op.IsSameType(*this));
- const MatrixTransformOperation& other = ToMatrixTransformOperation(other_op);
+ const auto& other = To<MatrixTransformOperation>(other_op);
TransformationMatrix from_t(other.a_, other.b_, other.c_, other.d_, other.e_,
other.f_);
diff --git a/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h
index bb943c2a603..d601a30c3fd 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -109,7 +110,13 @@ class PLATFORM_EXPORT MatrixTransformOperation final
double f_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(MatrixTransformOperation);
+template <>
+struct DowncastTraits<MatrixTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return MatrixTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc
index 7a491ab9d84..83fe6f2b0a0 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.cc
@@ -33,7 +33,7 @@ namespace blink {
scoped_refptr<TransformOperation> PerspectiveTransformOperation::Accumulate(
const TransformOperation& other) {
DCHECK(other.IsSameType(*this));
- double other_p = ToPerspectiveTransformOperation(other).p_;
+ double other_p = To<PerspectiveTransformOperation>(other).p_;
if (p_ == 0 && other_p == 0)
return nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
index 24628650440..e89ec30853f 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_PERSPECTIVE_TRANSFORM_OPERATION_H_
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -78,7 +79,13 @@ class PLATFORM_EXPORT PerspectiveTransformOperation final
double p_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(PerspectiveTransformOperation);
+template <>
+struct DowncastTraits<PerspectiveTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return PerspectiveTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc
index 4910951d0e3..648e24665ae 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc
@@ -43,7 +43,7 @@ bool RotateTransformOperation::operator==(
const TransformOperation& other) const {
if (!IsSameType(other))
return false;
- const Rotation& other_rotation = ToRotateTransformOperation(other).rotation_;
+ const auto& other_rotation = To<RotateTransformOperation>(other).rotation_;
return rotation_.axis == other_rotation.axis &&
rotation_.angle == other_rotation.angle;
}
@@ -62,7 +62,7 @@ scoped_refptr<TransformOperation> RotateTransformOperation::Accumulate(
const TransformOperation& other) {
DCHECK(IsMatchingOperationType(other.GetType()));
Rotation new_rotation =
- Rotation::Add(rotation_, ToRotateTransformOperation(other).rotation_);
+ Rotation::Add(rotation_, To<RotateTransformOperation>(other).rotation_);
return RotateTransformOperation::Create(new_rotation,
GetTypeForRotation(new_rotation));
}
@@ -91,8 +91,7 @@ scoped_refptr<TransformOperation> RotateTransformOperation::Blend(
DCHECK(from->PrimitiveType() == OperationType::kRotate3D);
OperationType type =
from->IsSameType(*this) ? type_ : OperationType::kRotate3D;
- const RotateTransformOperation& from_rotate =
- ToRotateTransformOperation(*from);
+ const auto& from_rotate = To<RotateTransformOperation>(*from);
return RotateTransformOperation::Create(
Rotation::Slerp(from_rotate.rotation_, rotation_, progress), type);
}
@@ -123,8 +122,7 @@ bool RotateAroundOriginTransformOperation::operator==(
const TransformOperation& other) const {
if (!IsSameType(other))
return false;
- const RotateAroundOriginTransformOperation& other_rotate =
- ToRotateAroundOriginTransformOperation(other);
+ const auto& other_rotate = To<RotateAroundOriginTransformOperation>(other);
const Rotation& other_rotation = other_rotate.rotation_;
return rotation_.axis == other_rotation.axis &&
rotation_.angle == other_rotation.angle &&
@@ -146,8 +144,7 @@ scoped_refptr<TransformOperation> RotateAroundOriginTransformOperation::Blend(
return RotateAroundOriginTransformOperation::Create(Angle() * progress,
origin_x_, origin_y_);
}
- const RotateAroundOriginTransformOperation& from_rotate =
- ToRotateAroundOriginTransformOperation(*from);
+ const auto& from_rotate = To<RotateAroundOriginTransformOperation>(*from);
return RotateAroundOriginTransformOperation::Create(
blink::Blend(from_rotate.Angle(), Angle(), progress),
blink::Blend(from_rotate.origin_x_, origin_x_, progress),
diff --git a/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h
index d5f7bdd8d1e..b0e054ca1fe 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/transforms/rotation.h"
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -107,7 +108,13 @@ class PLATFORM_EXPORT RotateTransformOperation : public TransformOperation {
const OperationType type_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(RotateTransformOperation);
+template <>
+struct DowncastTraits<RotateTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return RotateTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
class PLATFORM_EXPORT RotateAroundOriginTransformOperation final
: public RotateTransformOperation {
@@ -141,7 +148,13 @@ class PLATFORM_EXPORT RotateAroundOriginTransformOperation final
double origin_y_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(RotateAroundOriginTransformOperation);
+template <>
+struct DowncastTraits<RotateAroundOriginTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return RotateAroundOriginTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc
index 0f326e4ce8a..b6fb9a86cd5 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc
@@ -49,7 +49,7 @@ TransformOperation::OperationType GetTypeForScale(double x,
scoped_refptr<TransformOperation> ScaleTransformOperation::Accumulate(
const TransformOperation& other) {
DCHECK(other.CanBlendWith(*this));
- const auto& other_op = ToScaleTransformOperation(other);
+ const auto& other_op = To<ScaleTransformOperation>(other);
// Scale parameters are one in the identity transform function so use
// accumulation for one-based values.
double new_x = x_ + other_op.x_ - 1;
@@ -76,9 +76,11 @@ scoped_refptr<TransformOperation> ScaleTransformOperation::Blend(
double from_x = from_op ? from_op->x_ : 1.0;
double from_y = from_op ? from_op->y_ : 1.0;
double from_z = from_op ? from_op->z_ : 1.0;
+
+ bool is_3d = Is3DOperation() || (from && from->Is3DOperation());
return ScaleTransformOperation::Create(
blink::Blend(from_x, x_, progress), blink::Blend(from_y, y_, progress),
- blink::Blend(from_z, z_, progress), type_);
+ blink::Blend(from_z, z_, progress), is_3d ? kScale3D : kScale);
}
bool ScaleTransformOperation::CanBlendWith(
diff --git a/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.h
index 874e3efd558..39c678804c4 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/scale_transform_operation.h
@@ -26,6 +26,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_SCALE_TRANSFORM_OPERATION_H_
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -99,7 +100,13 @@ class PLATFORM_EXPORT ScaleTransformOperation final
OperationType type_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(ScaleTransformOperation);
+template <>
+struct DowncastTraits<ScaleTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return ScaleTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc
index 15eeabb0ed9..30c27055dfd 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc
@@ -28,7 +28,7 @@ namespace blink {
scoped_refptr<TransformOperation> SkewTransformOperation::Accumulate(
const TransformOperation& other) {
DCHECK(other.CanBlendWith(*this));
- const SkewTransformOperation& skew_other = ToSkewTransformOperation(other);
+ const auto& skew_other = To<SkewTransformOperation>(other);
return SkewTransformOperation::Create(angle_x_ + skew_other.angle_x_,
angle_y_ + skew_other.angle_y_, type_);
}
diff --git a/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.h
index 368ddfcb371..ab38b71f6ef 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/skew_transform_operation.h
@@ -27,6 +27,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -78,7 +79,12 @@ class PLATFORM_EXPORT SkewTransformOperation final : public TransformOperation {
OperationType type_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(SkewTransformOperation);
+template <>
+struct DowncastTraits<SkewTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return SkewTransformOperation::IsMatchingOperationType(transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h
index 6ccfd1d7c04..9ab8a4cd9bf 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/transform_operation.h
@@ -114,11 +114,6 @@ class PLATFORM_EXPORT TransformOperation
DISALLOW_COPY_AND_ASSIGN(TransformOperation);
};
-#define DEFINE_TRANSFORM_TYPE_CASTS(thisType) \
- DEFINE_TYPE_CASTS(thisType, TransformOperation, transform, \
- thisType::IsMatchingOperationType(transform->GetType()), \
- thisType::IsMatchingOperationType(transform.GetType()))
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TRANSFORMS_TRANSFORM_OPERATION_H_
diff --git a/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc b/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc
index 86fc8ff89ec..43dfa1f4ef9 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc
@@ -46,15 +46,15 @@ TransformOperation::OperationType GetTypeForTranslate(const Length& x,
bool x_zero = x.IsZero();
bool y_zero = x.IsZero();
bool z_zero = !z;
- if (!x_zero && !y_zero && !z_zero)
- return TransformOperation::kTranslate3D;
if (y_zero && z_zero)
return TransformOperation::kTranslateX;
if (x_zero && z_zero)
return TransformOperation::kTranslateY;
if (x_zero && y_zero)
return TransformOperation::kTranslateZ;
- return TransformOperation::kTranslate;
+ if (z_zero)
+ return TransformOperation::kTranslate;
+ return TransformOperation::kTranslate3D;
}
} // namespace
@@ -62,7 +62,7 @@ scoped_refptr<TransformOperation> TranslateTransformOperation::Accumulate(
const TransformOperation& other) {
DCHECK(other.CanBlendWith(*this));
- const auto& other_op = ToTranslateTransformOperation(other);
+ const auto& other_op = To<TranslateTransformOperation>(other);
Length new_x = AddLengths(x_, other_op.x_);
Length new_y = AddLengths(y_, other_op.y_);
double new_z = z_ + other_op.z_;
@@ -85,14 +85,16 @@ scoped_refptr<TransformOperation> TranslateTransformOperation::Blend(
blink::Blend(z_, 0., progress), type_);
}
- const auto* from_op = ToTranslateTransformOperation(from);
+ const auto* from_op = To<TranslateTransformOperation>(from);
const Length& from_x = from_op ? from_op->x_ : zero_length;
const Length& from_y = from_op ? from_op->y_ : zero_length;
double from_z = from_op ? from_op->z_ : 0;
+
+ bool is_3d = Is3DOperation() || (from && from->Is3DOperation());
return TranslateTransformOperation::Create(
x_.Blend(from_x, progress, kValueRangeAll),
y_.Blend(from_y, progress, kValueRangeAll),
- blink::Blend(from_z, z_, progress), type_);
+ blink::Blend(from_z, z_, progress), is_3d ? kTranslate3D : kTranslate);
}
bool TranslateTransformOperation::CanBlendWith(
diff --git a/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.h b/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.h
index b73cb80331e..6cdf6d9d37b 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/translate_transform_operation.h
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/geometry/length.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/transforms/transform_operation.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -119,7 +120,13 @@ class PLATFORM_EXPORT TranslateTransformOperation final
OperationType type_;
};
-DEFINE_TRANSFORM_TYPE_CASTS(TranslateTransformOperation);
+template <>
+struct DowncastTraits<TranslateTransformOperation> {
+ static bool AllowFrom(const TransformOperation& transform) {
+ return TranslateTransformOperation::IsMatchingOperationType(
+ transform.GetType());
+ }
+};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
index e88c93054d6..4be9b4f4f6a 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
@@ -17,6 +17,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
@@ -553,17 +554,16 @@ void VideoCaptureImpl::OnBufferReady(
uint8_t* u_data =
y_data + (media::VideoFrame::Rows(media::VideoFrame::kYPlane,
info->pixel_format,
- info->coded_size.height) *
+ info->coded_size.height()) *
info->strides->stride_by_plane[0]);
uint8_t* v_data =
u_data + (media::VideoFrame::Rows(media::VideoFrame::kUPlane,
info->pixel_format,
- info->coded_size.height) *
+ info->coded_size.height()) *
info->strides->stride_by_plane[1]);
frame = media::VideoFrame::WrapExternalYuvData(
info->pixel_format, gfx::Size(info->coded_size),
- gfx::Rect(info->visible_rect),
- gfx::Size(info->visible_rect.width, info->visible_rect.height),
+ gfx::Rect(info->visible_rect), info->visible_rect.size(),
info->strides->stride_by_plane[0],
info->strides->stride_by_plane[1],
info->strides->stride_by_plane[2], y_data, u_data, v_data,
@@ -571,8 +571,7 @@ void VideoCaptureImpl::OnBufferReady(
} else {
frame = media::VideoFrame::WrapExternalData(
info->pixel_format, gfx::Size(info->coded_size),
- gfx::Rect(info->visible_rect),
- gfx::Size(info->visible_rect.width, info->visible_rect.height),
+ gfx::Rect(info->visible_rect), info->visible_rect.size(),
const_cast<uint8_t*>(buffer_context->data()),
buffer_context->data_size(), info->timestamp);
}
@@ -582,8 +581,7 @@ void VideoCaptureImpl::OnBufferReady(
// the data without attaching the shared region to the frame.
frame = media::VideoFrame::WrapExternalData(
info->pixel_format, gfx::Size(info->coded_size),
- gfx::Rect(info->visible_rect),
- gfx::Size(info->visible_rect.width, info->visible_rect.height),
+ gfx::Rect(info->visible_rect), info->visible_rect.size(),
const_cast<uint8_t*>(buffer_context->data()),
buffer_context->data_size(), info->timestamp);
break;
@@ -600,8 +598,7 @@ void VideoCaptureImpl::OnBufferReady(
frame = media::VideoFrame::WrapNativeTextures(
info->pixel_format, mailbox_holder_array,
media::VideoFrame::ReleaseMailboxCB(), gfx::Size(info->coded_size),
- gfx::Rect(info->visible_rect),
- gfx::Size(info->visible_rect.width, info->visible_rect.height),
+ gfx::Rect(info->visible_rect), info->visible_rect.size(),
info->timestamp);
break;
}
@@ -641,8 +638,7 @@ void VideoCaptureImpl::OnBufferReady(
FROM_HERE,
base::BindOnce(
&BufferContext::BindBufferToTextureOnMediaThread,
- std::move(buffer_context), base::Passed(&info),
- base::Passed(&gmb), frame,
+ std::move(buffer_context), std::move(info), std::move(gmb), frame,
media::BindToCurrentLoop(base::BindOnce(
&VideoCaptureImpl::OnVideoFrameReady,
weak_factory_.GetWeakPtr(), buffer_id, reference_time))));
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
index 2a1682941ce..650f0da130d 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
@@ -148,10 +148,10 @@ class VideoCaptureImplTest : public ::testing::Test {
void(const Vector<media::VideoCaptureFormat>&));
void StartCapture(int client_id, const media::VideoCaptureParams& params) {
- const auto state_update_callback = base::Bind(
+ const auto state_update_callback = WTF::BindRepeating(
&VideoCaptureImplTest::OnStateUpdate, base::Unretained(this));
- const auto frame_ready_callback =
- base::Bind(&VideoCaptureImplTest::OnFrameReady, base::Unretained(this));
+ const auto frame_ready_callback = WTF::BindRepeating(
+ &VideoCaptureImplTest::OnFrameReady, base::Unretained(this));
video_capture_impl_->StartCapture(client_id, params, state_update_callback,
frame_ready_callback);
@@ -199,8 +199,8 @@ class VideoCaptureImplTest : public ::testing::Test {
info->timestamp = now - base::TimeTicks();
info->pixel_format = pixel_format;
- info->coded_size = WebSize(size);
- info->visible_rect = WebRect(gfx::Rect(size));
+ info->coded_size = size;
+ info->visible_rect = gfx::Rect(size);
info->color_space = gfx::ColorSpace();
video_capture_impl_->OnBufferReady(buffer_id, std::move(info));
@@ -211,17 +211,14 @@ class VideoCaptureImplTest : public ::testing::Test {
}
void GetDeviceSupportedFormats() {
- const base::Callback<void(const Vector<media::VideoCaptureFormat>&)>
- callback = base::Bind(&VideoCaptureImplTest::OnDeviceSupportedFormats,
- base::Unretained(this));
- video_capture_impl_->GetDeviceSupportedFormats(callback);
+ video_capture_impl_->GetDeviceSupportedFormats(
+ WTF::Bind(&VideoCaptureImplTest::OnDeviceSupportedFormats,
+ base::Unretained(this)));
}
void GetDeviceFormatsInUse() {
- const base::Callback<void(const Vector<media::VideoCaptureFormat>&)>
- callback = base::Bind(&VideoCaptureImplTest::OnDeviceFormatsInUse,
- base::Unretained(this));
- video_capture_impl_->GetDeviceFormatsInUse(callback);
+ video_capture_impl_->GetDeviceFormatsInUse(WTF::Bind(
+ &VideoCaptureImplTest::OnDeviceFormatsInUse, base::Unretained(this)));
}
void OnStateChanged(media::mojom::VideoCaptureState state) {
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/DEPS b/chromium/third_party/blink/renderer/platform/weborigin/DEPS
index 0d5faf41ba0..ee4bd6ccd3e 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/DEPS
+++ b/chromium/third_party/blink/renderer/platform/weborigin/DEPS
@@ -18,3 +18,7 @@ include_rules = [
"+third_party/blink/renderer/platform/testing",
"+third_party/blink/renderer/platform/wtf",
]
+
+specific_include_rules = {
+ "kurl_test.cc": [ "+third_party/blink/renderer/platform/scheduler/public/thread.h" ],
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc b/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
index 4ab44fc6c7d..ce96d1bef63 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_statics.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
+#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "url/gurl.h"
#include "url/url_util.h"
#ifndef NDEBUG
@@ -125,12 +126,6 @@ bool IsValidProtocol(const String& protocol) {
return true;
}
-void KURL::Initialize() {
- // This must be called before we create other threads to
- // avoid racy static local initialization.
- BlankURL();
-}
-
String KURL::StrippedForUseAsReferrer() const {
if (!ProtocolIsInHTTPFamily())
return String();
@@ -169,8 +164,11 @@ bool ProtocolIsJavaScript(const String& url) {
}
const KURL& BlankURL() {
- DEFINE_STATIC_LOCAL(KURL, static_blank_url, ("about:blank"));
- return static_blank_url;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<KURL>, static_blank_url, ());
+ KURL& blank_url = *static_blank_url;
+ if (blank_url.IsNull())
+ blank_url = KURL(AtomicString("about:blank"));
+ return blank_url;
}
bool KURL::IsAboutBlankURL() const {
@@ -178,8 +176,11 @@ bool KURL::IsAboutBlankURL() const {
}
const KURL& SrcdocURL() {
- DEFINE_STATIC_LOCAL(KURL, static_srcdoc_url, ("about:srcdoc"));
- return static_srcdoc_url;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<KURL>, static_srcdoc_url, ());
+ KURL& srcdoc_url = *static_srcdoc_url;
+ if (srcdoc_url.IsNull())
+ srcdoc_url = KURL(AtomicString("about:srcdoc"));
+ return srcdoc_url;
}
bool KURL::IsAboutSrcdocURL() const {
@@ -187,8 +188,8 @@ bool KURL::IsAboutSrcdocURL() const {
}
const KURL& NullURL() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(KURL, static_null_url, ());
- return static_null_url;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<KURL>, static_null_url, ());
+ return *static_null_url;
}
String KURL::ElidedString() const {
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl.h b/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
index 6500b29d892..8ddb31a682b 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
@@ -77,10 +77,6 @@ class PLATFORM_EXPORT KURL {
USING_FAST_MALLOC(KURL);
public:
- // This must be called during initialization (before we create
- // other threads).
- static void Initialize();
-
KURL();
KURL(const KURL&);
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
index 32b3ae8a580..94a471da823 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -37,6 +37,7 @@
#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "url/url_util.h"
@@ -873,6 +874,43 @@ TEST(KURLTest, strippedForUseAsReferrer) {
}
}
+TEST(KURLTest, ThreadSafesStaticKurlGetters) {
+#if DCHECK_IS_ON()
+ // Simulate the static getters being called during/after threads have been
+ // started, so that StaticSingleton's thread checks will be applied.
+ WTF::WillCreateThread();
+#endif
+
+ // Take references to the static KURLs, so that each has two references to
+ // its internal StringImpl, rather than one.
+ KURL blank_url = BlankURL();
+ EXPECT_FALSE(blank_url.IsEmpty());
+ KURL srcdoc_url = SrcdocURL();
+ EXPECT_FALSE(srcdoc_url.IsEmpty());
+ KURL null_url = NullURL();
+ EXPECT_TRUE(null_url.IsNull());
+
+ auto thread =
+ Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread));
+ thread->GetTaskRunner()->PostTask(FROM_HERE, base::BindOnce([]() {
+ // Reference each of the static KURLs
+ // again, from the background thread,
+ // which should succeed without thread
+ // verifier checks firing.
+ KURL blank_url = BlankURL();
+ EXPECT_FALSE(blank_url.IsEmpty());
+ KURL srcdoc_url = SrcdocURL();
+ EXPECT_FALSE(srcdoc_url.IsEmpty());
+ KURL null_url = NullURL();
+ EXPECT_TRUE(null_url.IsNull());
+ }));
+
+#if DCHECK_IS_ON()
+ // Restore the IsBeforeThreadCreated() flag.
+ WTF::SetIsBeforeThreadCreatedForTest();
+#endif
+}
+
enum class PortIsValid {
// The constructor does strict checking. Ports which are considered valid by
// the constructor are kAlways valid.
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/reporting_disposition.h b/chromium/third_party/blink/renderer/platform/weborigin/reporting_disposition.h
new file mode 100644
index 00000000000..54060e075c4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/weborigin/reporting_disposition.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REPORTING_DISPOSITION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REPORTING_DISPOSITION_H_
+
+namespace blink {
+
+enum class ReportingDisposition {
+ kSuppressReporting,
+ kReport,
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REPORTING_DISPOSITION_H_
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
index 3903a94f5df..5e53886a855 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
@@ -112,12 +112,6 @@ URLSchemesRegistry& GetMutableURLSchemesRegistry() {
} // namespace
-// Must be called before we create other threads to avoid racy static local
-// initialization.
-void SchemeRegistry::Initialize() {
- GetURLSchemesRegistry();
-}
-
void SchemeRegistry::RegisterURLSchemeAsLocal(const String& scheme) {
DCHECK_EQ(scheme, scheme.LowerASCII());
GetMutableURLSchemesRegistry().local_schemes.insert(scheme);
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h
index 4ef1bdfd07f..3a6f7734f19 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/scheme_registry.h
@@ -49,8 +49,6 @@ class PLATFORM_EXPORT SchemeRegistry {
STATIC_ONLY(SchemeRegistry);
public:
- static void Initialize();
-
static void RegisterURLSchemeAsLocal(const String&);
static bool ShouldTreatURLSchemeAsLocal(const String&);
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
index e71853c7d3c..c448d326226 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -237,7 +237,7 @@ scoped_refptr<SecurityOrigin> SecurityOrigin::CreateFromUrlOrigin(
DCHECK(String::FromUTF8(tuple.host()).ContainsOnlyASCIIOrEmpty());
scoped_refptr<SecurityOrigin> tuple_origin;
- if (!tuple.IsInvalid()) {
+ if (tuple.IsValid()) {
String scheme = String::FromUTF8(tuple.scheme());
String host = String::FromUTF8(tuple.host());
uint16_t port = tuple.port();
@@ -327,58 +327,7 @@ bool SecurityOrigin::CanAccess(const SecurityOrigin* other,
return true;
}
- // This is needed to ensure an origin can access to itself under nullified
- // document.domain.
- // TODO(tzik): Update the nulled domain handling and remove this condition.
- if (this == other) {
- detail = AccessResultDomainDetail::kDomainNotRelevant;
- return true;
- }
-
- if (IsOpaque() || other->IsOpaque()) {
- detail = AccessResultDomainDetail::kDomainNotRelevant;
- return nonce_if_opaque_ == other->nonce_if_opaque_;
- }
-
- // document.domain handling, as per
- // https://html.spec.whatwg.org/C/#dom-document-domain:
- //
- // 1) Neither document has set document.domain. In this case, we insist
- // that the scheme, host, and port of the URLs match.
- //
- // 2) Both documents have set document.domain. In this case, we insist
- // that the documents have set document.domain to the same value and
- // that the scheme of the URLs match. Ports do not need to match.
- bool can_access = false;
- if (protocol_ == other->protocol_) {
- if (!domain_was_set_in_dom_ && !other->domain_was_set_in_dom_) {
- detail = AccessResultDomainDetail::kDomainNotSet;
- if (host_ == other->host_ && port_ == other->port_)
- can_access = true;
- } else if (domain_was_set_in_dom_ && other->domain_was_set_in_dom_) {
- if (domain_ == other->domain_) {
- can_access = true;
- detail = (host_ == other->host_ && port_ == other->port_)
- ? AccessResultDomainDetail::kDomainMatchUnnecessary
- : AccessResultDomainDetail::kDomainMatchNecessary;
- } else {
- detail = (host_ == other->host_ && port_ == other->port_)
- ? AccessResultDomainDetail::kDomainMismatch
- : AccessResultDomainDetail::kDomainNotRelevant;
- }
- } else {
- detail = (host_ == other->host_ && port_ == other->port_)
- ? AccessResultDomainDetail::kDomainSetByOnlyOneOrigin
- : AccessResultDomainDetail::kDomainNotRelevant;
- }
- } else {
- detail = AccessResultDomainDetail::kDomainNotRelevant;
- }
-
- if (can_access && IsLocal() && !PassesFileCheck(other)) {
- detail = AccessResultDomainDetail::kDomainNotRelevant;
- can_access = false;
- }
+ bool can_access = IsSameOriginDomainWith(other, detail);
// Compare that the clusters are the same.
if (can_access && !cross_agent_cluster_access_ &&
@@ -629,6 +578,65 @@ bool SecurityOrigin::AreSameOrigin(const KURL& a, const KURL& b) {
return origin_b->IsSameOriginWith(origin_a.get());
}
+bool SecurityOrigin::IsSameOriginDomainWith(
+ const SecurityOrigin* other,
+ AccessResultDomainDetail& detail) const {
+ // This is needed to ensure an origin can access to itself under nullified
+ // document.domain.
+ // TODO(tzik): Update the nulled domain handling and remove this condition.
+ if (this == other) {
+ detail = AccessResultDomainDetail::kDomainNotRelevant;
+ return true;
+ }
+
+ if (IsOpaque() || other->IsOpaque()) {
+ detail = AccessResultDomainDetail::kDomainNotRelevant;
+ return nonce_if_opaque_ == other->nonce_if_opaque_;
+ }
+
+ // document.domain handling, as per
+ // https://html.spec.whatwg.org/C/#dom-document-domain:
+ //
+ // 1) Neither document has set document.domain. In this case, we insist
+ // that the scheme, host, and port of the URLs match.
+ //
+ // 2) Both documents have set document.domain. In this case, we insist
+ // that the documents have set document.domain to the same value and
+ // that the scheme of the URLs match. Ports do not need to match.
+ bool can_access = false;
+ if (protocol_ == other->protocol_) {
+ if (!domain_was_set_in_dom_ && !other->domain_was_set_in_dom_) {
+ detail = AccessResultDomainDetail::kDomainNotSet;
+ if (host_ == other->host_ && port_ == other->port_)
+ can_access = true;
+ } else if (domain_was_set_in_dom_ && other->domain_was_set_in_dom_) {
+ if (domain_ == other->domain_) {
+ can_access = true;
+ detail = (host_ == other->host_ && port_ == other->port_)
+ ? AccessResultDomainDetail::kDomainMatchUnnecessary
+ : AccessResultDomainDetail::kDomainMatchNecessary;
+ } else {
+ detail = (host_ == other->host_ && port_ == other->port_)
+ ? AccessResultDomainDetail::kDomainMismatch
+ : AccessResultDomainDetail::kDomainNotRelevant;
+ }
+ } else {
+ detail = (host_ == other->host_ && port_ == other->port_)
+ ? AccessResultDomainDetail::kDomainSetByOnlyOneOrigin
+ : AccessResultDomainDetail::kDomainNotRelevant;
+ }
+ } else {
+ detail = AccessResultDomainDetail::kDomainNotRelevant;
+ }
+
+ if (can_access && IsLocal() && !PassesFileCheck(other)) {
+ detail = AccessResultDomainDetail::kDomainNotRelevant;
+ can_access = false;
+ }
+
+ return can_access;
+}
+
const KURL& SecurityOrigin::UrlWithUniqueOpaqueOrigin() {
DCHECK(IsMainThread());
DEFINE_STATIC_LOCAL(const KURL, url, ("data:,"));
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
index 7a02c33ca25..f2ee4da33cf 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -139,19 +139,22 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
static bool IsSecure(const KURL&);
// Returns true if this SecurityOrigin can script objects in the given
- // SecurityOrigin. For example, call this function before allowing
- // script from one security origin to read or write objects from
- // another SecurityOrigin.
+ // SecurityOrigin. This check is similar to `IsSameOriginDomainWith()`, but
+ // additionally takes "universal access" flag into account, as well as the
+ // origin's agent cluster (see https://tc39.es/ecma262/#sec-agent-clusters).
+ //
+ // Note: This kind of access check should be rare; `IsSameOriginWith()` is
+ // almost certainly the right choice for new security checks.
+ //
+ // TODO(1027191): We're currently calling this method in a number of places
+ // where either `IsSameOriginWith()` or `IsSameOriginDomainWith()` might
+ // be more appropriate. We should audit its existing usage, and it might
+ // make sense to move it out of SecurityOrigin entirely to align it more
+ // tightly with `BindingSecurity` where it's clearly necessary.
bool CanAccess(const SecurityOrigin* other) const {
AccessResultDomainDetail unused_detail;
return CanAccess(other, unused_detail);
}
-
- // Returns true if this SecurityOrigin can script objects in |other|, just
- // as above, but also returns the category into which the access check fell.
- //
- // TODO(crbug.com/787905): Remove this variant once we have enough data to
- // make decisions about `document.domain`.
bool CanAccess(const SecurityOrigin* other, AccessResultDomainDetail&) const;
// Returns true if this SecurityOrigin can read content retrieved from
@@ -294,6 +297,25 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
bool IsSameOriginWith(const SecurityOrigin*) const;
static bool AreSameOrigin(const KURL& a, const KURL& b);
+ // This method implements HTML's "same origin-domain" check, which takes
+ // `document.domain` into account when comparing two origins.
+ //
+ // This method does not take the "universal access" flag into account. It does
+ // take the "local access" flag into account, considering `file:` origins that
+ // set the flag to be same origin-domain with all other `file:` origins that
+ // set the flag (assuming no `document.domain` mismatch).
+ //
+ // Note: Same origin-domain checks should be rare, and `IsSameOriginWith()`
+ // is almost certainly the right choice for new security checks.
+ //
+ // https://html.spec.whatwg.org/#same-origin-domain
+ bool IsSameOriginDomainWith(const SecurityOrigin* other) const {
+ AccessResultDomainDetail unused_detail;
+ return IsSameOriginDomainWith(other, unused_detail);
+ }
+ bool IsSameOriginDomainWith(const SecurityOrigin*,
+ AccessResultDomainDetail&) const;
+
static const KURL& UrlWithUniqueOpaqueOrigin();
// Transfer origin privileges from another security origin.
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
index 3c10ca1288f..879eef2c67e 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
@@ -662,6 +662,7 @@ TEST_F(SecurityOriginTest, CanonicalizeHost) {
}
TEST_F(SecurityOriginTest, UrlOriginConversions) {
+ url::ScopedSchemeRegistryForTests scoped_registry;
url::AddLocalScheme("nonstandard-but-local");
SchemeRegistry::RegisterURLSchemeAsLocal("nonstandard-but-local");
struct TestCases {
@@ -884,6 +885,7 @@ TEST_F(SecurityOriginTest, NonStandardScheme) {
}
TEST_F(SecurityOriginTest, NonStandardSchemeWithAndroidWebViewHack) {
+ url::ScopedSchemeRegistryForTests scoped_registry;
url::EnableNonStandardSchemesForAndroidWebView();
scoped_refptr<const SecurityOrigin> origin =
SecurityOrigin::CreateFromString("cow://");
@@ -891,7 +893,6 @@ TEST_F(SecurityOriginTest, NonStandardSchemeWithAndroidWebViewHack) {
EXPECT_EQ("cow", origin->Protocol());
EXPECT_EQ("", origin->Host());
EXPECT_EQ(0, origin->Port());
- url::ResetForTests();
}
TEST_F(SecurityOriginTest, OpaqueIsolatedCopy) {
@@ -960,7 +961,7 @@ TEST_F(SecurityOriginTest, IsSameOriginWith) {
// Opaque
{false, "data:text/html,whatever", "data:text/html,whatever"}};
- for (auto test : tests) {
+ for (const auto& test : tests) {
SCOPED_TRACE(testing::Message() << "Origin 1: `" << test.a << "` "
<< "Origin 2: `" << test.b << "`\n");
scoped_refptr<SecurityOrigin> a = SecurityOrigin::CreateFromString(test.a);
@@ -1036,4 +1037,136 @@ TEST_F(SecurityOriginTest, IsSameOriginWithWithLocalScheme) {
EXPECT_FALSE(b->IsSameOriginWith(a.get()));
}
+TEST_F(SecurityOriginTest, IsSameOriginDomainWith) {
+ struct TestCase {
+ bool same_origin_domain;
+ const char* a;
+ const char* domain_a; // empty string === no `domain` set.
+ const char* b;
+ const char* domain_b;
+ } tests[] = {
+ {true, "https://a.com", "", "https://a.com", ""},
+ {false, "https://a.com", "a.com", "https://a.com", ""},
+ {true, "https://a.com", "a.com", "https://a.com", "a.com"},
+ {false, "https://sub.a.com", "", "https://a.com", ""},
+ {false, "https://sub.a.com", "a.com", "https://a.com", ""},
+ {true, "https://sub.a.com", "a.com", "https://a.com", "a.com"},
+ {true, "https://sub.a.com", "a.com", "https://sub.a.com", "a.com"},
+ {true, "https://sub.a.com", "a.com", "https://sub.sub.a.com", "a.com"},
+
+ // Schemes.
+ {false, "https://a.com", "", "http://a.com", ""},
+ {false, "https://a.com", "a.com", "http://a.com", ""},
+ {false, "https://a.com", "a.com", "http://a.com", "a.com"},
+ {false, "https://sub.a.com", "a.com", "http://a.com", ""},
+ {false, "https://a.com", "a.com", "http://sub.a.com", "a.com"},
+
+ // Ports? Why would they matter?
+ {true, "https://a.com:443", "", "https://a.com", ""},
+ {false, "https://a.com:444", "", "https://a.com", ""},
+ {false, "https://a.com:444", "", "https://a.com:442", ""},
+
+ {false, "https://a.com:443", "a.com", "https://a.com", ""},
+ {false, "https://a.com:444", "a.com", "https://a.com", ""},
+ {false, "https://a.com:444", "a.com", "https://a.com:442", ""},
+
+ {true, "https://a.com:443", "a.com", "https://a.com", "a.com"},
+ {true, "https://a.com:444", "a.com", "https://a.com", "a.com"},
+ {true, "https://a.com:444", "a.com", "https://a.com:442", "a.com"},
+
+ {false, "https://sub.a.com:443", "", "https://a.com", ""},
+ {false, "https://sub.a.com:444", "", "https://a.com", ""},
+ {false, "https://sub.a.com:444", "", "https://a.com:442", ""},
+
+ {false, "https://sub.a.com:443", "a.com", "https://a.com", ""},
+ {false, "https://sub.a.com:444", "a.com", "https://a.com", ""},
+ {false, "https://sub.a.com:444", "a.com", "https://a.com:442", ""},
+
+ {true, "https://sub.a.com:443", "a.com", "https://a.com", "a.com"},
+ {true, "https://sub.a.com:444", "a.com", "https://a.com", "a.com"},
+ {true, "https://sub.a.com:444", "a.com", "https://a.com:442", "a.com"},
+ };
+
+ for (const auto& test : tests) {
+ SCOPED_TRACE(testing::Message()
+ << "Origin 1: `" << test.a << "` (`" << test.domain_a << "`)\n"
+ << "Origin 2: `" << test.b << "` (`" << test.domain_b
+ << "`)\n");
+ scoped_refptr<SecurityOrigin> a = SecurityOrigin::CreateFromString(test.a);
+ if (strlen(test.domain_a))
+ a->SetDomainFromDOM(test.domain_a);
+ scoped_refptr<SecurityOrigin> b = SecurityOrigin::CreateFromString(test.b);
+ if (strlen(test.domain_b))
+ b->SetDomainFromDOM(test.domain_b);
+ EXPECT_EQ(test.same_origin_domain, a->IsSameOriginDomainWith(b.get()));
+ EXPECT_EQ(test.same_origin_domain, b->IsSameOriginDomainWith(a.get()));
+
+ // Self-comparison
+ EXPECT_TRUE(a->IsSameOriginDomainWith(a.get()));
+ EXPECT_TRUE(b->IsSameOriginDomainWith(b.get()));
+
+ // DeriveNewOpaqueOrigin
+ EXPECT_FALSE(a->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(a.get()));
+ EXPECT_FALSE(b->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(a.get()));
+ EXPECT_FALSE(a->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(b.get()));
+ EXPECT_FALSE(b->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(b.get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(a->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(a->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(a->IsSameOriginDomainWith(b->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(b->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(a->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(
+ a->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(b->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(
+ b->DeriveNewOpaqueOrigin().get()));
+
+ // UniversalAccess does not override.
+ a->GrantUniversalAccess();
+ EXPECT_EQ(test.same_origin_domain, a->IsSameOriginDomainWith(b.get()));
+ EXPECT_EQ(test.same_origin_domain, b->IsSameOriginDomainWith(a.get()));
+ }
+}
+
+TEST_F(SecurityOriginTest, IsSameOriginDomainWithWithLocalScheme) {
+ scoped_refptr<SecurityOrigin> a =
+ SecurityOrigin::CreateFromString("file:///etc/passwd");
+ scoped_refptr<SecurityOrigin> b =
+ SecurityOrigin::CreateFromString("file:///etc/hosts");
+
+ // Self-comparison
+ EXPECT_TRUE(a->IsSameOriginDomainWith(a.get()));
+ EXPECT_TRUE(b->IsSameOriginDomainWith(b.get()));
+
+ // block_local_access_from_local_origin_ defaults to `false`:
+ EXPECT_TRUE(a->IsSameOriginDomainWith(b.get()));
+ EXPECT_TRUE(b->IsSameOriginDomainWith(a.get()));
+
+ // DeriveNewOpaqueOrigin
+ EXPECT_FALSE(a->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(a.get()));
+ EXPECT_FALSE(b->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(a.get()));
+ EXPECT_FALSE(a->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(b.get()));
+ EXPECT_FALSE(b->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(b.get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(a->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(a->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(a->IsSameOriginDomainWith(b->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(b->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(a->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(
+ a->DeriveNewOpaqueOrigin().get()));
+ EXPECT_FALSE(b->DeriveNewOpaqueOrigin()->IsSameOriginDomainWith(
+ b->DeriveNewOpaqueOrigin().get()));
+
+ // Set block_local_access_from_local_origin_ to `true`:
+ a->BlockLocalAccessFromLocalOrigin();
+ EXPECT_FALSE(a->IsSameOriginDomainWith(b.get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(a.get()));
+
+ // Self-comparison should still be true.
+ EXPECT_TRUE(a->IsSameOriginDomainWith(a.get()));
+ EXPECT_TRUE(b->IsSameOriginDomainWith(b.get()));
+
+ // UniversalAccess does not override
+ a->GrantUniversalAccess();
+ EXPECT_FALSE(a->IsSameOriginDomainWith(b.get()));
+ EXPECT_FALSE(b->IsSameOriginDomainWith(a.get()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
index 6f93952427c..a1d26ce91c1 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
@@ -72,8 +72,7 @@ network::mojom::ReferrerPolicy ReferrerPolicyResolveDefault(
network::mojom::ReferrerPolicy referrer_policy) {
if (referrer_policy == network::mojom::ReferrerPolicy::kDefault) {
if (RuntimeEnabledFeatures::ReducedReferrerGranularityEnabled()) {
- return network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin;
+ return network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin;
} else {
return network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade;
}
@@ -160,8 +159,7 @@ Referrer SecurityPolicy::GenerateReferrer(
: origin + "/",
referrer_policy_no_default);
}
- case network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin: {
+ case network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin: {
scoped_refptr<const SecurityOrigin> referrer_origin =
SecurityOrigin::Create(referrer_url);
scoped_refptr<const SecurityOrigin> url_origin =
@@ -328,8 +326,7 @@ bool SecurityPolicy::ReferrerPolicyFromString(
return true;
}
if (EqualIgnoringASCIICase(policy, "strict-origin-when-cross-origin")) {
- *result = network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin;
+ *result = network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin;
return true;
}
if (EqualIgnoringASCIICase(policy, "no-referrer-when-downgrade") ||
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
index 2c6e996fef8..ecc706ea8ea 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
@@ -32,10 +32,15 @@
#include "services/network/public/mojom/cors.mojom-blink.h"
#include "services/network/public/mojom/cors_origin_pattern.mojom-blink.h"
+#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "url/url_canon.h"
+#include "url/url_util.h"
namespace blink {
@@ -97,6 +102,9 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
"blob:http://a.test/b3aae9c8-7f90-440d-8d7c-43aa20d72fde";
const char kFilesystemURL[] = "filesystem:http://a.test/path/t/file.html";
+ bool reduced_granularity =
+ RuntimeEnabledFeatures::ReducedReferrerGranularityEnabled();
+
TestCase inputs[] = {
// HTTP -> HTTP: Same Origin
{network::mojom::ReferrerPolicy::kAlways, kInsecureURLA, kInsecureURLA,
@@ -115,15 +123,14 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
kInsecureURLA, kInsecureURLA},
{network::mojom::ReferrerPolicy::kStrictOrigin, kInsecureURLA,
kInsecureURLA, kInsecureOriginA},
- {network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+ {network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
kInsecureURLA, kInsecureURLA, kInsecureURLA},
// HTTP -> HTTP: Cross Origin
{network::mojom::ReferrerPolicy::kAlways, kInsecureURLA, kInsecureURLB,
kInsecureURLA},
{network::mojom::ReferrerPolicy::kDefault, kInsecureURLA, kInsecureURLB,
- kInsecureURLA},
+ reduced_granularity ? kInsecureOriginA : kInsecureURLA},
{network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade, kInsecureURLA,
kInsecureURLB, kInsecureURLA},
{network::mojom::ReferrerPolicy::kNever, kInsecureURLA, kInsecureURLB,
@@ -136,8 +143,7 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
kInsecureURLB, nullptr},
{network::mojom::ReferrerPolicy::kStrictOrigin, kInsecureURLA,
kInsecureURLB, kInsecureOriginA},
- {network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+ {network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
kInsecureURLA, kInsecureURLB, kInsecureOriginA},
// HTTPS -> HTTPS: Same Origin
@@ -157,15 +163,14 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
kSecureURLA},
{network::mojom::ReferrerPolicy::kStrictOrigin, kSecureURLA, kSecureURLA,
kSecureOriginA},
- {network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+ {network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
kSecureURLA, kSecureURLA, kSecureURLA},
// HTTPS -> HTTPS: Cross Origin
{network::mojom::ReferrerPolicy::kAlways, kSecureURLA, kSecureURLB,
kSecureURLA},
{network::mojom::ReferrerPolicy::kDefault, kSecureURLA, kSecureURLB,
- kSecureURLA},
+ reduced_granularity ? kSecureOriginA : kSecureURLA},
{network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade, kSecureURLA,
kSecureURLB, kSecureURLA},
{network::mojom::ReferrerPolicy::kNever, kSecureURLA, kSecureURLB,
@@ -178,15 +183,14 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
nullptr},
{network::mojom::ReferrerPolicy::kStrictOrigin, kSecureURLA, kSecureURLB,
kSecureOriginA},
- {network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+ {network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
kSecureURLA, kSecureURLB, kSecureOriginA},
// HTTP -> HTTPS
{network::mojom::ReferrerPolicy::kAlways, kInsecureURLA, kSecureURLB,
kInsecureURLA},
{network::mojom::ReferrerPolicy::kDefault, kInsecureURLA, kSecureURLB,
- kInsecureURLA},
+ reduced_granularity ? kInsecureOriginA : kInsecureURLA},
{network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade, kInsecureURLA,
kSecureURLB, kInsecureURLA},
{network::mojom::ReferrerPolicy::kNever, kInsecureURLA, kSecureURLB,
@@ -199,8 +203,7 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
nullptr},
{network::mojom::ReferrerPolicy::kStrictOrigin, kInsecureURLA,
kSecureURLB, kInsecureOriginA},
- {network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+ {network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
kInsecureURLA, kSecureURLB, kInsecureOriginA},
// HTTPS -> HTTP
@@ -220,8 +223,7 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
nullptr},
{network::mojom::ReferrerPolicy::kStrictOrigin, kSecureURLA,
kInsecureURLB, nullptr},
- {network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+ {network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
kSecureURLA, kInsecureURLB, nullptr},
// blob and filesystem URL handling
@@ -250,10 +252,18 @@ TEST(SecurityPolicyTest, GenerateReferrer) {
<< "' should have been empty: was '" << result.referrer.Utf8()
<< "'.";
}
- EXPECT_EQ(test.policy == network::mojom::ReferrerPolicy::kDefault
- ? network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade
- : test.policy,
- result.referrer_policy);
+
+ network::mojom::ReferrerPolicy expected_policy = test.policy;
+ if (expected_policy == network::mojom::ReferrerPolicy::kDefault) {
+ if (RuntimeEnabledFeatures::ReducedReferrerGranularityEnabled()) {
+ expected_policy =
+ network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin;
+ } else {
+ expected_policy =
+ network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade;
+ }
+ }
+ EXPECT_EQ(expected_policy, result.referrer_policy);
}
}
@@ -550,4 +560,47 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedPriority) {
https_chromium_origin(), https_sub_example_origin()));
}
+// Test that referrers for custom hierarchical (standard) schemes are correctly
+// handled by the new policy. (For instance, this covers android-app://.)
+TEST(SecurityPolicyTest, ReferrerForCustomScheme) {
+ url::ScopedSchemeRegistryForTests scoped_registry;
+ const char kCustomStandardScheme[] = "my-new-scheme";
+ url::AddStandardScheme(kCustomStandardScheme, url::SCHEME_WITH_HOST);
+ SchemeRegistry::RegisterURLSchemeAsAllowedForReferrer(kCustomStandardScheme);
+
+ String kFullReferrer = "my-new-scheme://com.foo.me/this-should-be-truncated";
+ String kTruncatedReferrer = "my-new-scheme://com.foo.me/";
+
+ bool initially_enabled =
+ RuntimeEnabledFeatures::ReducedReferrerGranularityEnabled();
+
+ {
+ // With the feature off, the old default policy of
+ // no-referrer-when-downgrade should preserve the entire URL.
+ RuntimeEnabledFeatures::SetReducedReferrerGranularityEnabled(false);
+
+ EXPECT_EQ(SecurityPolicy::GenerateReferrer(
+ network::mojom::ReferrerPolicy::kDefault,
+ KURL("https://www.example.com/"), kFullReferrer)
+ .referrer,
+ kFullReferrer);
+ }
+
+ {
+ // With the feature on, the new default policy of
+ // strict-origin-when-cross-origin should truncate the referrer.
+ RuntimeEnabledFeatures::SetReducedReferrerGranularityEnabled(true);
+
+ ASSERT_TRUE(RuntimeEnabledFeatures::ReducedReferrerGranularityEnabled());
+ EXPECT_EQ(SecurityPolicy::GenerateReferrer(
+ network::mojom::ReferrerPolicy::kDefault,
+ KURL("https://www.example.com/"), kFullReferrer)
+ .referrer,
+ kTruncatedReferrer);
+ }
+
+ RuntimeEnabledFeatures::SetReducedReferrerGranularityEnabled(
+ initially_enabled);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h b/chromium/third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h
deleted file mode 100644
index 363658cbca8..00000000000
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_SECURITY_VIOLATION_REPORTING_POLICY_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_SECURITY_VIOLATION_REPORTING_POLICY_H_
-
-namespace blink {
-
-enum class SecurityViolationReportingPolicy {
- kSuppressReporting,
- kReport,
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_SECURITY_VIOLATION_REPORTING_POLICY_H_
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
index 0fc04e446e0..7a775eb7467 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
@@ -4,9 +4,14 @@
#include "third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h"
+#include <string>
+#include <utility>
+
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "media/base/audio_bus.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
namespace blink {
@@ -14,19 +19,26 @@ namespace {
// Used as an identifier for the down-casters.
void* const kPeerConnectionRemoteTrackIdentifier =
const_cast<void**>(&kPeerConnectionRemoteTrackIdentifier);
+
+void SendLogMessage(const std::string& message) {
+ blink::WebRtcLogMessage("PCRAS::" + message);
+}
+
} // namespace
PeerConnectionRemoteAudioTrack::PeerConnectionRemoteAudioTrack(
scoped_refptr<webrtc::AudioTrackInterface> track_interface)
: MediaStreamAudioTrack(false /* is_local_track */),
track_interface_(std::move(track_interface)) {
- DVLOG(1)
- << "PeerConnectionRemoteAudioTrack::PeerConnectionRemoteAudioTrack()";
+ blink::WebRtcLogMessage(
+ base::StringPrintf("PCRAT::PeerConnectionRemoteAudioTrack({id=%s})",
+ track_interface_->id().c_str()));
}
PeerConnectionRemoteAudioTrack::~PeerConnectionRemoteAudioTrack() {
- DVLOG(1)
- << "PeerConnectionRemoteAudioTrack::~PeerConnectionRemoteAudioTrack()";
+ blink::WebRtcLogMessage(
+ base::StringPrintf("PCRAT::~PeerConnectionRemoteAudioTrack([id=%s])",
+ track_interface_->id().c_str()));
// Ensure the track is stopped.
MediaStreamAudioTrack::Stop();
}
@@ -42,6 +54,9 @@ PeerConnectionRemoteAudioTrack* PeerConnectionRemoteAudioTrack::From(
void PeerConnectionRemoteAudioTrack::SetEnabled(bool enabled) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "PCRAT::SetEnabled([id=%s] {enabled=%s})", track_interface_->id().c_str(),
+ (enabled ? "true" : "false")));
// This affects the shared state of the source for whether or not it's a part
// of the mixed audio that's rendered for remote tracks from WebRTC.
@@ -67,13 +82,13 @@ PeerConnectionRemoteAudioSource::PeerConnectionRemoteAudioSource(
track_interface_(std::move(track_interface)),
is_sink_of_peer_connection_(false) {
DCHECK(track_interface_);
- DVLOG(1)
- << "PeerConnectionRemoteAudioSource::PeerConnectionRemoteAudioSource()";
+ SendLogMessage(base::StringPrintf("PeerConnectionRemoteAudioSource([id=%s])",
+ track_interface_->id().c_str()));
}
PeerConnectionRemoteAudioSource::~PeerConnectionRemoteAudioSource() {
- DVLOG(1)
- << "PeerConnectionRemoteAudioSource::~PeerConnectionRemoteAudioSource()";
+ SendLogMessage(base::StringPrintf("~PeerConnectionRemoteAudioSource([id=%s])",
+ track_interface_->id().c_str()));
EnsureSourceIsStopped();
}
@@ -88,8 +103,8 @@ bool PeerConnectionRemoteAudioSource::EnsureSourceIsStarted() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (is_sink_of_peer_connection_)
return true;
- VLOG(1) << "Starting PeerConnection remote audio source with id="
- << track_interface_->id();
+ SendLogMessage(base::StringPrintf("EnsureSourceIsStarted([id=%s])",
+ track_interface_->id().c_str()));
track_interface_->AddSink(this);
is_sink_of_peer_connection_ = true;
return true;
@@ -98,10 +113,10 @@ bool PeerConnectionRemoteAudioSource::EnsureSourceIsStarted() {
void PeerConnectionRemoteAudioSource::EnsureSourceIsStopped() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (is_sink_of_peer_connection_) {
+ SendLogMessage(base::StringPrintf("EnsureSourceIsStopped([id=%s])",
+ track_interface_->id().c_str()));
track_interface_->RemoveSink(this);
is_sink_of_peer_connection_ = false;
- VLOG(1) << "Stopped PeerConnection remote audio source with id="
- << track_interface_->id();
}
}
@@ -149,7 +164,8 @@ void PeerConnectionRemoteAudioSource::OnData(const void* audio_data,
MediaStreamAudioSource::DeliverDataToTracks(*audio_bus_, playout_time);
#ifndef NDEBUG
- single_audio_thread_guard_.Release();
+ if (is_only_thread_here)
+ single_audio_thread_guard_.Release();
#endif
}
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h
index 46305d1b6b4..b831df797b2 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h
@@ -9,8 +9,8 @@
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
-#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/media_stream_interface.h"
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h
index 8ef336fe2e4..ac942e2642a 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_source.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_WEBRTC_SOURCE_H_
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace base {
class UnguessableToken;
@@ -39,7 +40,7 @@ class PLATFORM_EXPORT WebRtcAudioRendererSource {
virtual void AudioRendererThreadStopped() = 0;
// Callback to notify the client of the output device the renderer is using.
- virtual void SetOutputDeviceForAec(const std::string& output_device_id) = 0;
+ virtual void SetOutputDeviceForAec(const String& output_device_id) = 0;
// Returns the UnguessableToken used to connect this stream to an input stream
// for echo cancellation.
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
index bda303b71c9..d73e43710f4 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
@@ -6,6 +6,9 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/webrtc/common_video/include/video_frame_buffer.h"
#include "third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
@@ -82,7 +85,8 @@ void IsValidFrame(const media::VideoFrame& frame) {
}
scoped_refptr<media::VideoFrame> ConstructI420VideoFrame(
- const media::VideoFrame& source_frame) {
+ const media::VideoFrame& source_frame,
+ blink::WebRtcVideoFrameAdapter::LogStatus log_to_webrtc) {
// NV12 is the only supported format.
DCHECK_EQ(source_frame.format(), media::PIXEL_FORMAT_NV12);
DCHECK_EQ(source_frame.storage_type(),
@@ -101,6 +105,22 @@ scoped_refptr<media::VideoFrame> ConstructI420VideoFrame(
((source_frame.visible_rect().x() / 2) * 2) +
((source_frame.visible_rect().y() / 2) * gmb->stride(1)));
+ if (log_to_webrtc ==
+ blink::WebRtcVideoFrameAdapter::LogStatus::kLogToWebRtc) {
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "VFC::WebRtcVideoFrameAdapter : ConstructI420VideoFrame "
+ "pixel_format %d "
+ "natural_size %s coded_size %s visible_rect %s "
+ "source_plane_y %p source_plane_uv %p "
+ "source_stride_y %d, source_stride_uv %d "
+ "visible_y %p visible_uv %p",
+ static_cast<int>(source_frame.format()),
+ source_frame.natural_size().ToString().c_str(),
+ source_frame.coded_size().ToString().c_str(),
+ source_frame.visible_rect().ToString().c_str(), gmb->memory(0),
+ gmb->memory(1), gmb->stride(0), gmb->stride(1), src_y, src_uv));
+ }
+
// Convert to I420 and scale to the natural size specified in |source_frame|.
scoped_refptr<media::VideoFrame> i420_frame = media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_I420, source_frame.natural_size(),
@@ -130,8 +150,9 @@ scoped_refptr<media::VideoFrame> ConstructI420VideoFrame(
namespace blink {
WebRtcVideoFrameAdapter::WebRtcVideoFrameAdapter(
- scoped_refptr<media::VideoFrame> frame)
- : frame_(std::move(frame)) {}
+ scoped_refptr<media::VideoFrame> frame,
+ LogStatus log_to_webrtc)
+ : frame_(std::move(frame)), log_to_webrtc_(log_to_webrtc) {}
WebRtcVideoFrameAdapter::~WebRtcVideoFrameAdapter() {}
@@ -157,8 +178,12 @@ rtc::scoped_refptr<webrtc::I420BufferInterface>
WebRtcVideoFrameAdapter::CreateFrameAdapter() const {
if (frame_->storage_type() ==
media::VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER) {
- auto i420_frame = ConstructI420VideoFrame(*frame_);
+ auto i420_frame = ConstructI420VideoFrame(*frame_, log_to_webrtc_);
if (!i420_frame) {
+ if (log_to_webrtc_ == LogStatus::kLogToWebRtc) {
+ blink::WebRtcLogMessage(
+ "VFC::WebRtcVideoFrameAdapter couldn't contruct I420 frame");
+ }
return new rtc::RefCountedObject<
FrameAdapter<webrtc::I420BufferInterface>>(
media::VideoFrame::CreateColorFrame(frame_->natural_size(), 0u, 0x80,
@@ -166,8 +191,10 @@ WebRtcVideoFrameAdapter::CreateFrameAdapter() const {
}
// Keep |frame_| alive until |i420_frame| is destroyed.
- i420_frame->AddDestructionObserver(base::BindOnce(
- base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(), frame_));
+ i420_frame->AddDestructionObserver(
+ ConvertToBaseOnceCallback(CrossThreadBindOnce(
+ base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(),
+ frame_)));
IsValidFrame(*i420_frame);
return new rtc::RefCountedObject<FrameAdapter<webrtc::I420BufferInterface>>(
@@ -185,7 +212,29 @@ WebRtcVideoFrameAdapter::CreateFrameAdapter() const {
}
IsValidFrame(*frame_);
+ if (log_to_webrtc_ == LogStatus::kLogToWebRtc) {
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "VFC::WebRtcVideoFrameAdapter created I420 adapter: "
+ "natural_size %s coded_size %s visible_rect %s "
+ "PlaneY %p PlaneU %p PlaneY %p StrideY %d StrideU %d StrideY %d ",
+ frame_->natural_size().ToString().c_str(),
+ frame_->coded_size().ToString().c_str(),
+ frame_->visible_rect().ToString().c_str(),
+ frame_->visible_data(media::VideoFrame::kYPlane),
+ frame_->visible_data(media::VideoFrame::kUPlane),
+ frame_->visible_data(media::VideoFrame::kVPlane),
+ frame_->stride(media::VideoFrame::kYPlane),
+ frame_->stride(media::VideoFrame::kUPlane),
+ frame_->stride(media::VideoFrame::kVPlane)));
+ }
if (media::PIXEL_FORMAT_I420A == frame_->format()) {
+ if (log_to_webrtc_ == LogStatus::kLogToWebRtc) {
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "VFC::WebRtcVideoFrameAdapter pixel format is I420A. "
+ "PlaneA %p StrideA %d",
+ frame_->visible_data(media::VideoFrame::kAPlane),
+ frame_->stride(media::VideoFrame::kAPlane)));
+ }
return new rtc::RefCountedObject<
FrameAdapterWithA<webrtc::I420ABufferInterface>>(frame_);
}
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h
index 3b674a25230..e0cb044a583 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h
@@ -12,6 +12,7 @@
#include "third_party/webrtc/api/video/video_frame_buffer.h"
namespace blink {
+
// Thin adapter from media::VideoFrame to webrtc::VideoFrameBuffer. This
// implementation is read-only and will return null if trying to get a
// non-const pointer to the pixel data. This object will be accessed from
@@ -19,7 +20,10 @@ namespace blink {
class PLATFORM_EXPORT WebRtcVideoFrameAdapter
: public webrtc::VideoFrameBuffer {
public:
- explicit WebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame);
+ enum class LogStatus { kNoLogging, kLogToWebRtc };
+
+ WebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame,
+ LogStatus log_to_webrtc);
scoped_refptr<media::VideoFrame> getMediaVideoFrame() const { return frame_; }
@@ -41,6 +45,8 @@ class PLATFORM_EXPORT WebRtcVideoFrameAdapter
mutable rtc::scoped_refptr<webrtc::I420BufferInterface> frame_adapter_;
scoped_refptr<media::VideoFrame> frame_;
+
+ const LogStatus log_to_webrtc_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc
index d65df0e8adb..f7380df85e6 100644
--- a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc
@@ -25,7 +25,8 @@ TEST(WebRtcVideoFrameAdapterTest, WidthAndHeight) {
media::VideoFrame::STORAGE_OWNED_MEMORY);
rtc::scoped_refptr<webrtc::VideoFrameBuffer> owned_memory_frame_adapter(
new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
- std::move(owned_memory_frame)));
+ std::move(owned_memory_frame),
+ WebRtcVideoFrameAdapter::LogStatus::kNoLogging));
EXPECT_EQ(owned_memory_frame_adapter->width(), kVisibleRect.width());
EXPECT_EQ(owned_memory_frame_adapter->height(), kVisibleRect.height());
@@ -35,7 +36,9 @@ TEST(WebRtcVideoFrameAdapterTest, WidthAndHeight) {
CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_adapter(
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(std::move(gmb_frame)));
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ std::move(gmb_frame),
+ WebRtcVideoFrameAdapter::LogStatus::kNoLogging));
EXPECT_EQ(gmb_frame_adapter->width(), kNaturalSize.width());
EXPECT_EQ(gmb_frame_adapter->height(), kNaturalSize.height());
}
@@ -52,7 +55,9 @@ TEST(WebRtcVideoFrameAdapterTest, ToI420DownScale) {
// The adapter should report width and height from the natural size for
// VideoFrame backed by GpuMemoryBuffer.
rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_adapter(
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(std::move(gmb_frame)));
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ std::move(gmb_frame),
+ WebRtcVideoFrameAdapter::LogStatus::kNoLogging));
EXPECT_EQ(gmb_frame_adapter->width(), kNaturalSize.width());
EXPECT_EQ(gmb_frame_adapter->height(), kNaturalSize.height());
diff --git a/chromium/third_party/blink/renderer/platform/widget/frame_widget.cc b/chromium/third_party/blink/renderer/platform/widget/frame_widget.cc
new file mode 100644
index 00000000000..2f471eeeba8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/widget/frame_widget.cc
@@ -0,0 +1,11 @@
+// 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 "third_party/blink/renderer/platform/widget/frame_widget.h"
+
+namespace blink {
+
+FrameWidget::~FrameWidget() = default;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/frame_widget.h b/chromium/third_party/blink/renderer/platform/widget/frame_widget.h
new file mode 100644
index 00000000000..fffcf36f899
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/widget/frame_widget.h
@@ -0,0 +1,81 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_FRAME_WIDGET_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_FRAME_WIDGET_H_
+
+#include "third_party/blink/public/web/web_swap_result.h"
+#include "third_party/blink/public/web/web_widget_client.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace cc {
+class AnimationHost;
+class Layer;
+class PaintImage;
+} // namespace cc
+
+namespace blink {
+
+// In interface exposed within Blink from local root frames that provides
+// local-root specific things related to compositing and input.
+class PLATFORM_EXPORT FrameWidget {
+ public:
+ virtual ~FrameWidget();
+
+ // Returns the WebWidgetClient, which is implemented outside of blink.
+ virtual WebWidgetClient* Client() const = 0;
+
+ // Returns the compositors's AnimationHost for the widget.
+ virtual cc::AnimationHost* AnimationHost() const = 0;
+
+ // Set the browser's behavior when overscroll happens, e.g. whether to glow
+ // or navigate.
+ virtual void SetOverscrollBehavior(
+ const cc::OverscrollBehavior& overscroll_behavior) = 0;
+
+ // Posts a task with the given delay, then calls ScheduleAnimation() on the
+ // Client().
+ virtual void RequestAnimationAfterDelay(const base::TimeDelta&) = 0;
+
+ // Sets the root layer. The |layer| can be null when detaching the root layer.
+ virtual void SetRootLayer(scoped_refptr<cc::Layer> layer) = 0;
+
+ // Used to update the active selection bounds. Pass a default-constructed
+ // LayerSelection to clear it.
+ virtual void RegisterSelection(cc::LayerSelection selection) = 0;
+
+ // Image decode functionality.
+ virtual void RequestDecode(const cc::PaintImage&,
+ base::OnceCallback<void(bool)>) = 0;
+
+ // Forwards to WebFrameWidget::NotifySwapAndPresentationTime().
+ // The |callback| will be fired when the corresponding renderer frame is
+ // submitted (still called "swapped") to the display compositor (either with
+ // DidSwap or DidNotSwap).
+ virtual void NotifySwapAndPresentationTimeInBlink(
+ WebReportTimeCallback swap_callback,
+ WebReportTimeCallback presentation_callback) = 0;
+
+ // Enable or disable BeginMainFrameNotExpected signals from the compositor,
+ // which are consumed by the blink scheduler.
+ virtual void RequestBeginMainFrameNotExpected(bool request) = 0;
+
+ // A stable numeric Id for the local root's compositor. For tracing/debugging
+ // purposes.
+ virtual int GetLayerTreeId() = 0;
+
+ // Set or get what event handlers exist in the document contained in the
+ // WebWidget in order to inform the compositor thread if it is able to handle
+ // an input event, or it needs to pass it to the main thread to be handled.
+ // The class is the type of input event, and for each class there is a
+ // properties defining if the compositor thread can handle the event.
+ virtual void SetEventListenerProperties(cc::EventListenerClass,
+ cc::EventListenerProperties) = 0;
+ virtual cc::EventListenerProperties EventListenerProperties(
+ cc::EventListenerClass) const = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_FRAME_WIDGET_H_
diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base.cc b/chromium/third_party/blink/renderer/platform/widget/widget_base.cc
new file mode 100644
index 00000000000..800bb29a8d5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -0,0 +1,79 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/widget/widget_base.h"
+
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
+#include "third_party/blink/renderer/platform/widget/widget_base_client.h"
+
+namespace blink {
+
+WidgetBase::WidgetBase(
+ WidgetBaseClient* client,
+ CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>
+ widget_host,
+ CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget)
+ : client_(client),
+ widget_host_(std::move(widget_host)),
+ receiver_(this, std::move(widget)) {}
+
+WidgetBase::~WidgetBase() = default;
+
+void WidgetBase::SetCompositorHosts(cc::LayerTreeHost* layer_tree_host,
+ cc::AnimationHost* animation_host) {
+ layer_tree_host_ = layer_tree_host;
+ animation_host_ = animation_host;
+}
+
+cc::LayerTreeHost* WidgetBase::LayerTreeHost() const {
+ return layer_tree_host_;
+}
+
+cc::AnimationHost* WidgetBase::AnimationHost() const {
+ return animation_host_;
+}
+
+void WidgetBase::SetCompositorVisible(bool visible) {
+ if (visible)
+ was_shown_time_ = base::TimeTicks::Now();
+ else
+ first_update_visual_state_after_hidden_ = true;
+}
+
+void WidgetBase::UpdateVisualState() {
+ // When recording main frame metrics set the lifecycle reason to
+ // kBeginMainFrame, because this is the calller of UpdateLifecycle
+ // for the main frame. Otherwise, set the reason to kTests, which is
+ // the only other reason this method is called.
+ DocumentUpdateReason lifecycle_reason =
+ ShouldRecordBeginMainFrameMetrics()
+ ? DocumentUpdateReason::kBeginMainFrame
+ : DocumentUpdateReason::kTest;
+ client_->UpdateLifecycle(WebLifecycleUpdate::kAll, lifecycle_reason);
+ client_->SetSuppressFrameRequestsWorkaroundFor704763Only(false);
+ if (first_update_visual_state_after_hidden_) {
+ client_->RecordTimeToFirstActivePaint(base::TimeTicks::Now() -
+ was_shown_time_);
+ first_update_visual_state_after_hidden_ = false;
+ }
+}
+
+void WidgetBase::WillBeginCompositorFrame() {
+ client_->SetSuppressFrameRequestsWorkaroundFor704763Only(true);
+}
+
+void WidgetBase::BeginMainFrame(base::TimeTicks frame_time) {
+ client_->DispatchRafAlignedInput(frame_time);
+ client_->BeginMainFrame(frame_time);
+}
+
+bool WidgetBase::ShouldRecordBeginMainFrameMetrics() {
+ // We record metrics only when running in multi-threaded mode, not
+ // single-thread mode for testing.
+ return Thread::CompositorThread();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base.h b/chromium/third_party/blink/renderer/platform/widget/widget_base.h
new file mode 100644
index 00000000000..3d70fae9378
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/widget/widget_base.h
@@ -0,0 +1,75 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_H_
+
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace cc {
+class AnimationHost;
+class LayerTreeHost;
+} // namespace cc
+
+namespace blink {
+class WidgetBaseClient;
+
+// This class is the foundational class for all widgets that blink creates.
+// (WebPagePopupImpl, WebFrameWidgetBase) will contain an instance of this
+// class. For simplicity purposes this class will be a member of those classes.
+// It will eventually host compositing, input and emulation. See design doc:
+// https://docs.google.com/document/d/10uBnSWBaitGsaROOYO155Wb83rjOPtrgrGTrQ_pcssY/edit?ts=5e3b26f7
+class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget {
+ public:
+ WidgetBase(
+ WidgetBaseClient* client,
+ CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>
+ widget_host,
+ CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget);
+ ~WidgetBase() override;
+
+ // Set the current compositor hosts.
+ void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*);
+
+ // Set the compositor as visible. If |visible| is true, then the compositor
+ // will request a new layer frame sink, begin producing frames from the
+ // compositor scheduler, and in turn will update the document lifecycle.
+ void SetCompositorVisible(bool visible);
+
+ // Called to update the document lifecycle, advance the state of animations
+ // and dispatch rAF.
+ void BeginMainFrame(base::TimeTicks frame_time);
+
+ // Update the visual state of the document, running the document lifecycle.
+ void UpdateVisualState();
+
+ // Called when a compositor frame will begin.
+ void WillBeginCompositorFrame();
+
+ cc::AnimationHost* AnimationHost() const;
+ cc::LayerTreeHost* LayerTreeHost() const;
+
+ // Returns if we should gather begin main frame metrics. If there is no
+ // compositor thread this returns false.
+ static bool ShouldRecordBeginMainFrameMetrics();
+
+ private:
+ // Not owned, they are owned by the RenderWidget.
+ cc::LayerTreeHost* layer_tree_host_ = nullptr;
+ cc::AnimationHost* animation_host_ = nullptr;
+ WidgetBaseClient* client_;
+ mojo::AssociatedRemote<mojom::blink::WidgetHost> widget_host_;
+ mojo::AssociatedReceiver<mojom::blink::Widget> receiver_;
+ bool first_update_visual_state_after_hidden_ = false;
+ base::TimeTicks was_shown_time_ = base::TimeTicks::Now();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_H_
diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h b/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h
new file mode 100644
index 00000000000..4d9d8036357
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/widget/widget_base_client.h
@@ -0,0 +1,41 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_CLIENT_H_
+
+#include "base/time/time.h"
+#include "third_party/blink/public/common/metrics/document_update_reason.h"
+#include "third_party/blink/public/web/web_lifecycle_update.h"
+
+namespace blink {
+
+// This class is part of the foundation of all widgets. It provides
+// callbacks from the compositing infrastructure that the individual widgets
+// will need to implement.
+class WidgetBaseClient {
+ public:
+ // Dispatch any pending input. This method will called before
+ // dispatching a RequestAnimationFrame to the widget.
+ virtual void DispatchRafAlignedInput(base::TimeTicks frame_time) = 0;
+
+ // Called to update the document lifecycle, advance the state of animations
+ // and dispatch rAF.
+ virtual void BeginMainFrame(base::TimeTicks frame_time) = 0;
+
+ // Called to record the time between when the widget was marked visible
+ // until the compositor begain producing a frame.
+ virtual void RecordTimeToFirstActivePaint(base::TimeDelta duration) = 0;
+
+ // Requests that the lifecycle of the widget be updated.
+ virtual void UpdateLifecycle(WebLifecycleUpdate requested_update,
+ DocumentUpdateReason reason) = 0;
+
+ // TODO(crbug.com/704763): Remove the need for this.
+ virtual void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
index 6e9a1056bfa..4c07d2e881b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -4,6 +4,7 @@
assert(!is_ios)
+import("//build/config/compiler/compiler.gni")
import("//build/config/jumbo.gni")
import("//testing/test.gni")
import("//third_party/blink/renderer/config.gni")
@@ -42,6 +43,7 @@ jumbo_component("wtf") {
"allocator/partitions.h",
"assertions.cc",
"assertions.h",
+ "bit_field.h",
"bloom_filter.h",
"casting.h",
"conditional_destructor.h",
@@ -74,6 +76,7 @@ jumbo_component("wtf") {
"leak_annotations.h",
"linked_hash_set.h",
"list_hash_set.h",
+ "lru_cache.h",
"math_extras.h",
"pod_arena.h",
"pod_free_list_arena.h",
@@ -174,6 +177,7 @@ jumbo_component("wtf") {
"uuid.cc",
"uuid.h",
"vector.h",
+ "vector_backed_linked_list.h",
"vector_traits.h",
"wtf.cc",
"wtf.h",
@@ -235,14 +239,17 @@ jumbo_component("wtf") {
sources -= [ "text/atomic_string_cf.cc" ]
}
+ if (!is_debug && !optimize_for_size) {
+ configs -= [ "//build/config/compiler:default_optimization" ]
+ configs += [ "//build/config/compiler:optimize_max" ]
+ }
+
configs -= [ "//build/config/compiler:default_symbols" ]
configs += blink_symbols_config
}
test("wtf_unittests") {
- deps = [
- ":wtf_unittests_sources",
- ]
+ deps = [ ":wtf_unittests_sources" ]
}
jumbo_source_set("wtf_unittests_sources") {
@@ -251,9 +258,11 @@ jumbo_source_set("wtf_unittests_sources") {
testonly = true
sources = [
+ "allocator/atomic_operations_test.cc",
"allocator/partitions_test.cc",
"ascii_ctype_test.cc",
"assertions_test.cc",
+ "bit_field_test.cc",
"cross_thread_functional_test.cc",
"decimal_test.cc",
"deque_test.cc",
@@ -262,7 +271,9 @@ jumbo_source_set("wtf_unittests_sources") {
"functional_test.cc",
"hash_map_test.cc",
"hash_set_test.cc",
+ "linked_hash_set_test.cc",
"list_hash_set_test.cc",
+ "lru_cache_test.cc",
"math_extras_test.cc",
"pod_arena_test.cc",
"pod_arena_test_helpers.h",
@@ -294,6 +305,7 @@ jumbo_source_set("wtf_unittests_sources") {
"tree_node_test.cc",
"type_traits_test.cc",
"uuid_test.cc",
+ "vector_backed_linked_list_test.cc",
"vector_test.cc",
]
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.cc b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.cc
index b69702742d8..11349c5e44f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.cc
@@ -18,3 +18,57 @@ static_assert(WTF::IsStackAllocatedType<StackAllocatedType>::value,
"Failed to detect STACK_ALLOCATED macro.");
} // namespace
+
+namespace WTF {
+
+void AtomicReadMemcpy(void* to, const void* from, size_t bytes) {
+ // Check alignment of |to| and |from|
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ size_t* sizet_to = reinterpret_cast<size_t*>(to);
+ const size_t* sizet_from = reinterpret_cast<const size_t*>(from);
+ for (; bytes > sizeof(size_t);
+ bytes -= sizeof(size_t), ++sizet_to, ++sizet_from) {
+ *sizet_to = AsAtomicPtr(sizet_from)->load(std::memory_order_relaxed);
+ }
+ uint8_t* uint8t_to = reinterpret_cast<uint8_t*>(sizet_to);
+ const uint8_t* uint8t_from = reinterpret_cast<const uint8_t*>(sizet_from);
+ for (; bytes > 0; bytes -= sizeof(uint8_t), ++uint8t_to, ++uint8t_from) {
+ *uint8t_to = AsAtomicPtr(uint8t_from)->load(std::memory_order_relaxed);
+ }
+ DCHECK_EQ(0u, bytes);
+}
+
+void AtomicWriteMemcpy(void* to, const void* from, size_t bytes) {
+ // Check alignment of |to| and |from|
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ size_t* sizet_to = reinterpret_cast<size_t*>(to);
+ const size_t* sizet_from = reinterpret_cast<const size_t*>(from);
+ for (; bytes > sizeof(size_t);
+ bytes -= sizeof(size_t), ++sizet_to, ++sizet_from) {
+ AsAtomicPtr(sizet_to)->store(*sizet_from, std::memory_order_relaxed);
+ }
+ uint8_t* uint8t_to = reinterpret_cast<uint8_t*>(sizet_to);
+ const uint8_t* uint8t_from = reinterpret_cast<const uint8_t*>(sizet_from);
+ for (; bytes > 0; bytes -= sizeof(uint8_t), ++uint8t_to, ++uint8t_from) {
+ AsAtomicPtr(uint8t_to)->store(*uint8t_from, std::memory_order_relaxed);
+ }
+ DCHECK_EQ(0u, bytes);
+}
+
+void AtomicMemzero(void* buf, size_t bytes) {
+ // Check alignment of |buf|
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(buf) & (sizeof(size_t) - 1));
+ size_t* sizet_buf = reinterpret_cast<size_t*>(buf);
+ for (; bytes > sizeof(size_t); bytes -= sizeof(size_t), ++sizet_buf) {
+ AsAtomicPtr(sizet_buf)->store(0, std::memory_order_relaxed);
+ }
+ uint8_t* uint8t_buf = reinterpret_cast<uint8_t*>(sizet_buf);
+ for (; bytes > 0; bytes -= sizeof(uint8_t), ++uint8t_buf) {
+ AsAtomicPtr(uint8t_buf)->store(0, std::memory_order_relaxed);
+ }
+ DCHECK_EQ(0u, bytes);
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
index af536529a6d..66fc9943d46 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
@@ -5,6 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALLOCATOR_ALLOCATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALLOCATOR_ALLOCATOR_H_
+#include <atomic>
+
+#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
@@ -147,6 +150,205 @@ class __thisIsHereToForceASemicolonAfterThisMacro;
#define USING_FAST_MALLOC_WITH_TYPE_NAME(type) \
USING_FAST_MALLOC_INTERNAL(type, #type)
+// TOOD(omerkatz): replace these casts with std::atomic_ref (C++20) once it
+// becomes available
+template <typename T>
+ALWAYS_INLINE std::atomic<T>* AsAtomicPtr(T* t) {
+ return reinterpret_cast<std::atomic<T>*>(t);
+}
+template <typename T>
+ALWAYS_INLINE const std::atomic<T>* AsAtomicPtr(const T* t) {
+ return reinterpret_cast<const std::atomic<T>*>(t);
+}
+
+// Copies |bytes| bytes from |from| to |to| using atomic reads. Assumes |to|
+// and |from| are size_t-aligned and point to buffers of size |bytes|. Note
+// that atomicity is guaranteed only per word, not for the entire |bytes|
+// bytes as a whole. When copying arrays of elements, If |to| and |from|
+// are overlapping, should move the elements one by one.
+WTF_EXPORT void AtomicReadMemcpy(void* to, const void* from, size_t bytes);
+template <size_t bytes>
+ALWAYS_INLINE void AtomicReadMemcpy(void* to, const void* from) {
+ static_assert(bytes > 0, "Number of copied bytes should be greater than 0");
+ AtomicReadMemcpy(to, from, bytes);
+}
+
+// AtomicReadMemcpy specializations:
+
+#if defined(ARCH_CPU_X86_64)
+template <>
+ALWAYS_INLINE void AtomicReadMemcpy<sizeof(uint32_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(uint32_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(uint32_t) - 1));
+ *reinterpret_cast<uint32_t*>(to) =
+ AsAtomicPtr(reinterpret_cast<const uint32_t*>(from))
+ ->load(std::memory_order_relaxed);
+}
+#endif // ARCH_CPU_X86_64
+
+template <>
+ALWAYS_INLINE void AtomicReadMemcpy<sizeof(size_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ *reinterpret_cast<size_t*>(to) =
+ AsAtomicPtr(reinterpret_cast<const size_t*>(from))
+ ->load(std::memory_order_relaxed);
+}
+
+template <>
+ALWAYS_INLINE void AtomicReadMemcpy<2 * sizeof(size_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ *reinterpret_cast<size_t*>(to) =
+ AsAtomicPtr(reinterpret_cast<const size_t*>(from))
+ ->load(std::memory_order_relaxed);
+ *(reinterpret_cast<size_t*>(to) + 1) =
+ AsAtomicPtr(reinterpret_cast<const size_t*>(from) + 1)
+ ->load(std::memory_order_relaxed);
+}
+
+template <>
+ALWAYS_INLINE void AtomicReadMemcpy<3 * sizeof(size_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ *reinterpret_cast<size_t*>(to) =
+ AsAtomicPtr(reinterpret_cast<const size_t*>(from))
+ ->load(std::memory_order_relaxed);
+ *(reinterpret_cast<size_t*>(to) + 1) =
+ AsAtomicPtr(reinterpret_cast<const size_t*>(from) + 1)
+ ->load(std::memory_order_relaxed);
+ *(reinterpret_cast<size_t*>(to) + 2) =
+ AsAtomicPtr(reinterpret_cast<const size_t*>(from) + 2)
+ ->load(std::memory_order_relaxed);
+}
+
+// Copies |bytes| bytes from |from| to |to| using atomic writes. Assumes |to|
+// and |from| are size_t-aligned and point to buffers of size |bytes|. Note
+// that atomicity is guaranteed only per word, not for the entire |bytes|
+// bytes as a whole. When copying arrays of elements, If |to| and |from| are
+// overlapping, should move the elements one by one.
+WTF_EXPORT void AtomicWriteMemcpy(void* to, const void* from, size_t bytes);
+template <size_t bytes>
+ALWAYS_INLINE void AtomicWriteMemcpy(void* to, const void* from) {
+ static_assert(bytes > 0, "Number of copied bytes should be greater than 0");
+ AtomicWriteMemcpy(to, from, bytes);
+}
+
+// AtomicReadMemcpy specializations:
+
+#if defined(ARCH_CPU_X86_64)
+template <>
+ALWAYS_INLINE void AtomicWriteMemcpy<sizeof(uint32_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(uint32_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(uint32_t) - 1));
+ AsAtomicPtr(reinterpret_cast<uint32_t*>(to))
+ ->store(*reinterpret_cast<const uint32_t*>(from),
+ std::memory_order_relaxed);
+}
+#endif // ARCH_CPU_X86_64
+
+template <>
+ALWAYS_INLINE void AtomicWriteMemcpy<sizeof(size_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ AsAtomicPtr(reinterpret_cast<size_t*>(to))
+ ->store(*reinterpret_cast<const size_t*>(from),
+ std::memory_order_relaxed);
+}
+
+template <>
+ALWAYS_INLINE void AtomicWriteMemcpy<2 * sizeof(size_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ AsAtomicPtr(reinterpret_cast<size_t*>(to))
+ ->store(*reinterpret_cast<const size_t*>(from),
+ std::memory_order_relaxed);
+ AsAtomicPtr(reinterpret_cast<size_t*>(to) + 1)
+ ->store(*(reinterpret_cast<const size_t*>(from) + 1),
+ std::memory_order_relaxed);
+}
+
+template <>
+ALWAYS_INLINE void AtomicWriteMemcpy<3 * sizeof(size_t)>(void* to,
+ const void* from) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(to) & (sizeof(size_t) - 1));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(from) & (sizeof(size_t) - 1));
+ AsAtomicPtr(reinterpret_cast<size_t*>(to))
+ ->store(*reinterpret_cast<const size_t*>(from),
+ std::memory_order_relaxed);
+ AsAtomicPtr(reinterpret_cast<size_t*>(to) + 1)
+ ->store(*(reinterpret_cast<const size_t*>(from) + 1),
+ std::memory_order_relaxed);
+ AsAtomicPtr(reinterpret_cast<size_t*>(to) + 2)
+ ->store(*(reinterpret_cast<const size_t*>(from) + 2),
+ std::memory_order_relaxed);
+}
+
+// Set the first |bytes| bytes of |buf| to 0 using atomic writes. Assumes |buf|
+// is size_t-aligned and points to a buffer of size at least |bytes|. Note
+// that atomicity is guaranteed only per word, not for the entire |bytes| bytes
+// as a whole.
+WTF_EXPORT void AtomicMemzero(void* buf, size_t bytes);
+
+template <size_t bytes>
+ALWAYS_INLINE void AtomicMemzero(void* buf) {
+ static_assert(bytes > 0, "Number of copied bytes should be greater than 0");
+ AtomicMemzero(buf, bytes);
+}
+
+// AtomicReadMemcpy specializations:
+
+#if defined(ARCH_CPU_X86_64)
+template <>
+ALWAYS_INLINE void AtomicMemzero<sizeof(uint32_t)>(void* buf) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(buf) & (sizeof(uint32_t) - 1));
+ AsAtomicPtr(reinterpret_cast<uint32_t*>(buf))
+ ->store(0, std::memory_order_relaxed);
+}
+#endif // ARCH_CPU_X86_64
+
+template <>
+ALWAYS_INLINE void AtomicMemzero<sizeof(size_t)>(void* buf) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(buf) & (sizeof(size_t) - 1));
+ AsAtomicPtr(reinterpret_cast<size_t*>(buf))
+ ->store(0, std::memory_order_relaxed);
+}
+
+template <>
+ALWAYS_INLINE void AtomicMemzero<2 * sizeof(size_t)>(void* buf) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(buf) & (sizeof(size_t) - 1));
+ AsAtomicPtr(reinterpret_cast<size_t*>(buf))
+ ->store(0, std::memory_order_relaxed);
+ AsAtomicPtr(reinterpret_cast<size_t*>(buf) + 1)
+ ->store(0, std::memory_order_relaxed);
+}
+
+template <>
+ALWAYS_INLINE void AtomicMemzero<3 * sizeof(size_t)>(void* buf) {
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(buf) & (sizeof(size_t) - 1));
+ AsAtomicPtr(reinterpret_cast<size_t*>(buf))
+ ->store(0, std::memory_order_relaxed);
+ AsAtomicPtr(reinterpret_cast<size_t*>(buf) + 1)
+ ->store(0, std::memory_order_relaxed);
+ AsAtomicPtr(reinterpret_cast<size_t*>(buf) + 2)
+ ->store(0, std::memory_order_relaxed);
+}
+
+// Swaps values using atomic writes.
+template <typename T>
+ALWAYS_INLINE void AtomicWriteSwap(T& lhs, T& rhs) {
+ T tmp_val = rhs;
+ AsAtomicPtr(&rhs)->store(lhs, std::memory_order_relaxed);
+ AsAtomicPtr(&lhs)->store(tmp_val, std::memory_order_relaxed);
+}
+
} // namespace WTF
// This version of placement new omits a 0 check.
@@ -156,20 +358,4 @@ inline void* operator new(size_t, NotNullTag, void* location) {
return location;
}
-#if defined(__clang__) && __has_attribute(uninitialized)
-// Attribute "uninitialized" disables -ftrivial-auto-var-init=pattern for
-// the specified variable.
-//
-// -ftrivial-auto-var-init is security risk mitigation feature, so attribute
-// should not be used "just in case", but only to fix real performance
-// bottlenecks when other approaches do not work. In general the compiler is
-// quite effective at eliminating unneeded initializations introduced by the
-// flag, e.g. when they are followed by actual initialization by a program.
-// However if compiler optimization fails and code refactoring is hard, the
-// attribute can be used as a workaround.
-#define STACK_UNINITIALIZED __attribute__((uninitialized))
-#else
-#define STACK_UNINITIALIZED
-#endif
-
#endif /* WTF_Allocator_h */
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/atomic_operations_test.cc b/chromium/third_party/blink/renderer/platform/wtf/allocator/atomic_operations_test.cc
new file mode 100644
index 00000000000..819b3bff584
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/atomic_operations_test.cc
@@ -0,0 +1,139 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace WTF {
+
+class AtomicOperationsTest : public ::testing::Test {};
+
+template <size_t buffer_size, typename CopyMethod>
+void TestCopyImpl(CopyMethod copy) {
+ alignas(sizeof(size_t)) unsigned char src[buffer_size];
+ for (size_t i = 0; i < buffer_size; ++i)
+ src[i] = static_cast<char>(i + 1);
+ // Allocating extra memory before and after the buffer to make sure the
+ // atomic memcpy doesn't exceed the buffer in any direction.
+ alignas(sizeof(size_t)) unsigned char tgt[buffer_size + (2 * sizeof(size_t))];
+ memset(tgt, 0, buffer_size + (2 * sizeof(size_t)));
+ copy(tgt + sizeof(size_t), src);
+ // Check nothing before the buffer was changed
+ EXPECT_EQ(0u, *reinterpret_cast<size_t*>(&tgt[0]));
+ // Check buffer was copied correctly
+ EXPECT_TRUE(!memcmp(src, tgt + sizeof(size_t), buffer_size));
+ // Check nothing after the buffer was changed
+ EXPECT_EQ(0u, *reinterpret_cast<size_t*>(&tgt[sizeof(size_t) + buffer_size]));
+}
+
+// Tests for AtomicReadMemcpy
+template <size_t buffer_size>
+void TestAtomicReadMemcpy() {
+ TestCopyImpl<buffer_size>(AtomicReadMemcpy<buffer_size>);
+}
+
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_UINT8T) {
+ TestAtomicReadMemcpy<sizeof(uint8_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_UINT16T) {
+ TestAtomicReadMemcpy<sizeof(uint16_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_UINT32T) {
+ TestAtomicReadMemcpy<sizeof(uint32_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_UINT64T) {
+ TestAtomicReadMemcpy<sizeof(uint64_t)>();
+}
+
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_17Bytes) {
+ TestAtomicReadMemcpy<17>();
+}
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_34Bytes) {
+ TestAtomicReadMemcpy<34>();
+}
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_68Bytes) {
+ TestAtomicReadMemcpy<68>();
+}
+TEST_F(AtomicOperationsTest, AtomicReadMemcpy_127Bytes) {
+ TestAtomicReadMemcpy<127>();
+}
+
+// Tests for AtomicWriteMemcpy
+template <size_t buffer_size>
+void TestAtomicWriteMemcpy() {
+ TestCopyImpl<buffer_size>(AtomicWriteMemcpy<buffer_size>);
+}
+
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_UINT8T) {
+ TestAtomicWriteMemcpy<sizeof(uint8_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_UINT16T) {
+ TestAtomicWriteMemcpy<sizeof(uint16_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_UINT32T) {
+ TestAtomicWriteMemcpy<sizeof(uint32_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_UINT64T) {
+ TestAtomicWriteMemcpy<sizeof(uint64_t)>();
+}
+
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_17Bytes) {
+ TestAtomicWriteMemcpy<17>();
+}
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_34Bytes) {
+ TestAtomicWriteMemcpy<34>();
+}
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_68Bytes) {
+ TestAtomicWriteMemcpy<68>();
+}
+TEST_F(AtomicOperationsTest, AtomicWriteMemcpy_127Bytes) {
+ TestAtomicWriteMemcpy<127>();
+}
+
+// Tests for AtomicMemzero
+template <size_t buffer_size>
+void TestAtomicMemzero() {
+ // Allocating extra memory before and after the buffer to make sure the
+ // AtomicMemzero doesn't exceed the buffer in any direction.
+ alignas(sizeof(size_t)) unsigned char buf[buffer_size + (2 * sizeof(size_t))];
+ memset(buf, ~uint8_t{0}, buffer_size + (2 * sizeof(size_t)));
+ AtomicMemzero<buffer_size>(buf + sizeof(size_t));
+ // Check nothing before the buffer was changed
+ EXPECT_EQ(~size_t{0}, *reinterpret_cast<size_t*>(&buf[0]));
+ // Check buffer was copied correctly
+ static const unsigned char for_comparison[buffer_size] = {0};
+ EXPECT_TRUE(!memcmp(buf + sizeof(size_t), for_comparison, buffer_size));
+ // Check nothing after the buffer was changed
+ EXPECT_EQ(~size_t{0},
+ *reinterpret_cast<size_t*>(&buf[sizeof(size_t) + buffer_size]));
+}
+
+TEST_F(AtomicOperationsTest, AtomicMemzero_UINT8T) {
+ TestAtomicMemzero<sizeof(uint8_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicMemzero_UINT16T) {
+ TestAtomicMemzero<sizeof(uint16_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicMemzero_UINT32T) {
+ TestAtomicMemzero<sizeof(uint32_t)>();
+}
+TEST_F(AtomicOperationsTest, AtomicMemzero_UINT64T) {
+ TestAtomicMemzero<sizeof(uint64_t)>();
+}
+
+TEST_F(AtomicOperationsTest, AtomicMemzero_17Bytes) {
+ TestAtomicMemzero<17>();
+}
+TEST_F(AtomicOperationsTest, AtomicMemzero_34Bytes) {
+ TestAtomicMemzero<34>();
+}
+TEST_F(AtomicOperationsTest, AtomicMemzero_68Bytes) {
+ TestAtomicMemzero<68>();
+}
+TEST_F(AtomicOperationsTest, AtomicMemzero_127Bytes) {
+ TestAtomicMemzero<127>();
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h b/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
index 143b0584ce5..e1bc3a994e4 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
@@ -76,14 +76,16 @@ class WTF_EXPORT PartitionAllocator {
Free(ptr); // Not the system free, the one from this class.
}
- static void TraceMarkedBackingStore(void*) {}
- static void BackingWriteBarrier(void*) {}
- template <typename>
- static void BackingWriteBarrierForHashTable(void*) {}
+ static void TraceBackingStoreIfMarked(const void*) {}
+ template <typename T>
+ static void BackingWriteBarrier(T**) {}
+ template <typename, typename T>
+ static void BackingWriteBarrierForHashTable(T**) {}
static bool IsAllocationAllowed() { return true; }
static bool IsObjectResurrectionForbidden() { return false; }
static bool IsSweepForbidden() { return false; }
+ static bool IsIncrementalMarking() { return false; }
static void EnterGCForbiddenScope() {}
static void LeaveGCForbiddenScope() {}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
index cde57169e59..abb17cad6d9 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
@@ -36,7 +36,6 @@
#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/allocator/partition_allocator/partition_root_base.h"
#include "base/debug/alias.h"
-#include "base/lazy_instance.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -45,63 +44,54 @@ namespace WTF {
const char* const Partitions::kAllocatedObjectPoolName =
"partition_alloc/allocated_objects";
-static base::LazyInstance<base::subtle::SpinLock>::Leaky initialization_lock_ =
- LAZY_INSTANCE_INITIALIZER;
bool Partitions::initialized_ = false;
-// These statics are inlined, so cannot be LazyInstances. We create
-// LazyInstances below, and then set the pointers correctly in Initialize().
+// These statics are inlined, so cannot be LazyInstances. We create the values,
+// and then set the pointers correctly in Initialize().
base::PartitionRootGeneric* Partitions::fast_malloc_root_ = nullptr;
base::PartitionRootGeneric* Partitions::array_buffer_root_ = nullptr;
base::PartitionRootGeneric* Partitions::buffer_root_ = nullptr;
base::PartitionRoot* Partitions::layout_root_ = nullptr;
-static base::LazyInstance<base::PartitionAllocatorGeneric>::Leaky
- lazy_fast_malloc = LAZY_INSTANCE_INITIALIZER;
-static base::LazyInstance<base::PartitionAllocatorGeneric>::Leaky
- lazy_array_buffer = LAZY_INSTANCE_INITIALIZER;
-static base::LazyInstance<base::PartitionAllocatorGeneric>::Leaky lazy_buffer =
- LAZY_INSTANCE_INITIALIZER;
-static base::LazyInstance<base::SizeSpecificPartitionAllocator<1024>>::Leaky
- lazy_layout = LAZY_INSTANCE_INITIALIZER;
-
+// static
void Partitions::Initialize() {
- base::subtle::SpinLock::Guard guard(initialization_lock_.Get());
-
- if (!initialized_) {
- base::PartitionAllocatorGeneric* fast_malloc_allocator =
- lazy_fast_malloc.Pointer();
- base::PartitionAllocatorGeneric* array_buffer_allocator =
- lazy_array_buffer.Pointer();
- base::PartitionAllocatorGeneric* buffer_allocator = lazy_buffer.Pointer();
- base::SizeSpecificPartitionAllocator<1024>* layout_allocator =
- lazy_layout.Pointer();
-
- base::PartitionAllocGlobalInit(&Partitions::HandleOutOfMemory);
- fast_malloc_allocator->init();
- array_buffer_allocator->init();
- buffer_allocator->init();
- layout_allocator->init();
-
- fast_malloc_root_ = fast_malloc_allocator->root();
- array_buffer_root_ = array_buffer_allocator->root();
- buffer_root_ = buffer_allocator->root();
- layout_root_ = layout_allocator->root();
-
- initialized_ = true;
- }
+ static bool initialized = InitializeOnce();
+ DCHECK(initialized);
+}
+
+// static
+bool Partitions::InitializeOnce() {
+ static base::PartitionAllocatorGeneric fast_malloc_allocator{};
+ static base::PartitionAllocatorGeneric array_buffer_allocator{};
+ static base::PartitionAllocatorGeneric buffer_allocator{};
+ static base::SizeSpecificPartitionAllocator<1024> layout_allocator{};
+
+ base::PartitionAllocGlobalInit(&Partitions::HandleOutOfMemory);
+
+ fast_malloc_allocator.init();
+ array_buffer_allocator.init();
+ buffer_allocator.init();
+ layout_allocator.init();
+
+ fast_malloc_root_ = fast_malloc_allocator.root();
+ array_buffer_root_ = array_buffer_allocator.root();
+ buffer_root_ = buffer_allocator.root();
+ layout_root_ = layout_allocator.root();
+
+ initialized_ = true;
+ return initialized_;
}
// static
void Partitions::StartPeriodicReclaim(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
CHECK(IsMainThread());
- if (!initialized_)
- return;
+ DCHECK(initialized_);
base::PartitionAllocMemoryReclaimer::Instance()->Start(task_runner);
}
+// static
void Partitions::DumpMemoryStats(
bool is_light_dump,
base::PartitionStatsDumper* partition_stats_dumper) {
@@ -141,6 +131,7 @@ class LightPartitionStatsDumperImpl : public base::PartitionStatsDumper {
} // namespace
+// static
size_t Partitions::TotalSizeOfCommittedPages() {
DCHECK(initialized_);
size_t total_size = 0;
@@ -151,118 +142,128 @@ size_t Partitions::TotalSizeOfCommittedPages() {
return total_size;
}
+// static
size_t Partitions::TotalActiveBytes() {
LightPartitionStatsDumperImpl dumper;
WTF::Partitions::DumpMemoryStats(true, &dumper);
return dumper.TotalActiveBytes();
}
-static NOINLINE void PartitionsOutOfMemoryUsing2G() {
+static NOINLINE void PartitionsOutOfMemoryUsing2G(size_t size) {
size_t signature = 2UL * 1024 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing1G() {
+static NOINLINE void PartitionsOutOfMemoryUsing1G(size_t size) {
size_t signature = 1UL * 1024 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing512M() {
+static NOINLINE void PartitionsOutOfMemoryUsing512M(size_t size) {
size_t signature = 512 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing256M() {
+static NOINLINE void PartitionsOutOfMemoryUsing256M(size_t size) {
size_t signature = 256 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing128M() {
+static NOINLINE void PartitionsOutOfMemoryUsing128M(size_t size) {
size_t signature = 128 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing64M() {
+static NOINLINE void PartitionsOutOfMemoryUsing64M(size_t size) {
size_t signature = 64 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing32M() {
+static NOINLINE void PartitionsOutOfMemoryUsing32M(size_t size) {
size_t signature = 32 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsing16M() {
+static NOINLINE void PartitionsOutOfMemoryUsing16M(size_t size) {
size_t signature = 16 * 1024 * 1024;
base::debug::Alias(&signature);
- OOM_CRASH();
+ OOM_CRASH(size);
}
-static NOINLINE void PartitionsOutOfMemoryUsingLessThan16M() {
+static NOINLINE void PartitionsOutOfMemoryUsingLessThan16M(size_t size) {
size_t signature = 16 * 1024 * 1024 - 1;
base::debug::Alias(&signature);
- DLOG(FATAL) << "ParitionAlloc: out of memory with < 16M usage (error:"
+ DLOG(FATAL) << "PartitionAlloc: out of memory with < 16M usage (error:"
<< base::GetAllocPageErrorCode() << ")";
+ OOM_CRASH(size);
}
+// static
void* Partitions::BufferMalloc(size_t n, const char* type_name) {
return BufferPartition()->Alloc(n, type_name);
}
+// static
void* Partitions::BufferTryRealloc(void* p, size_t n, const char* type_name) {
return BufferPartition()->TryRealloc(p, n, type_name);
}
+// static
void Partitions::BufferFree(void* p) {
BufferPartition()->Free(p);
}
+// static
size_t Partitions::BufferActualSize(size_t n) {
return BufferPartition()->ActualSize(n);
}
+// static
void* Partitions::FastMalloc(size_t n, const char* type_name) {
return FastMallocPartition()->Alloc(n, type_name);
}
+// static
void* Partitions::FastZeroedMalloc(size_t n, const char* type_name) {
return FastMallocPartition()->AllocFlags(base::PartitionAllocZeroFill, n,
type_name);
}
+// static
void Partitions::FastFree(void* p) {
FastMallocPartition()->Free(p);
}
-void Partitions::HandleOutOfMemory() {
+// static
+void Partitions::HandleOutOfMemory(size_t size) {
volatile size_t total_usage = TotalSizeOfCommittedPages();
uint32_t alloc_page_error_code = base::GetAllocPageErrorCode();
base::debug::Alias(&alloc_page_error_code);
if (total_usage >= 2UL * 1024 * 1024 * 1024)
- PartitionsOutOfMemoryUsing2G();
+ PartitionsOutOfMemoryUsing2G(size);
if (total_usage >= 1UL * 1024 * 1024 * 1024)
- PartitionsOutOfMemoryUsing1G();
+ PartitionsOutOfMemoryUsing1G(size);
if (total_usage >= 512 * 1024 * 1024)
- PartitionsOutOfMemoryUsing512M();
+ PartitionsOutOfMemoryUsing512M(size);
if (total_usage >= 256 * 1024 * 1024)
- PartitionsOutOfMemoryUsing256M();
+ PartitionsOutOfMemoryUsing256M(size);
if (total_usage >= 128 * 1024 * 1024)
- PartitionsOutOfMemoryUsing128M();
+ PartitionsOutOfMemoryUsing128M(size);
if (total_usage >= 64 * 1024 * 1024)
- PartitionsOutOfMemoryUsing64M();
+ PartitionsOutOfMemoryUsing64M(size);
if (total_usage >= 32 * 1024 * 1024)
- PartitionsOutOfMemoryUsing32M();
+ PartitionsOutOfMemoryUsing32M(size);
if (total_usage >= 16 * 1024 * 1024)
- PartitionsOutOfMemoryUsing16M();
- PartitionsOutOfMemoryUsingLessThan16M();
+ PartitionsOutOfMemoryUsing16M(size);
+ PartitionsOutOfMemoryUsingLessThan16M(size);
}
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
index 48e833a2467..4dcc3564ed8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
@@ -50,6 +50,7 @@ class WTF_EXPORT Partitions {
// memory snapshots.
static const char* const kAllocatedObjectPoolName;
+ // Should be called on the thread which is or will become the main one.
static void Initialize();
static void StartPeriodicReclaim(
scoped_refptr<base::SequencedTaskRunner> task_runner);
@@ -90,7 +91,7 @@ class WTF_EXPORT Partitions {
static void* FastZeroedMalloc(size_t n, const char* type_name);
static void FastFree(void* p);
- static void HandleOutOfMemory();
+ static void HandleOutOfMemory(size_t size);
private:
ALWAYS_INLINE static base::PartitionRootGeneric* FastMallocPartition() {
@@ -98,8 +99,9 @@ class WTF_EXPORT Partitions {
return fast_malloc_root_;
}
- static bool initialized_;
+ static bool InitializeOnce();
+ static bool initialized_;
// See Allocator.md for a description of these partitions.
static base::PartitionRootGeneric* fast_malloc_root_;
static base::PartitionRootGeneric* array_buffer_root_;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/bit_field.h b/chromium/third_party/blink/renderer/platform/wtf/bit_field.h
new file mode 100644
index 00000000000..e65e183b475
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/bit_field.h
@@ -0,0 +1,153 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BIT_FIELD_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BIT_FIELD_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace WTF {
+
+enum class BitFieldValueConstness {
+ kNonConst,
+ kConst,
+};
+
+namespace internal {
+
+template <class BitFieldType>
+class BitFieldBase;
+
+// Helper class for defining values in a bit field. This helper provides
+// utilities to read, write and update the value in the bit field.
+template <class ValueType,
+ size_t offset,
+ size_t size,
+ class BitFieldType,
+ BitFieldValueConstness is_const = BitFieldValueConstness::kNonConst>
+class BitFieldValue final {
+ static_assert(std::is_fundamental<ValueType>::value,
+ "Fields in a bit field must be of a primitive type.");
+ static_assert(std::is_fundamental<BitFieldType>::value,
+ "Bit fields must be of a primitive type.");
+ static_assert(std::is_unsigned<BitFieldType>::value,
+ "Bit field must be of an unsigned type");
+ static_assert(sizeof(ValueType) <= sizeof(BitFieldType),
+ "Value in bit field cannot be bigger than the bit field");
+ static_assert(
+ offset < 8 * sizeof(BitFieldType),
+ "Field offset in bit field must be smaller than the bit field size");
+ static_assert(
+ size < 8 * sizeof(BitFieldType),
+ "Field size in bit field must be smaller than the bit field size");
+ static_assert(offset + size <= 8 * sizeof(BitFieldType),
+ "Field in bit field cannot overflow the bit field");
+ static_assert(size > 0, "Bit field fields cannot have 0 size.");
+
+ public:
+ using Type = ValueType;
+
+ template <class OtherValueType,
+ int other_size,
+ BitFieldValueConstness other_is_const =
+ BitFieldValueConstness::kNonConst>
+ using DefineNextValue = BitFieldValue<OtherValueType,
+ offset + size,
+ other_size,
+ BitFieldType,
+ other_is_const>;
+
+ // Create a bit field with the given value.
+ static constexpr BitFieldType encode(ValueType value) {
+ DCHECK(is_valid(value));
+ return static_cast<BitFieldType>(value) << offset;
+ }
+
+ // Update a bit field with the given value.
+ static constexpr BitFieldType update(BitFieldType previous, ValueType value) {
+ return (previous & ~kMask) | encode(value);
+ }
+
+ // Read the value from the bit field.
+ static constexpr ValueType decode(BitFieldType value) {
+ return static_cast<ValueType>((value & kMask) >> offset);
+ }
+
+ private:
+ static constexpr BitFieldValueConstness kIsConst = is_const;
+
+ static constexpr BitFieldType kValidationMask =
+ (BitFieldType{1} << size) - BitFieldType{1};
+ static constexpr BitFieldType kMask = (kValidationMask) << offset;
+ static_assert(kMask != 0, "Mask in which all bits are 0 is not allowed.");
+ static_assert(~kMask != 0, "Mask in which all bits are 1 is not allowed.");
+
+ // Confirm that the provided value fits into the bit field.
+ static constexpr bool is_valid(ValueType value) {
+ return (static_cast<BitFieldType>(value) & ~kValidationMask) == 0;
+ }
+
+ friend class BitFieldBase<BitFieldType>;
+};
+
+} // namespace internal
+
+// BitField intended to be used by a single thread.
+template <class BitFieldType>
+class WTF_EXPORT SingleThreadedBitField {
+ static_assert(std::is_fundamental<BitFieldType>::value,
+ "Bit fields must be of a primitive type.");
+ static_assert(std::is_unsigned<BitFieldType>::value,
+ "Bit field must be of an unsigned type");
+
+ public:
+ template <class Type,
+ int size,
+ BitFieldValueConstness is_const = BitFieldValueConstness::kNonConst>
+ using DefineFirstValue =
+ internal::BitFieldValue<Type, 0, size, BitFieldType, is_const>;
+
+ explicit SingleThreadedBitField() : SingleThreadedBitField(0) {}
+ explicit SingleThreadedBitField(BitFieldType bits) : bits_(bits) {}
+
+ template <typename Value>
+ typename Value::Type get() const {
+ return Value::decode(bits_);
+ }
+
+ template <typename Value>
+ void set(typename Value::Type value) {
+ bits_ = Value::update(bits_, value);
+ }
+
+ protected:
+ BitFieldType bits_;
+};
+
+// BitField that can be written by a single thread but read by multiple threads.
+template <class BitFieldType>
+class WTF_EXPORT ConcurrentlyReadBitField
+ : public SingleThreadedBitField<BitFieldType> {
+ using Base = SingleThreadedBitField<BitFieldType>;
+ using Base::bits_;
+
+ public:
+ explicit ConcurrentlyReadBitField() : Base(0) {}
+ explicit ConcurrentlyReadBitField(BitFieldType bits) : Base(bits) {}
+
+ template <typename Value>
+ typename Value::Type get_concurrently() const {
+ return Value::decode(AsAtomicPtr(&bits_)->load(std::memory_order_relaxed));
+ }
+
+ template <typename Value>
+ void set(typename Value::Type value) {
+ AsAtomicPtr(&bits_)->store(Value::update(bits_, value),
+ std::memory_order_relaxed);
+ }
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BIT_FIELD_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/bit_field_test.cc b/chromium/third_party/blink/renderer/platform/wtf/bit_field_test.cc
new file mode 100644
index 00000000000..795db25fbe5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/bit_field_test.cc
@@ -0,0 +1,105 @@
+// 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 "third_party/blink/renderer/platform/wtf/bit_field.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace WTF {
+
+class BitFieldTest : public ::testing::Test {};
+
+TEST_F(BitFieldTest, BitFieldDefaultCtor) {
+ using BitField = SingleThreadedBitField<uint32_t>;
+ using Value1 = BitField::DefineFirstValue<uint32_t, 31>;
+ using Value2 = Value1::DefineNextValue<uint32_t, 1>;
+
+ SingleThreadedBitField<uint32_t> bit_field;
+ EXPECT_EQ(0u, bit_field.get<Value1>());
+ EXPECT_EQ(0u, bit_field.get<Value2>());
+}
+
+TEST_F(BitFieldTest, BitFieldCtor) {
+ using BitField = SingleThreadedBitField<uint32_t>;
+ using Value1 = BitField::DefineFirstValue<uint32_t, 31>;
+ using Value2 = Value1::DefineNextValue<uint32_t, 1>;
+
+ SingleThreadedBitField<uint32_t> bit_field(0xdeadbeef);
+ EXPECT_EQ(0x5eadbeefu, bit_field.get<Value1>());
+ EXPECT_EQ(1u, bit_field.get<Value2>());
+}
+
+TEST_F(BitFieldTest, SplitBitField) {
+ using BitField = SingleThreadedBitField<uint32_t>;
+ using Value1 = BitField::DefineFirstValue<uint16_t, 16>;
+ using Value2 = Value1::DefineNextValue<uint16_t, 8>;
+ using Value3 = Value2::DefineNextValue<uint16_t, 8>;
+
+ SingleThreadedBitField<uint32_t> bit_field(0xdeadbeef);
+ EXPECT_EQ(0xde, bit_field.get<Value3>());
+ EXPECT_EQ(0xad, bit_field.get<Value2>());
+ EXPECT_EQ(0xbeef, bit_field.get<Value1>());
+}
+
+TEST_F(BitFieldTest, BitFieldBits) {
+ using BitField = SingleThreadedBitField<uint8_t>;
+ using Value1 = BitField::DefineFirstValue<bool, 1>;
+ using Value2 = Value1::DefineNextValue<bool, 1>;
+ using Value3 = Value2::DefineNextValue<bool, 1>;
+ using Value4 = Value3::DefineNextValue<bool, 1>;
+ using Value5 = Value4::DefineNextValue<bool, 1>;
+ using Value6 = Value5::DefineNextValue<bool, 1>;
+ using Value7 = Value6::DefineNextValue<bool, 1>;
+ using Value8 = Value7::DefineNextValue<bool, 1>;
+
+ SingleThreadedBitField<uint32_t> bit_field(0b10101010);
+ EXPECT_FALSE(bit_field.get<Value1>());
+ EXPECT_TRUE(bit_field.get<Value2>());
+ EXPECT_FALSE(bit_field.get<Value3>());
+ EXPECT_TRUE(bit_field.get<Value4>());
+ EXPECT_FALSE(bit_field.get<Value5>());
+ EXPECT_TRUE(bit_field.get<Value6>());
+ EXPECT_FALSE(bit_field.get<Value7>());
+ EXPECT_TRUE(bit_field.get<Value8>());
+}
+
+TEST_F(BitFieldTest, BitFieldSetValue) {
+ using BitField = SingleThreadedBitField<uint32_t>;
+ using Value1 = BitField::DefineFirstValue<uint16_t, 16>;
+ using Value2 = Value1::DefineNextValue<uint16_t, 16>;
+
+ SingleThreadedBitField<uint32_t> bit_field;
+ CHECK_EQ(0u, bit_field.get<Value1>());
+ CHECK_EQ(0u, bit_field.get<Value2>());
+ bit_field.set<Value1>(1337);
+ EXPECT_EQ(1337u, bit_field.get<Value1>());
+ EXPECT_EQ(0u, bit_field.get<Value2>());
+}
+
+TEST_F(BitFieldTest, ConcurrentBitFieldGettersReturnTheSame) {
+ using BitField = SingleThreadedBitField<uint32_t>;
+ using Value1 = BitField::DefineFirstValue<uint16_t, 16>;
+ using Value2 = Value1::DefineNextValue<uint16_t, 16>;
+
+ ConcurrentlyReadBitField<uint32_t> bit_field(0xdeadbeef);
+ CHECK_EQ(0xbeef, bit_field.get<Value1>());
+ CHECK_EQ(0xdead, bit_field.get<Value2>());
+ EXPECT_EQ(bit_field.get_concurrently<Value1>(), bit_field.get<Value1>());
+ EXPECT_EQ(bit_field.get_concurrently<Value2>(), bit_field.get<Value2>());
+}
+
+TEST_F(BitFieldTest, ConcurrentBitFieldSetValue) {
+ using BitField = SingleThreadedBitField<uint32_t>;
+ using Value1 = BitField::DefineFirstValue<uint16_t, 16>;
+ using Value2 = Value1::DefineNextValue<uint16_t, 16>;
+
+ ConcurrentlyReadBitField<uint32_t> bit_field;
+ CHECK_EQ(0u, bit_field.get_concurrently<Value1>());
+ CHECK_EQ(0u, bit_field.get_concurrently<Value2>());
+ bit_field.set<Value1>(1337);
+ EXPECT_EQ(1337u, bit_field.get_concurrently<Value1>());
+ EXPECT_EQ(0u, bit_field.get_concurrently<Value2>());
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/construct_traits.h b/chromium/third_party/blink/renderer/platform/wtf/construct_traits.h
index 7812accbc0b..02741c5c9c6 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/construct_traits.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/construct_traits.h
@@ -11,9 +11,9 @@
namespace WTF {
-// ConstructTraits is used to construct elements in WTF collections. All
-// in-place constructions that may assign Oilpan objects must be dispatched
-// through ConstructAndNotifyElement.
+// ConstructTraits is used to construct elements in WTF collections.
+// All in-place constructions that may assign Oilpan objects must be
+// dispatched through ConstructAndNotifyElement.
template <typename T, typename Traits, typename Allocator>
class ConstructTraits {
STATIC_ONLY(ConstructTraits);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h b/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
index 51b1575473f..1aeaf9b843b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
@@ -69,6 +69,12 @@ struct SyncToken;
namespace mojo {
template <typename Interface>
class PendingReceiver;
+template <typename Interface>
+class PendingRemote;
+template <typename Interface>
+class PendingAssociatedRemote;
+template <typename Interface>
+class PendingAssociatedReceiver;
}
namespace WTF {
@@ -80,6 +86,15 @@ struct CrossThreadCopierPassThrough {
static Type Copy(const T& parameter) { return parameter; }
};
+template <typename T>
+struct CrossThreadCopierByValuePassThrough {
+ STATIC_ONLY(CrossThreadCopierByValuePassThrough);
+ typedef T Type;
+ static Type Copy(T receiver) {
+ return receiver; // This is in fact a move.
+ }
+};
+
template <typename T, bool isArithmeticOrEnum>
struct CrossThreadCopierBase;
@@ -273,12 +288,31 @@ struct CrossThreadCopier<String> {
};
template <typename Interface>
-struct CrossThreadCopier<mojo::PendingReceiver<Interface>> {
+struct CrossThreadCopier<mojo::PendingReceiver<Interface>>
+ : public CrossThreadCopierByValuePassThrough<
+ mojo::PendingReceiver<Interface>> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+template <typename Interface>
+struct CrossThreadCopier<mojo::PendingRemote<Interface>>
+ : public CrossThreadCopierByValuePassThrough<
+ mojo::PendingRemote<Interface>> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+template <typename Interface>
+struct CrossThreadCopier<mojo::PendingAssociatedRemote<Interface>>
+ : public CrossThreadCopierByValuePassThrough<
+ mojo::PendingAssociatedRemote<Interface>> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+template <typename Interface>
+struct CrossThreadCopier<mojo::PendingAssociatedReceiver<Interface>>
+ : public CrossThreadCopierByValuePassThrough<
+ mojo::PendingAssociatedReceiver<Interface>> {
STATIC_ONLY(CrossThreadCopier);
- using Type = mojo::PendingReceiver<Interface>;
- static Type Copy(Type receiver) {
- return receiver; // This is in fact a move.
- }
};
template <>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/cross_thread_functional.h b/chromium/third_party/blink/renderer/platform/wtf/cross_thread_functional.h
index 86f58560098..973b8138f7d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/cross_thread_functional.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/cross_thread_functional.h
@@ -75,10 +75,10 @@ auto CrossThreadBindRepeating(FunctionType&& function, Ps&&... parameters) {
std::decay_t<Ps>...>::ok,
"A bound argument uses a bad pattern.");
return internal::MakeCrossThreadFunction(
- base::Bind(internal::CoerceFunctorForCrossThreadBind(
- std::forward<FunctionType>(function)),
- CrossThreadCopier<std::decay_t<Ps>>::Copy(
- std::forward<Ps>(parameters))...));
+ base::BindRepeating(internal::CoerceFunctorForCrossThreadBind(
+ std::forward<FunctionType>(function)),
+ CrossThreadCopier<std::decay_t<Ps>>::Copy(
+ std::forward<Ps>(parameters))...));
}
template <typename FunctionType, typename... Ps>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/deque.h b/chromium/third_party/blink/renderer/platform/wtf/deque.h
index e3e444e701b..4f2d25a8895 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/deque.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/deque.h
@@ -146,7 +146,7 @@ class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
void clear();
template <typename VisitorDispatcher, typename A = Allocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher);
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher) const;
static_assert(!std::is_polymorphic<T>::value ||
!VectorTraits<T>::kCanInitializeWithMemset,
@@ -162,6 +162,7 @@ class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
protected:
T** GetBufferSlot() { return buffer_.BufferSlot(); }
+ const T* const* GetBufferSlot() const { return buffer_.BufferSlot(); }
private:
friend class DequeIteratorBase<T, inlineCapacity, Allocator>;
@@ -169,8 +170,11 @@ class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
class BackingBuffer : public VectorBuffer<T, INLINE_CAPACITY, Allocator> {
private:
using Base = VectorBuffer<T, INLINE_CAPACITY, Allocator>;
+ using Base::BufferSafe;
using Base::size_;
+ friend class Deque;
+
public:
BackingBuffer() : Base() {}
explicit BackingBuffer(wtf_size_t capacity) : Base(capacity) {}
@@ -236,6 +240,7 @@ class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> {
typedef T& reference;
typedef std::bidirectional_iterator_tag iterator_category;
+ DequeIterator() = default;
DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, wtf_size_t index)
: Base(deque, index) {}
@@ -676,39 +681,23 @@ inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::Before() const {
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
template <typename VisitorDispatcher, typename A>
std::enable_if_t<A::kIsGarbageCollected>
-Deque<T, inlineCapacity, Allocator>::Trace(VisitorDispatcher visitor) {
+Deque<T, inlineCapacity, Allocator>::Trace(VisitorDispatcher visitor) const {
+ // Bail out for concurrent marking.
+ if (visitor->ConcurrentTracingBailOut(
+ {this, [](blink::Visitor* visitor, const void* object) {
+ reinterpret_cast<const Deque<T, inlineCapacity, Allocator>*>(
+ object)
+ ->Trace(visitor);
+ }}))
+ return;
+
+ static_assert(inlineCapacity == 0,
+ "Heap allocated Deque should not use inline buffer");
static_assert(Allocator::kIsGarbageCollected,
"Garbage collector must be enabled.");
- if (buffer_.HasOutOfLineBuffer()) {
- Allocator::TraceVectorBacking(visitor, buffer_.Buffer(),
- buffer_.BufferSlot());
- } else {
- Allocator::TraceVectorBacking(visitor, static_cast<T*>(nullptr),
- buffer_.BufferSlot());
- const T* buffer_begin = buffer_.Buffer();
- const T* end = buffer_begin + end_;
- if (IsTraceableInCollectionTrait<VectorTraits<T>>::value) {
- if (start_ <= end_) {
- for (const T* buffer_entry = buffer_begin + start_; buffer_entry != end;
- buffer_entry++) {
- Allocator::template Trace<T, VectorTraits<T>>(
- visitor, *const_cast<T*>(buffer_entry));
- }
- } else {
- for (const T* buffer_entry = buffer_begin; buffer_entry != end;
- buffer_entry++) {
- Allocator::template Trace<T, VectorTraits<T>>(
- visitor, *const_cast<T*>(buffer_entry));
- }
- const T* buffer_end = buffer_.Buffer() + buffer_.capacity();
- for (const T* buffer_entry = buffer_begin + start_;
- buffer_entry != buffer_end; buffer_entry++) {
- Allocator::template Trace<T, VectorTraits<T>>(
- visitor, *const_cast<T*>(buffer_entry));
- }
- }
- }
- }
+ const T* buffer = buffer_.BufferSafe();
+ DCHECK(!buffer || buffer_.IsOutOfLineBuffer(buffer));
+ Allocator::TraceVectorBacking(visitor, buffer, buffer_.BufferSlot());
}
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h b/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h
index 9e15db75c15..23d62960ec9 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_counted_set.h
@@ -106,7 +106,8 @@ class HashCountedSet {
Vector<Value> AsVector() const;
template <typename VisitorDispatcher, typename A = Allocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher visitor) {
+ std::enable_if_t<A::kIsGarbageCollected> Trace(
+ VisitorDispatcher visitor) const {
impl_.Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_map.h b/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
index 46b39e0697f..88fc20f0ea1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
@@ -22,6 +22,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_MAP_H_
#include <initializer_list>
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/hash_table.h"
@@ -43,6 +44,12 @@ struct KeyValuePairKeyExtractor {
static const typename T::KeyType& Extract(const T& p) {
return p.key;
}
+ // Assumes out points to a buffer of size at least sizeof(T::KeyType).
+ template <typename T>
+ static const typename T::KeyType& ExtractSafe(const T& p, void* out) {
+ AtomicReadMemcpy<sizeof(typename T::KeyType)>(out, &p.key);
+ return *reinterpret_cast<typename T::KeyType*>(out);
+ }
};
// Note: empty or deleted key values are not allowed, using them may lead to
@@ -202,7 +209,8 @@ class HashMap {
static bool IsValidKey(const IncomingKeyType&);
template <typename VisitorDispatcher, typename A = Allocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher visitor) {
+ std::enable_if_t<A::kIsGarbageCollected> Trace(
+ VisitorDispatcher visitor) const {
impl_.Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
index d7cdeeddf1c..abef9643fb0 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
@@ -22,6 +22,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_SET_H_
#include <initializer_list>
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_table.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
@@ -134,7 +135,8 @@ class HashSet {
ValueType TakeAny();
template <typename VisitorDispatcher, typename A = Allocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher visitor) {
+ std::enable_if_t<A::kIsGarbageCollected> Trace(
+ VisitorDispatcher visitor) const {
impl_.Trace(visitor);
}
@@ -151,6 +153,12 @@ struct IdentityExtractor {
static const T& Extract(const T& t) {
return t;
}
+ // Assumes out points to a buffer of size at least sizeof(T).
+ template <typename T>
+ static const T& ExtractSafe(const T& t, void* out) {
+ AtomicReadMemcpy<sizeof(T)>(out, &t);
+ return *reinterpret_cast<T*>(out);
+ }
};
template <typename Translator>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
index 472e2232846..1d195f1218b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -23,9 +23,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_TABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_TABLE_H_
-#include <atomic>
#include <memory>
+#include "base/bits.h"
#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
@@ -92,13 +92,6 @@
#endif
#endif
-namespace {
-template <typename T>
-ALWAYS_INLINE std::atomic<T>& AsAtomic(T& t) {
- return reinterpret_cast<std::atomic<T>&>(t);
-}
-} // namespace
-
namespace WTF {
// This is for tracing inside collections that have special support for weak
@@ -144,7 +137,7 @@ struct WTF_EXPORT HashTableStats {
static HashTableStats& instance();
template <typename VisitorDispatcher>
- void trace(VisitorDispatcher) {}
+ void trace(VisitorDispatcher) const {}
private:
void RecordCollisionAtCountWithoutLock(int count);
@@ -657,15 +650,32 @@ struct HashTableAddResult final {
template <typename Value, typename Extractor, typename KeyTraits>
struct HashTableHelper {
+ template <typename T>
+ struct AddConstToPtrType {
+ using type = T;
+ };
+ template <typename T>
+ struct AddConstToPtrType<T*> {
+ using type = const T*;
+ };
+
+ using Key = typename AddConstToPtrType<typename KeyTraits::TraitType>::type;
+
STATIC_ONLY(HashTableHelper);
- static bool IsEmptyBucket(const Value& value) {
- return IsHashTraitsEmptyValue<KeyTraits>(Extractor::Extract(value));
+ static bool IsEmptyBucket(const Key& key) {
+ return IsHashTraitsEmptyValue<KeyTraits>(key);
}
- static bool IsDeletedBucket(const Value& value) {
- return KeyTraits::IsDeletedValue(Extractor::Extract(value));
+ static bool IsDeletedBucket(const Key& key) {
+ return KeyTraits::IsDeletedValue(key);
}
static bool IsEmptyOrDeletedBucket(const Value& value) {
- return IsEmptyBucket(value) || IsDeletedBucket(value);
+ const Key& key = Extractor::Extract(value);
+ return IsEmptyBucket(key) || IsDeletedBucket(key);
+ }
+ static bool IsEmptyOrDeletedBucketSafe(const Value& value) {
+ alignas(std::max(alignof(Key), sizeof(size_t))) char buf[sizeof(Key)];
+ const Key& key = Extractor::ExtractSafe(value, &buf);
+ return IsEmptyBucket(key) || IsDeletedBucket(key);
}
};
@@ -846,7 +856,7 @@ class HashTable final
ValueType** GetBufferSlot() { return &table_; }
template <typename VisitorDispatcher, typename A = Allocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher);
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher) const;
#if DCHECK_IS_ON()
void EnterAccessForbiddenScope() {
@@ -953,6 +963,22 @@ class HashTable final
void ClearEnqueued() { queue_flag_ = false; }
bool Enqueued() { return queue_flag_; }
+ // Constructor for hash tables with raw storage.
+ struct RawStorageTag {};
+ HashTable(RawStorageTag, ValueType* table, unsigned size)
+ : table_(table),
+ table_size_(size),
+ key_count_(0),
+ deleted_count_(0),
+ queue_flag_(0)
+#if DCHECK_IS_ON()
+ ,
+ access_forbidden_(0),
+ modifications_(0)
+#endif
+ {
+ }
+
ValueType* table_;
unsigned table_size_;
unsigned key_count_;
@@ -1664,7 +1690,17 @@ void HashTable<Key,
KeyTraits,
Allocator>::DeleteAllBucketsAndDeallocate(ValueType* table,
unsigned size) {
- if (!std::is_trivially_destructible<ValueType>::value) {
+ // We delete a bucket in the following cases:
+ // - It is not trivially destructible.
+ // - The table is weak (thus garbage collected) and we are currently marking.
+ // This is to handle the case where a backing store is removed from the
+ // HashTable after HashTable has been enqueued for processing. If we remove
+ // the backing in that case it stays unprocessed which upsets the marking
+ // verifier that checks that all backings are in consistent state.
+ const bool needs_bucket_deletion =
+ !std::is_trivially_destructible<ValueType>::value ||
+ (WTF::IsWeak<ValueType>::value && Allocator::IsIncrementalMarking());
+ if (needs_bucket_deletion) {
for (unsigned i = 0; i < size; ++i) {
// This code is called when the hash table is cleared or resized. We
// have allocated a new backing store and we need to run the
@@ -1751,7 +1787,7 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
}
}
table_ = temporary_table;
- Allocator::template BackingWriteBarrierForHashTable<HashTable>(table_);
+ Allocator::template BackingWriteBarrierForHashTable<HashTable>(&table_);
if (Traits::kEmptyValueIsZero) {
memset(original_table, 0, new_table_size * sizeof(ValueType));
@@ -1761,10 +1797,6 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
}
new_entry = RehashTo(original_table, new_table_size, new_entry);
- EnterAccessForbiddenScope();
- DeleteAllBucketsAndDeallocate(temporary_table, old_table_size);
- LeaveAccessForbiddenScope();
-
return new_entry;
}
@@ -1778,41 +1810,50 @@ template <typename Key,
Value*
HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
RehashTo(ValueType* new_table, unsigned new_table_size, Value* entry) {
- unsigned old_table_size = table_size_;
- ValueType* old_table = table_;
-
#if DUMP_HASHTABLE_STATS
- if (old_table_size != 0) {
+ if (table_size_ != 0) {
HashTableStats::instance().numRehashes.fetch_add(1,
std::memory_order_relaxed);
}
#endif
#if DUMP_HASHTABLE_STATS_PER_TABLE
- if (old_table_size != 0)
+ if (table_size_ != 0)
stats_->numRehashes.fetch_add(1, std::memory_order_relaxed);
#endif
- AsAtomic<ValueType*>(table_).store(new_table, std::memory_order_relaxed);
- Allocator::template BackingWriteBarrierForHashTable<HashTable>(new_table);
- table_size_ = new_table_size;
+ HashTable new_hash_table(RawStorageTag{}, new_table, new_table_size);
Value* new_entry = nullptr;
- for (unsigned i = 0; i != old_table_size; ++i) {
- if (IsEmptyOrDeletedBucket(old_table[i])) {
- DCHECK_NE(&old_table[i], entry);
+ for (unsigned i = 0; i != table_size_; ++i) {
+ if (IsEmptyOrDeletedBucket(table_[i])) {
+ DCHECK_NE(&table_[i], entry);
continue;
}
- Value* reinserted_entry = Reinsert(std::move(old_table[i]));
- if (&old_table[i] == entry) {
+ Value* reinserted_entry = new_hash_table.Reinsert(std::move(table_[i]));
+ if (&table_[i] == entry) {
DCHECK(!new_entry);
new_entry = reinserted_entry;
}
}
- // Rescan the contents of the backing store as no write barriers were emitted
- // during re-insertion. Traits::NeedsToForbidGCOnMove ensures that no
- // garbage collection is triggered during moving.
- Allocator::TraceMarkedBackingStore(new_table);
+
+ Allocator::TraceBackingStoreIfMarked(new_hash_table.table_);
+
+ ValueType* old_table = table_;
+ unsigned old_table_size = table_size_;
+
+ // This swaps the newly allocated buffer with the current one. The store to
+ // the current table has to be atomic to prevent races with concurrent marker.
+ AsAtomicPtr(&table_)->store(new_hash_table.table_, std::memory_order_relaxed);
+ Allocator::template BackingWriteBarrierForHashTable<HashTable>(&table_);
+ table_size_ = new_table_size;
+
+ new_hash_table.table_ = old_table;
+ new_hash_table.table_size_ = old_table_size;
+
+ // Explicitly clear since garbage collected HashTables don't do this on
+ // destruction.
+ new_hash_table.clear();
deleted_count_ = 0;
@@ -1835,7 +1876,6 @@ Value*
HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
Rehash(unsigned new_table_size, Value* entry) {
unsigned old_table_size = table_size_;
- ValueType* old_table = table_;
#if DUMP_HASHTABLE_STATS
if (old_table_size != 0) {
@@ -1862,10 +1902,6 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
ValueType* new_table = AllocateTable(new_table_size);
Value* new_entry = RehashTo(new_table, new_table_size, entry);
- EnterAccessForbiddenScope();
- DeleteAllBucketsAndDeallocate(old_table, old_table_size);
- LeaveAccessForbiddenScope();
-
return new_entry;
}
@@ -1890,7 +1926,7 @@ void HashTable<Key,
EnterAccessForbiddenScope();
DeleteAllBucketsAndDeallocate(table_, table_size_);
LeaveAccessForbiddenScope();
- table_ = nullptr;
+ AsAtomicPtr(&table_)->store(nullptr, std::memory_order_relaxed);
table_size_ = 0;
key_count_ = 0;
}
@@ -1976,11 +2012,17 @@ void HashTable<Key,
// race). Atomic reads are not needed here because this method is only called
// on the mutator thread, which is also the only one that writes to them, so
// there is *no* risk of data races when reading.
- Value* tmp_table = other.table_;
- AsAtomic<Value*>(other.table_).store(table_, std::memory_order_relaxed);
- AsAtomic<Value*>(table_).store(tmp_table, std::memory_order_relaxed);
- Allocator::template BackingWriteBarrierForHashTable<HashTable>(table_);
- Allocator::template BackingWriteBarrierForHashTable<HashTable>(other.table_);
+ AtomicWriteSwap(table_, other.table_);
+ Allocator::template BackingWriteBarrierForHashTable<HashTable>(&table_);
+ Allocator::template BackingWriteBarrierForHashTable<HashTable>(&other.table_);
+ if (IsWeak<ValueType>::value) {
+ // Weak processing is omitted when no backing store is present. In case such
+ // an empty table is later on used it needs to be strongified.
+ if (table_)
+ Allocator::TraceBackingStoreIfMarked(table_);
+ if (other.table_)
+ Allocator::TraceBackingStoreIfMarked(other.table_);
+ }
std::swap(table_size_, other.table_size_);
std::swap(key_count_, other.key_count_);
// std::swap does not work for bit fields.
@@ -2038,7 +2080,8 @@ template <WeakHandlingFlag weakHandlingFlag,
typename Allocator>
struct WeakProcessingHashTableHelper {
STATIC_ONLY(WeakProcessingHashTableHelper);
- static void Process(const typename Allocator::WeakCallbackInfo&, void*) {}
+ static void Process(const typename Allocator::WeakCallbackInfo&,
+ const void*) {}
};
template <typename Key,
@@ -2069,8 +2112,9 @@ struct WeakProcessingHashTableHelper<kWeakHandling,
// Used for purely weak and for weak-and-strong tables (ephemerons).
static void Process(const typename Allocator::WeakCallbackInfo&,
- void* parameter) {
- HashTableType* table = reinterpret_cast<HashTableType*>(parameter);
+ const void* parameter) {
+ HashTableType* table =
+ reinterpret_cast<HashTableType*>(const_cast<void*>(parameter));
// During incremental marking, the table may be freed after the callback has
// been registered.
if (!table->table_)
@@ -2105,12 +2149,22 @@ template <typename Key,
template <typename VisitorDispatcher, typename A>
std::enable_if_t<A::kIsGarbageCollected>
HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
- Trace(VisitorDispatcher visitor) {
+ Trace(VisitorDispatcher visitor) const {
+ // bail out for concurrent marking
+ if (visitor->ConcurrentTracingBailOut(
+ {this, [](blink::Visitor* visitor, const void* object) {
+ reinterpret_cast<
+ const HashTable<Key, Value, Extractor, HashFunctions, Traits,
+ KeyTraits, Allocator>*>(object)
+ ->Trace(visitor);
+ }}))
+ return;
+
static_assert(WTF::IsWeak<ValueType>::value ||
IsTraceableInCollectionTrait<Traits>::value,
"Value should not be traced");
- ValueType* table =
- AsAtomic<ValueType*>(table_).load(std::memory_order_relaxed);
+ const ValueType* table =
+ AsAtomicPtr(&table_)->load(std::memory_order_relaxed);
if (!WTF::IsWeak<ValueType>::value) {
// Strong HashTable.
Allocator::template TraceHashTableBackingStrongly<ValueType, HashTable>(
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_traits.h b/chromium/third_party/blink/renderer/platform/wtf/hash_traits.h
index fe2bea5d8d8..58833a13d2b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_traits.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_traits.h
@@ -22,7 +22,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_TRAITS_H_
-#include <string.h> // For memset.
#include <limits>
#include <memory>
#include <type_traits>
@@ -43,6 +42,27 @@ struct EnumOrGenericHashTraits;
template <typename T>
struct HashTraits;
+namespace {
+template <typename T, bool use_atomic_writes = IsTraceable<T>::value>
+void ClearMemoryAtomically(T* slot, size_t size) {
+ size_t* address = reinterpret_cast<size_t*>(slot);
+ // This method is called for clearing hash table entires that are removed. In
+ // case Oilpan concurrent marking is tracing the hash table at the same time,
+ // there might be a data race between the marker reading the entry and zeroing
+ // the entry. Using atomic reads here resolves any possible races.
+ // Note that sizeof(T) might not be a multiple of sizeof(size_t). The last
+ // sizeof(T)%sizeof(size_t) bytes don't require atomic write as it cannot hold
+ // a pointer (i.e it will not be traceable).
+ if (use_atomic_writes) {
+ for (; size >= sizeof(size_t); size -= sizeof(size_t), ++address) {
+ WTF::AsAtomicPtr(address)->store(0, std::memory_order_relaxed);
+ }
+ }
+ DCHECK(!use_atomic_writes || (size < sizeof(size_t)));
+ memset(address, 0, size);
+}
+} // namespace
+
template <typename T>
struct GenericHashTraitsBase<false, T> {
// The emptyValueIsZero flag is used to optimize allocation of empty hash
@@ -196,7 +216,7 @@ struct HashTraits<P*> : GenericHashTraits<P*> {
static void ConstructDeletedValue(P*& slot, bool) {
slot = reinterpret_cast<P*>(-1);
}
- static bool IsDeletedValue(P* value) {
+ static bool IsDeletedValue(const P* value) {
return value == reinterpret_cast<P*>(-1);
}
};
@@ -374,8 +394,9 @@ struct PairHashTraits
// at a later point, the same assumptions around memory zeroing must
// hold as they did at the initial allocation. Therefore we zero the
// value part of the slot here for GC collections.
- if (zero_value)
- memset(reinterpret_cast<void*>(&slot.second), 0, sizeof(slot.second));
+ if (zero_value) {
+ ClearMemoryAtomically(&slot.second, sizeof(slot.second));
+ }
}
static bool IsDeletedValue(const TraitType& value) {
return FirstTraits::IsDeletedValue(value.first);
@@ -446,8 +467,9 @@ struct KeyValuePairHashTraits
static void ConstructDeletedValue(TraitType& slot, bool zero_value) {
KeyTraits::ConstructDeletedValue(slot.key, zero_value);
// See similar code in this file for why we need to do this.
- if (zero_value)
- memset(reinterpret_cast<void*>(&slot.value), 0, sizeof(slot.value));
+ if (zero_value) {
+ ClearMemoryAtomically(&slot.value, sizeof(slot.value));
+ }
}
static bool IsDeletedValue(const TraitType& value) {
return KeyTraits::IsDeletedValue(value.key);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h
index 9c12afcda68..0c4308e3ee1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h
@@ -25,8 +25,10 @@
#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
+#include "third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h"
namespace WTF {
@@ -49,20 +51,51 @@ template <typename Value,
class LinkedHashSet;
template <typename LinkedHashSet>
-class LinkedHashSetIterator;
-template <typename LinkedHashSet>
class LinkedHashSetConstIterator;
template <typename LinkedHashSet>
-class LinkedHashSetReverseIterator;
-template <typename LinkedHashSet>
class LinkedHashSetConstReverseIterator;
-template <typename Value, typename HashFunctions, typename Allocator>
+template <typename Value, typename HashFunctions>
struct LinkedHashSetTranslator;
-template <typename Value, typename Allocator>
+template <typename Value>
struct LinkedHashSetExtractor;
template <typename Value, typename ValueTraits, typename Allocator>
struct LinkedHashSetTraits;
+class LinkedHashSetNodeBase;
+
+class LinkedHashSetNodeBasePointer {
+ public:
+ LinkedHashSetNodeBasePointer(LinkedHashSetNodeBase* node) : node_(node) {}
+
+ LinkedHashSetNodeBasePointer& operator=(
+ const LinkedHashSetNodeBasePointer& other) {
+ SetSafe(other);
+ return *this;
+ }
+
+ LinkedHashSetNodeBasePointer& operator=(LinkedHashSetNodeBase* other) {
+ SetSafe(other);
+ return *this;
+ }
+
+ LinkedHashSetNodeBasePointer& operator=(std::nullptr_t) {
+ SetSafe(nullptr);
+ return *this;
+ }
+
+ LinkedHashSetNodeBase* Get() const { return node_; }
+ explicit operator bool() const { return Get(); }
+ operator LinkedHashSetNodeBase*() const { return Get(); }
+ LinkedHashSetNodeBase* operator->() const { return Get(); }
+ LinkedHashSetNodeBase& operator*() const { return *Get(); }
+
+ private:
+ void SetSafe(LinkedHashSetNodeBase* node) {
+ AsAtomicPtr(&node_)->store(node, std::memory_order_relaxed);
+ }
+
+ LinkedHashSetNodeBase* node_ = nullptr;
+};
class LinkedHashSetNodeBase {
DISALLOW_NEW();
@@ -75,10 +108,16 @@ class LinkedHashSetNodeBase {
if (!next_)
return;
DCHECK(prev_);
- DCHECK(next_->prev_ == this);
- DCHECK(prev_->next_ == this);
- next_->prev_ = prev_;
- prev_->next_ = next_;
+ {
+ AsanUnpoisonScope unpoison_scope(next_, sizeof(LinkedHashSetNodeBase));
+ DCHECK(next_->prev_ == this);
+ next_->prev_ = prev_;
+ }
+ {
+ AsanUnpoisonScope unpoison_scope(prev_, sizeof(LinkedHashSetNodeBase));
+ DCHECK(prev_->next_ == this);
+ prev_->next_ = next_;
+ }
}
~LinkedHashSetNodeBase() { Unlink(); }
@@ -111,8 +150,8 @@ class LinkedHashSetNodeBase {
DCHECK((prev && next) || (!prev && !next));
}
- LinkedHashSetNodeBase* prev_;
- LinkedHashSetNodeBase* next_;
+ LinkedHashSetNodeBasePointer prev_;
+ LinkedHashSetNodeBasePointer next_;
protected:
// If we take a copy of a node we can't copy the next and prev pointers,
@@ -177,8 +216,7 @@ class LinkedHashSet {
typedef TraitsArg Traits;
typedef LinkedHashSetNode<Value> Node;
typedef LinkedHashSetNodeBase NodeBase;
- typedef LinkedHashSetTranslator<Value, HashFunctions, Allocator>
- NodeHashFunctions;
+ typedef LinkedHashSetTranslator<Value, HashFunctions> NodeHashFunctions;
typedef LinkedHashSetTraits<Value, Traits, Allocator> NodeHashTraits;
typedef HashTable<Node,
@@ -191,13 +229,11 @@ class LinkedHashSet {
ImplType;
public:
- typedef LinkedHashSetIterator<LinkedHashSet> iterator;
- friend class LinkedHashSetIterator<LinkedHashSet>;
+ typedef LinkedHashSetConstIterator<LinkedHashSet> iterator;
typedef LinkedHashSetConstIterator<LinkedHashSet> const_iterator;
friend class LinkedHashSetConstIterator<LinkedHashSet>;
- typedef LinkedHashSetReverseIterator<LinkedHashSet> reverse_iterator;
- friend class LinkedHashSetReverseIterator<LinkedHashSet>;
+ typedef LinkedHashSetConstReverseIterator<LinkedHashSet> reverse_iterator;
typedef LinkedHashSetConstReverseIterator<LinkedHashSet>
const_reverse_iterator;
friend class LinkedHashSetConstReverseIterator<LinkedHashSet>;
@@ -210,7 +246,7 @@ class LinkedHashSet {
: stored_value(&hash_table_add_result.stored_value->value_),
is_new_entry(hash_table_add_result.is_new_entry) {}
- Value* stored_value;
+ const Value* stored_value;
bool is_new_entry;
};
@@ -277,13 +313,6 @@ class LinkedHashSet {
template <typename IncomingValueType>
AddResult insert(IncomingValueType&&);
- // Same as insert() except that the return value is an
- // iterator. Useful in cases where it's needed to have the
- // same return value as find() and where it's not possible to
- // use a pointer to the storedValue.
- template <typename IncomingValueType>
- iterator AddReturnIterator(IncomingValueType&&);
-
// Add the value to the end of the collection. If the value was already in
// the list, it is moved to the end.
template <typename IncomingValueType>
@@ -298,13 +327,13 @@ class LinkedHashSet {
AddResult InsertBefore(ValuePeekInType before_value,
IncomingValueType&& new_value);
template <typename IncomingValueType>
- AddResult InsertBefore(iterator it, IncomingValueType&& new_value) {
+ AddResult InsertBefore(const_iterator it, IncomingValueType&& new_value) {
return impl_.template insert<NodeHashFunctions>(
std::forward<IncomingValueType>(new_value), it.GetNode());
}
void erase(ValuePeekInType);
- void erase(iterator);
+ void erase(const_iterator);
void clear() { impl_.clear(); }
template <typename Collection>
void RemoveAll(const Collection& other) {
@@ -312,13 +341,24 @@ class LinkedHashSet {
}
template <typename VisitorDispatcher>
- void Trace(VisitorDispatcher visitor) {
+ void Trace(VisitorDispatcher visitor) const {
+ if (visitor->ConcurrentTracingBailOut(
+ {this, [](blink::Visitor* visitor, const void* object) {
+ reinterpret_cast<const LinkedHashSet<ValueArg, HashFunctions,
+ TraitsArg, Allocator>*>(
+ object)
+ ->Trace(visitor);
+ }}))
+ return;
+
impl_.Trace(visitor);
// Should the underlying table be moved by GC, register a callback
// that fixes up the interior pointers that the (Heap)LinkedHashSet keeps.
- if (impl_.table_) {
+ const auto* table =
+ AsAtomicPtr(&impl_.table_)->load(std::memory_order_relaxed);
+ if (table) {
Allocator::RegisterBackingStoreCallback(
- visitor, impl_.table_,
+ visitor, table,
NodeHashTraits::template MoveBackingCallback<ImplType>);
}
}
@@ -336,13 +376,13 @@ class LinkedHashSet {
private:
Node* Anchor() { return reinterpret_cast<Node*>(&anchor_); }
const Node* Anchor() const { return reinterpret_cast<const Node*>(&anchor_); }
- Node* FirstNode() { return reinterpret_cast<Node*>(anchor_.next_); }
+ Node* FirstNode() { return reinterpret_cast<Node*>(anchor_.next_.Get()); }
const Node* FirstNode() const {
- return reinterpret_cast<const Node*>(anchor_.next_);
+ return reinterpret_cast<const Node*>(anchor_.next_.Get());
}
- Node* LastNode() { return reinterpret_cast<Node*>(anchor_.prev_); }
+ Node* LastNode() { return reinterpret_cast<Node*>(anchor_.prev_.Get()); }
const Node* LastNode() const {
- return reinterpret_cast<const Node*>(anchor_.prev_);
+ return reinterpret_cast<const Node*>(anchor_.prev_.Get());
}
iterator MakeIterator(const Node* position) {
@@ -362,7 +402,7 @@ class LinkedHashSet {
NodeBase anchor_;
};
-template <typename Value, typename HashFunctions, typename Allocator>
+template <typename Value, typename HashFunctions>
struct LinkedHashSetTranslator {
STATIC_ONLY(LinkedHashSetTranslator);
typedef LinkedHashSetNode<Value> Node;
@@ -395,7 +435,7 @@ struct LinkedHashSetTranslator {
static const bool safe_to_compare_to_empty_or_deleted = false;
};
-template <typename Value, typename Allocator>
+template <typename Value>
struct LinkedHashSetExtractor {
STATIC_ONLY(LinkedHashSetExtractor);
static const Value& Extract(const LinkedHashSetNode<Value>& node) {
@@ -449,10 +489,14 @@ struct LinkedHashSetTraits
}
template <typename HashTable>
- static void MoveBackingCallback(void* from, void* to, size_t size) {
+ static void MoveBackingCallback(const void* const_from,
+ const void* const_to,
+ size_t size) {
// Note: the hash table move may have been overlapping; linearly scan the
// entire table and fixup interior pointers into the old region with
// correspondingly offset ones into the new.
+ void* from = const_cast<void*>(const_from);
+ void* to = const_cast<void*>(const_to);
const size_t table_size = size / sizeof(Node);
Node* table = reinterpret_cast<Node*>(to);
NodeBase* from_start = reinterpret_cast<NodeBase*>(from);
@@ -464,7 +508,7 @@ struct LinkedHashSetTraits
if (HashTable::IsEmptyOrDeletedBucket(node))
continue;
if (node.next_ >= from_start && node.next_ < from_end) {
- const size_t diff = reinterpret_cast<uintptr_t>(node.next_) -
+ const size_t diff = reinterpret_cast<uintptr_t>(node.next_.Get()) -
reinterpret_cast<uintptr_t>(from);
node.next_ =
reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff);
@@ -473,7 +517,7 @@ struct LinkedHashSetTraits
anchor_node = node.next_;
}
if (node.prev_ >= from_start && node.prev_ < from_end) {
- const size_t diff = reinterpret_cast<uintptr_t>(node.prev_) -
+ const size_t diff = reinterpret_cast<uintptr_t>(node.prev_.Get()) -
reinterpret_cast<uintptr_t>(from);
node.prev_ =
reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff);
@@ -490,15 +534,17 @@ struct LinkedHashSetTraits
}
{
DCHECK(anchor_node->prev_ >= from_start && anchor_node->prev_ < from_end);
- const size_t diff = reinterpret_cast<uintptr_t>(anchor_node->prev_) -
- reinterpret_cast<uintptr_t>(from);
+ const size_t diff =
+ reinterpret_cast<uintptr_t>(anchor_node->prev_.Get()) -
+ reinterpret_cast<uintptr_t>(from);
anchor_node->prev_ =
reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff);
}
{
DCHECK(anchor_node->next_ >= from_start && anchor_node->next_ < from_end);
- const size_t diff = reinterpret_cast<uintptr_t>(anchor_node->next_) -
- reinterpret_cast<uintptr_t>(from);
+ const size_t diff =
+ reinterpret_cast<uintptr_t>(anchor_node->next_.Get()) -
+ reinterpret_cast<uintptr_t>(from);
anchor_node->next_ =
reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff);
}
@@ -506,59 +552,6 @@ struct LinkedHashSetTraits
};
template <typename LinkedHashSetType>
-class LinkedHashSetIterator {
- DISALLOW_NEW();
-
- private:
- typedef typename LinkedHashSetType::Node Node;
- typedef typename LinkedHashSetType::Traits Traits;
-
- typedef typename LinkedHashSetType::Value& ReferenceType;
- typedef typename LinkedHashSetType::Value* PointerType;
-
- typedef LinkedHashSetConstIterator<LinkedHashSetType> const_iterator;
-
- Node* GetNode() { return const_cast<Node*>(iterator_.GetNode()); }
-
- protected:
- LinkedHashSetIterator(const Node* position, LinkedHashSetType* container)
- : iterator_(position, container) {}
-
- public:
- // Default copy, assignment and destructor are OK.
-
- PointerType Get() const { return const_cast<PointerType>(iterator_.Get()); }
- ReferenceType operator*() const { return *Get(); }
- PointerType operator->() const { return Get(); }
-
- LinkedHashSetIterator& operator++() {
- ++iterator_;
- return *this;
- }
- LinkedHashSetIterator& operator--() {
- --iterator_;
- return *this;
- }
-
- // Postfix ++ and -- intentionally omitted.
-
- // Comparison.
- bool operator==(const LinkedHashSetIterator& other) const {
- return iterator_ == other.iterator_;
- }
- bool operator!=(const LinkedHashSetIterator& other) const {
- return iterator_ != other.iterator_;
- }
-
- operator const_iterator() const { return iterator_; }
-
- protected:
- const_iterator iterator_;
- template <typename T, typename U, typename V, typename W>
- friend class LinkedHashSet;
-};
-
-template <typename LinkedHashSetType>
class LinkedHashSetConstIterator {
DISALLOW_NEW();
@@ -569,7 +562,9 @@ class LinkedHashSetConstIterator {
typedef const typename LinkedHashSetType::Value& ReferenceType;
typedef const typename LinkedHashSetType::Value* PointerType;
- const Node* GetNode() const { return static_cast<const Node*>(position_); }
+ Node* GetNode() const {
+ return const_cast<Node*>(static_cast<const Node*>(position_));
+ }
protected:
LinkedHashSetConstIterator(const LinkedHashSetNodeBase* position,
@@ -628,42 +623,6 @@ class LinkedHashSetConstIterator {
#endif
template <typename T, typename U, typename V, typename W>
friend class LinkedHashSet;
- friend class LinkedHashSetIterator<LinkedHashSetType>;
-};
-
-template <typename LinkedHashSetType>
-class LinkedHashSetReverseIterator
- : public LinkedHashSetIterator<LinkedHashSetType> {
- typedef LinkedHashSetReverseIterator<LinkedHashSetType> reverse_iterator;
- typedef LinkedHashSetIterator<LinkedHashSetType> Superclass;
- typedef LinkedHashSetConstReverseIterator<LinkedHashSetType>
- const_reverse_iterator;
- typedef typename LinkedHashSetType::Node Node;
-
- protected:
- LinkedHashSetReverseIterator(const Node* position,
- LinkedHashSetType* container)
- : Superclass(position, container) {}
-
- public:
- LinkedHashSetReverseIterator& operator++() {
- Superclass::operator--();
- return *this;
- }
- LinkedHashSetReverseIterator& operator--() {
- Superclass::operator++();
- return *this;
- }
-
- // Postfix ++ and -- intentionally omitted.
-
- operator const_reverse_iterator() const {
- return *reinterpret_cast<const_reverse_iterator*>(
- const_cast<reverse_iterator*>(this));
- }
-
- template <typename T, typename U, typename V, typename W>
- friend class LinkedHashSet;
};
template <typename LinkedHashSetType>
@@ -797,7 +756,7 @@ inline const T& LinkedHashSet<T, U, V, W>::front() const {
template <typename T, typename U, typename V, typename W>
inline void LinkedHashSet<T, U, V, W>::RemoveFirst() {
DCHECK(!IsEmpty());
- impl_.erase(static_cast<Node*>(anchor_.next_));
+ impl_.erase(static_cast<Node*>(anchor_.next_.Get()));
}
template <typename T, typename U, typename V, typename W>
@@ -815,7 +774,7 @@ inline const T& LinkedHashSet<T, U, V, W>::back() const {
template <typename T, typename U, typename V, typename W>
inline void LinkedHashSet<T, U, V, W>::pop_back() {
DCHECK(!IsEmpty());
- impl_.erase(static_cast<Node*>(anchor_.prev_));
+ impl_.erase(static_cast<Node*>(anchor_.prev_.Get()));
}
template <typename T, typename U, typename V, typename W>
@@ -903,16 +862,6 @@ LinkedHashSet<Value, HashFunctions, Traits, Allocator>::insert(
template <typename T, typename U, typename V, typename W>
template <typename IncomingValueType>
-typename LinkedHashSet<T, U, V, W>::iterator
-LinkedHashSet<T, U, V, W>::AddReturnIterator(IncomingValueType&& value) {
- typename ImplType::AddResult result =
- impl_.template insert<NodeHashFunctions>(
- std::forward<IncomingValueType>(value), &anchor_);
- return MakeIterator(result.stored_value);
-}
-
-template <typename T, typename U, typename V, typename W>
-template <typename IncomingValueType>
typename LinkedHashSet<T, U, V, W>::AddResult
LinkedHashSet<T, U, V, W>::AppendOrMoveToLast(IncomingValueType&& value) {
typename ImplType::AddResult result =
@@ -951,7 +900,7 @@ LinkedHashSet<T, U, V, W>::InsertBefore(ValuePeekInType before_value,
}
template <typename T, typename U, typename V, typename W>
-inline void LinkedHashSet<T, U, V, W>::erase(iterator it) {
+inline void LinkedHashSet<T, U, V, W>::erase(const_iterator it) {
if (it == end())
return;
impl_.erase(it.GetNode());
@@ -964,20 +913,284 @@ inline void LinkedHashSet<T, U, V, W>::erase(ValuePeekInType value) {
template <typename T, typename Allocator>
inline void swap(LinkedHashSetNode<T>& a, LinkedHashSetNode<T>& b) {
- typedef LinkedHashSetNodeBase Base;
// The key and value cannot be swapped atomically, and it would be
// wrong to have a GC when only one was swapped and the other still
// contained garbage (eg. from a previous use of the same slot).
// Therefore we forbid a GC until both the key and the value are
// swapped.
Allocator::EnterGCForbiddenScope();
- swap(static_cast<Base&>(a), static_cast<Base&>(b));
+ swap(static_cast<LinkedHashSetNodeBase&>(a),
+ static_cast<LinkedHashSetNodeBase&>(b));
swap(a.value_, b.value_);
Allocator::LeaveGCForbiddenScope();
}
+// TODO(keinakashima): replace existing LinkedHashSet with NewLinkedHashSet
+// after completion
+
+// This class is still experimental. Do not use this class.
+
+// LinkedHashSet provides a Set interface like HashSet, but also has a
+// predictable iteration order. It has O(1) insertion, removal, and test for
+// containership. It maintains a linked list through its contents such that
+// iterating it yields values in the order in which they were inserted.
+// The linked list is implementing in a vector (with links being indexes instead
+// of pointers), to simplify the move of backing during GC compaction.
+
+// TODO(keinakashima): implement NewLinkedHashTraits (now we cannot insert
+// deleted/empty value) and add it to template parameter
+
+template <typename ValueArg, typename Allocator = PartitionAllocator>
+class NewLinkedHashSet {
+ USE_ALLOCATOR(NewLinkedHashSet, Allocator);
+
+ private:
+ using Value = ValueArg;
+ using Map = HashMap<Value,
+ wtf_size_t,
+ typename DefaultHash<Value>::Hash,
+ HashTraits<Value>,
+ HashTraits<wtf_size_t>,
+ Allocator>;
+ using ListType = VectorBackedLinkedList<Value, Allocator>;
+
+ public:
+ using iterator = typename ListType::const_iterator;
+ using reverse_iterator = typename ListType::const_reverse_iterator;
+ using const_iterator = typename ListType::const_iterator;
+ using const_reverse_iterator = typename ListType::const_reverse_iterator;
+
+ // TODO(keinakashima): add security check
+ struct AddResult final {
+ STACK_ALLOCATED();
+
+ public:
+ AddResult(const Value* stored_value, bool is_new_entry)
+ : stored_value(stored_value), is_new_entry(is_new_entry) {}
+ const Value* stored_value;
+ bool is_new_entry;
+ };
+
+ typedef typename HashTraits<Value>::PeekInType ValuePeekInType;
+
+ NewLinkedHashSet();
+ NewLinkedHashSet(const NewLinkedHashSet&) = default;
+ NewLinkedHashSet(NewLinkedHashSet&&) = default;
+ NewLinkedHashSet& operator=(const NewLinkedHashSet&) = default;
+ NewLinkedHashSet& operator=(NewLinkedHashSet&&) = default;
+
+ ~NewLinkedHashSet() = default;
+
+ void Swap(NewLinkedHashSet&);
+
+ wtf_size_t size() const { return list_.size(); }
+ bool IsEmpty() const { return list_.empty(); }
+
+ iterator begin() { return list_.begin(); }
+ const_iterator begin() const { return list_.cbegin(); }
+ const_iterator cbegin() const { return list_.cbegin(); }
+ iterator end() { return list_.end(); }
+ const_iterator end() const { return list_.cend(); }
+ const_iterator cend() const { return list_.cend(); }
+
+ reverse_iterator rbegin() { return list_.rbegin(); }
+ const_reverse_iterator rbegin() const { return list_.crbegin(); }
+ const_reverse_iterator crbegin() const { return list_.crbegin(); }
+ reverse_iterator rend() { return list_.rend(); }
+ const_reverse_iterator rend() const { return list_.crend(); }
+ const_reverse_iterator crend() const { return list_.crend(); }
+
+ const Value& front() const { return list_.front(); }
+ const Value& back() const { return list_.back(); }
+
+ iterator find(ValuePeekInType);
+ const_iterator find(ValuePeekInType) const;
+ bool Contains(ValuePeekInType) const;
+
+ template <typename IncomingValueType>
+ AddResult insert(IncomingValueType&&);
+
+ // If |value| already exists in the set, nothing happens.
+ // If |before_value| doesn't exist in the set, appends |value|.
+ template <typename IncomingValueType>
+ AddResult InsertBefore(ValuePeekInType before_value,
+ IncomingValueType&& value);
+
+ template <typename IncomingValueType>
+ AddResult InsertBefore(const_iterator it, IncomingValueType&& value);
+
+ template <typename IncomingValueType>
+ AddResult AppendOrMoveToLast(IncomingValueType&&);
+
+ template <typename IncomingValueType>
+ AddResult PrependOrMoveToFirst(IncomingValueType&&);
+
+ void erase(ValuePeekInType);
+ void erase(const_iterator);
+ void RemoveFirst();
+ void pop_back();
+
+ void clear() {
+ value_to_index_.clear();
+ list_.clear();
+ }
+
+ template <typename VisitorDispatcher, typename A = Allocator>
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher visitor) {
+ value_to_index_.Trace(visitor);
+ list_.Trace(visitor);
+ }
+
+ private:
+ enum class MoveType {
+ kMoveIfValueExists,
+ kDontMove,
+ };
+
+ template <typename IncomingValueType>
+ AddResult InsertOrMoveBefore(const_iterator, IncomingValueType&&, MoveType);
+
+ Map value_to_index_;
+ ListType list_;
+};
+
+template <typename T, typename Allocator>
+inline NewLinkedHashSet<T, Allocator>::NewLinkedHashSet() {
+ static_assert(Allocator::kIsGarbageCollected ||
+ !IsPointerToGarbageCollectedType<T>::value,
+ "Cannot put raw pointers to garbage-collected classes into "
+ "an off-heap NewLinkedHashSet. Use "
+ "HeapNewLinkedHashSet<Member<T>> instead.");
+}
+
+template <typename T, typename Allocator>
+inline void NewLinkedHashSet<T, Allocator>::Swap(NewLinkedHashSet& other) {
+ value_to_index_.swap(other.value_to_index_);
+ list_.swap(other.list_);
+}
+
+template <typename T, typename Allocator>
+typename NewLinkedHashSet<T, Allocator>::iterator
+NewLinkedHashSet<T, Allocator>::find(ValuePeekInType value) {
+ typename Map::const_iterator it = value_to_index_.find(value);
+
+ if (it == value_to_index_.end())
+ return end();
+ return list_.MakeIterator(it->value);
+}
+
+template <typename T, typename Allocator>
+typename NewLinkedHashSet<T, Allocator>::const_iterator
+NewLinkedHashSet<T, Allocator>::find(ValuePeekInType value) const {
+ typename Map::const_iterator it = value_to_index_.find(value);
+
+ if (it == value_to_index_.end())
+ return end();
+ return list_.MakeConstIterator(it->value);
+}
+
+template <typename T, typename Allocator>
+bool NewLinkedHashSet<T, Allocator>::Contains(ValuePeekInType value) const {
+ return value_to_index_.Contains(value);
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename NewLinkedHashSet<T, Allocator>::AddResult
+NewLinkedHashSet<T, Allocator>::insert(IncomingValueType&& value) {
+ return InsertOrMoveBefore(end(), std::forward<IncomingValueType>(value),
+ MoveType::kDontMove);
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename NewLinkedHashSet<T, Allocator>::AddResult
+NewLinkedHashSet<T, Allocator>::InsertBefore(ValuePeekInType before_value,
+ IncomingValueType&& value) {
+ return InsertOrMoveBefore(find(before_value),
+ std::forward<IncomingValueType>(value),
+ MoveType::kDontMove);
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename NewLinkedHashSet<T, Allocator>::AddResult
+NewLinkedHashSet<T, Allocator>::InsertBefore(const_iterator it,
+ IncomingValueType&& value) {
+ return InsertOrMoveBefore(it, std::forward<IncomingValueType>(value),
+ MoveType::kDontMove);
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename NewLinkedHashSet<T, Allocator>::AddResult
+NewLinkedHashSet<T, Allocator>::AppendOrMoveToLast(IncomingValueType&& value) {
+ return InsertOrMoveBefore(end(), std::forward<IncomingValueType>(value),
+ MoveType::kMoveIfValueExists);
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename NewLinkedHashSet<T, Allocator>::AddResult
+NewLinkedHashSet<T, Allocator>::PrependOrMoveToFirst(
+ IncomingValueType&& value) {
+ return InsertOrMoveBefore(begin(), std::forward<IncomingValueType>(value),
+ MoveType::kMoveIfValueExists);
+}
+
+template <typename T, typename Allocator>
+inline void NewLinkedHashSet<T, Allocator>::erase(ValuePeekInType value) {
+ erase(find(value));
+}
+
+template <typename T, typename Allocator>
+inline void NewLinkedHashSet<T, Allocator>::erase(const_iterator it) {
+ if (it == end())
+ return;
+ value_to_index_.erase(*it);
+ list_.erase(it);
+}
+
+template <typename T, typename Allocator>
+inline void NewLinkedHashSet<T, Allocator>::RemoveFirst() {
+ DCHECK(!IsEmpty());
+ erase(begin());
+}
+
+template <typename T, typename Allocator>
+inline void NewLinkedHashSet<T, Allocator>::pop_back() {
+ DCHECK(!IsEmpty());
+ erase(--end());
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename NewLinkedHashSet<T, Allocator>::AddResult
+NewLinkedHashSet<T, Allocator>::InsertOrMoveBefore(const_iterator position,
+ IncomingValueType&& value,
+ MoveType type) {
+ typename Map::AddResult result = value_to_index_.insert(value, kNotFound);
+
+ if (result.is_new_entry) {
+ const_iterator stored_position_iterator =
+ list_.insert(position, std::forward<IncomingValueType>(value));
+ result.stored_value->value = stored_position_iterator.GetIndex();
+ return AddResult(stored_position_iterator.Get(), true);
+ }
+
+ const_iterator stored_position_iterator =
+ list_.MakeConstIterator(result.stored_value->value);
+ if (type == MoveType::kDontMove)
+ return AddResult(stored_position_iterator.Get(), false);
+
+ const_iterator moved_position_iterator =
+ list_.MoveTo(stored_position_iterator, position);
+ return AddResult(moved_position_iterator.Get(), false);
+}
+
} // namespace WTF
using WTF::LinkedHashSet;
+using WTF::NewLinkedHashSet;
#endif /* WTF_LinkedHashSet_h */
diff --git a/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
new file mode 100644
index 00000000000..bcfb0be1d0f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
@@ -0,0 +1,463 @@
+// 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 "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_test_helper.h"
+
+namespace WTF {
+
+TEST(NewLinkedHashSetTest, CopyConstructAndAssignInt) {
+ NewLinkedHashSet<int> set1;
+ EXPECT_EQ(set1.size(), 0u);
+ EXPECT_TRUE(set1.IsEmpty());
+ set1.insert(1);
+ set1.insert(2);
+ set1.insert(3);
+ EXPECT_EQ(set1.size(), 3u);
+ NewLinkedHashSet<int> set2(set1);
+ EXPECT_EQ(set2.size(), 3u);
+ NewLinkedHashSet<int> set3;
+ EXPECT_EQ(set3.size(), 0u);
+ set3 = set2;
+ EXPECT_EQ(set3.size(), 3u);
+ auto it1 = set1.begin();
+ auto it2 = set2.begin();
+ auto it3 = set3.begin();
+ for (int i = 0; i < 3; i++) {
+ EXPECT_EQ(*it1, i + 1);
+ EXPECT_EQ(*it2, i + 1);
+ EXPECT_EQ(*it3, i + 1);
+ ++it1;
+ ++it2;
+ ++it3;
+ }
+}
+
+TEST(NewLinkedHashSetTest, CopyConstructAndAssignIntPtr) {
+ NewLinkedHashSet<int*> set1;
+ EXPECT_EQ(set1.size(), 0u);
+ EXPECT_TRUE(set1.IsEmpty());
+ std::unique_ptr<int> int1 = std::make_unique<int>(1);
+ std::unique_ptr<int> int2 = std::make_unique<int>(2);
+ std::unique_ptr<int> int3 = std::make_unique<int>(3);
+ set1.insert(int1.get());
+ set1.insert(int2.get());
+ set1.insert(int3.get());
+ EXPECT_EQ(set1.size(), 3u);
+ NewLinkedHashSet<int*> set2(set1);
+ EXPECT_EQ(set2.size(), 3u);
+ NewLinkedHashSet<int*> set3;
+ EXPECT_EQ(set3.size(), 0u);
+ set3 = set2;
+ EXPECT_EQ(set3.size(), 3u);
+ auto it1 = set1.begin();
+ auto it2 = set2.begin();
+ auto it3 = set3.begin();
+ for (int i = 0; i < 3; i++) {
+ EXPECT_EQ(**it1, i + 1);
+ EXPECT_EQ(**it2, i + 1);
+ EXPECT_EQ(**it3, i + 1);
+ ++it1;
+ ++it2;
+ ++it3;
+ }
+
+ for (int* ptr : set1)
+ *ptr += 1000;
+ it1 = set1.begin();
+ it2 = set2.begin();
+ it3 = set3.begin();
+ for (int i = 0; i < 3; i++) {
+ EXPECT_EQ(**it1, i + 1001);
+ EXPECT_EQ(**it2, i + 1001);
+ EXPECT_EQ(**it3, i + 1001);
+ ++it1;
+ ++it2;
+ ++it3;
+ }
+}
+
+TEST(NewLinkedHashSetTest, CopyConstructAndAssignString) {
+ NewLinkedHashSet<String> set1;
+ EXPECT_EQ(set1.size(), 0u);
+ EXPECT_TRUE(set1.IsEmpty());
+ set1.insert("1");
+ set1.insert("2");
+ set1.insert("3");
+ EXPECT_EQ(set1.size(), 3u);
+ NewLinkedHashSet<String> set2(set1);
+ EXPECT_EQ(set2.size(), 3u);
+ NewLinkedHashSet<String> set3;
+ EXPECT_EQ(set3.size(), 0u);
+ set3 = set2;
+ EXPECT_EQ(set3.size(), 3u);
+ auto it1 = set1.begin();
+ auto it2 = set2.begin();
+ auto it3 = set3.begin();
+ for (int i = 0; i < 3; i++) {
+ EXPECT_EQ(*it1, String(Vector<UChar>({'1' + i})));
+ EXPECT_EQ(*it2, String(Vector<UChar>({'1' + i})));
+ EXPECT_EQ(*it3, String(Vector<UChar>({'1' + i})));
+ ++it1;
+ ++it2;
+ ++it3;
+ }
+}
+
+TEST(NewLinkedHashSetTest, MoveConstructAndAssignInt) {
+ NewLinkedHashSet<ValueInstanceCount<int>> set1;
+ EXPECT_EQ(set1.size(), 0u);
+ EXPECT_TRUE(set1.IsEmpty());
+ int counter1 = 0;
+ int counter2 = 0;
+ int counter3 = 0;
+ set1.insert(ValueInstanceCount<int>(&counter1, 1));
+ set1.insert(ValueInstanceCount<int>(&counter2, 2));
+ set1.insert(ValueInstanceCount<int>(&counter3, 3));
+ EXPECT_EQ(set1.size(), 3u);
+ NewLinkedHashSet<ValueInstanceCount<int>> set2(std::move(set1));
+ EXPECT_EQ(set2.size(), 3u);
+ NewLinkedHashSet<ValueInstanceCount<int>> set3;
+ EXPECT_EQ(set3.size(), 0u);
+ set3 = std::move(set2);
+ EXPECT_EQ(set3.size(), 3u);
+ auto it = set3.begin();
+ for (int i = 0; i < 3; i++) {
+ EXPECT_EQ(it->Value(), i + 1);
+ ++it;
+ }
+
+ // Only move constructors were used, each object is only in set3.
+ // Count 2x because each set uses hash map and vector.
+ EXPECT_EQ(counter1, 2);
+ EXPECT_EQ(counter2, 2);
+ EXPECT_EQ(counter3, 2);
+
+ NewLinkedHashSet<ValueInstanceCount<int>> set4(set3);
+ // Copy constructor was used, each object is in set3 and set4.
+ EXPECT_EQ(counter1, 4);
+ EXPECT_EQ(counter2, 4);
+ EXPECT_EQ(counter3, 4);
+}
+
+TEST(NewLinkedHashSetTest, MoveConstructAndAssignString) {
+ NewLinkedHashSet<ValueInstanceCount<String>> set1;
+ EXPECT_EQ(set1.size(), 0u);
+ EXPECT_TRUE(set1.IsEmpty());
+ int counter1 = 0;
+ int counter2 = 0;
+ int counter3 = 0;
+ set1.insert(ValueInstanceCount<String>(&counter1, "1"));
+ set1.insert(ValueInstanceCount<String>(&counter2, "2"));
+ set1.insert(ValueInstanceCount<String>(&counter3, "3"));
+ EXPECT_EQ(set1.size(), 3u);
+ NewLinkedHashSet<ValueInstanceCount<String>> set2(std::move(set1));
+ EXPECT_EQ(set2.size(), 3u);
+ NewLinkedHashSet<ValueInstanceCount<String>> set3;
+ EXPECT_EQ(set3.size(), 0u);
+ set3 = std::move(set2);
+ EXPECT_EQ(set3.size(), 3u);
+ auto it = set3.begin();
+ for (int i = 0; i < 3; i++) {
+ EXPECT_EQ(it->Value(), String(Vector<UChar>({'1' + i})));
+ ++it;
+ }
+
+ // Only move constructors were used, each object is only in set3.
+ // Count 2x because each set uses hash map and vector.
+ EXPECT_EQ(counter1, 2);
+ EXPECT_EQ(counter2, 2);
+ EXPECT_EQ(counter3, 2);
+
+ NewLinkedHashSet<ValueInstanceCount<String>> set4(set3);
+ // Copy constructor was used, each object is in set3 and set4.
+ EXPECT_EQ(counter1, 4);
+ EXPECT_EQ(counter2, 4);
+ EXPECT_EQ(counter3, 4);
+}
+
+TEST(NewLinkedHashSetTest, Iterator) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.rbegin() == set.rend());
+}
+
+TEST(NewLinkedHashSetTest, FrontAndBack) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ EXPECT_EQ(set.size(), 0u);
+ EXPECT_TRUE(set.IsEmpty());
+
+ set.PrependOrMoveToFirst(1);
+ EXPECT_EQ(set.front(), 1);
+ EXPECT_EQ(set.back(), 1);
+
+ set.insert(2);
+ EXPECT_EQ(set.front(), 1);
+ EXPECT_EQ(set.back(), 2);
+
+ set.AppendOrMoveToLast(3);
+ EXPECT_EQ(set.front(), 1);
+ EXPECT_EQ(set.back(), 3);
+
+ set.PrependOrMoveToFirst(3);
+ EXPECT_EQ(set.front(), 3);
+ EXPECT_EQ(set.back(), 2);
+
+ set.AppendOrMoveToLast(1);
+ EXPECT_EQ(set.front(), 3);
+ EXPECT_EQ(set.back(), 1);
+}
+
+TEST(NewLinkedHashSetTest, FindAndContains) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ set.insert(2);
+ set.AppendOrMoveToLast(2);
+ set.PrependOrMoveToFirst(1);
+ set.insert(3);
+ set.AppendOrMoveToLast(4);
+ set.insert(5);
+
+ int i = 1;
+ for (auto element : set) {
+ EXPECT_EQ(element, i);
+ i++;
+ }
+
+ Set::const_iterator it = set.find(2);
+ EXPECT_EQ(*it, 2);
+ it = set.find(3);
+ EXPECT_EQ(*it, 3);
+ it = set.find(10);
+ EXPECT_TRUE(it == set.end());
+
+ EXPECT_TRUE(set.Contains(1));
+ EXPECT_TRUE(set.Contains(2));
+ EXPECT_TRUE(set.Contains(3));
+ EXPECT_TRUE(set.Contains(4));
+ EXPECT_TRUE(set.Contains(5));
+
+ EXPECT_FALSE(set.Contains(10));
+}
+
+TEST(NewLinkedHashSetTest, Insert) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ Set::AddResult result = set.insert(1);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 1);
+
+ result = set.insert(1);
+ EXPECT_FALSE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 1);
+
+ result = set.insert(2);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 2);
+
+ result = set.insert(3);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 3);
+
+ result = set.insert(2);
+ EXPECT_FALSE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 2);
+
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_TRUE(it == set.end());
+}
+
+TEST(NewLinkedHashSetTest, InsertBefore) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+
+ set.InsertBefore(set.begin(), 1);
+ set.InsertBefore(10, 3);
+ set.InsertBefore(3, 2);
+ set.InsertBefore(set.end(), 6);
+ set.InsertBefore(--set.end(), 5);
+ set.InsertBefore(5, 4);
+
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 4);
+ ++it;
+ EXPECT_EQ(*it, 5);
+ ++it;
+ EXPECT_EQ(*it, 6);
+ ++it;
+ EXPECT_TRUE(it == set.end());
+}
+
+TEST(NewLinkedHashSetTest, AppendOrMoveToLast) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ Set::AddResult result = set.AppendOrMoveToLast(1);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 1);
+
+ result = set.AppendOrMoveToLast(2);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 2);
+
+ result = set.AppendOrMoveToLast(1);
+ EXPECT_FALSE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 1);
+
+ result = set.AppendOrMoveToLast(3);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 3);
+
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 3);
+}
+
+TEST(NewLinkedHashSetTest, PrependOrMoveToFirst) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ Set::AddResult result = set.PrependOrMoveToFirst(1);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 1);
+
+ result = set.PrependOrMoveToFirst(2);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 2);
+
+ result = set.PrependOrMoveToFirst(1);
+ EXPECT_FALSE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 1);
+
+ result = set.PrependOrMoveToFirst(3);
+ EXPECT_TRUE(result.is_new_entry);
+ EXPECT_EQ(*result.stored_value, 3);
+
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+}
+
+TEST(NewLinkedHashSetTest, Erase) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+ set.insert(4);
+ set.insert(5);
+
+ Set::const_iterator it = set.begin();
+ ++it;
+ set.erase(it);
+ it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 4);
+ ++it;
+ EXPECT_EQ(*it, 5);
+
+ set.erase(3);
+ it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 4);
+ ++it;
+ EXPECT_EQ(*it, 5);
+
+ set.insert(6);
+ it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 4);
+ ++it;
+ EXPECT_EQ(*it, 5);
+ ++it;
+ EXPECT_EQ(*it, 6);
+}
+
+TEST(NewLinkedHashSetTest, RemoveFirst) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+
+ set.RemoveFirst();
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 3);
+
+ set.RemoveFirst();
+ it = set.begin();
+ EXPECT_EQ(*it, 3);
+
+ set.RemoveFirst();
+ EXPECT_TRUE(set.begin() == set.end());
+}
+
+TEST(NewLinkedHashSetTest, pop_back) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+
+ set.pop_back();
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+
+ set.pop_back();
+ it = set.begin();
+ EXPECT_EQ(*it, 1);
+
+ set.pop_back();
+ EXPECT_TRUE(set.begin() == set.end());
+}
+
+TEST(NewLinkedHashSetTest, Clear) {
+ using Set = NewLinkedHashSet<int>;
+ Set set;
+ set.insert(1);
+ set.insert(2);
+ set.insert(3);
+
+ set.clear();
+ EXPECT_TRUE(set.begin() == set.end());
+
+ set.insert(1);
+ Set::const_iterator it = set.begin();
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_TRUE(it == set.end());
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
index 39fd2a0dfdb..2792dbc6b97 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
@@ -58,7 +58,7 @@ class ListHashSetReverseIterator;
template <typename Set>
class ListHashSetConstReverseIterator;
-template <typename ValueArg>
+template <typename ValueArg, typename Allocator>
class ListHashSetNodeBase;
template <typename ValueArg, typename Allocator>
class ListHashSetNode;
@@ -70,6 +70,17 @@ struct ListHashSetNodeHashFunctions;
template <typename HashArg>
struct ListHashSetTranslator;
+template <typename Value, typename Allocator>
+struct ListHashSetTraits
+ : public HashTraits<ListHashSetNode<Value, Allocator>*> {
+ using Node = ListHashSetNode<Value, Allocator>;
+
+ static void ConstructDeletedValue(Node*& slot, bool) {
+ AsAtomicPtr(&slot)->store(reinterpret_cast<Node*>(-1),
+ std::memory_order_relaxed);
+ }
+};
+
// Note that for a ListHashSet you cannot specify the HashTraits as a template
// argument. It uses the default hash traits for the ValueArg type.
template <typename ValueArg,
@@ -85,7 +96,7 @@ class ListHashSet
USE_ALLOCATOR(ListHashSet, Allocator);
typedef ListHashSetNode<ValueArg, Allocator> Node;
- typedef HashTraits<Node*> NodeTraits;
+ typedef ListHashSetTraits<ValueArg, Allocator> NodeTraits;
typedef ListHashSetNodeHashFunctions<HashArg> NodeHash;
typedef ListHashSetTranslator<HashArg> BaseTranslator;
@@ -137,14 +148,9 @@ class ListHashSet
public:
friend class ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>;
AddResult(Node* node, bool is_new_entry)
- : stored_value(&node->value_),
- is_new_entry(is_new_entry),
- node_(node) {}
+ : stored_value(&node->value_), is_new_entry(is_new_entry) {}
ValueType* stored_value;
bool is_new_entry;
-
- private:
- Node* node_;
};
ListHashSet();
@@ -201,12 +207,6 @@ class ListHashSet
template <typename IncomingValueType>
AddResult insert(IncomingValueType&&);
- // Same as insert() except that the return value is an iterator. Useful in
- // cases where it's needed to have the same return value as find() and where
- // it's not possible to use a pointer to the storedValue.
- template <typename IncomingValueType>
- iterator AddReturnIterator(IncomingValueType&&);
-
// Add the value to the end of the collection. If the value was already in
// the list, it is moved to the end.
template <typename IncomingValueType>
@@ -235,8 +235,8 @@ class ListHashSet
ValueType Take(ValuePeekInType);
ValueType TakeFirst();
- template <typename VisitorDispatcher>
- void Trace(VisitorDispatcher);
+ template <typename VisitorDispatcher, typename A = AllocatorArg>
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher) const;
protected:
typename ImplType::ValueType** GetBufferSlot() {
@@ -272,10 +272,62 @@ class ListHashSet
typename Allocator::AllocatorProvider allocator_provider_;
};
+template <typename T, typename Allocator>
+class ListHashSetNodeBasePointer {
+ using NodeType = ListHashSetNodeBase<T, Allocator>;
+
+ public:
+ ListHashSetNodeBasePointer& operator=(
+ const ListHashSetNodeBasePointer& other) {
+ SetSafe(other);
+ return *this;
+ }
+
+ template <typename U>
+ ListHashSetNodeBasePointer& operator=(
+ const ListHashSetNodeBasePointer<U, Allocator>& other) {
+ SetSafe(other);
+ return *this;
+ }
+
+ template <typename U>
+ ListHashSetNodeBasePointer& operator=(U* other) {
+ SetSafe(other);
+ return *this;
+ }
+
+ ListHashSetNodeBasePointer& operator=(std::nullptr_t) {
+ SetSafe(nullptr);
+ return *this;
+ }
+
+ NodeType* Get() const { return node_; }
+ explicit operator bool() const { return Get(); }
+ operator NodeType*() const { return Get(); }
+ NodeType* operator->() const { return Get(); }
+ NodeType& operator*() const { return *Get(); }
+
+ private:
+ void SetSafe(NodeType* node) {
+ AsAtomicPtr(&node_)->store(node, std::memory_order_relaxed);
+ }
+
+ NodeType* GetSafe() const {
+ if (Allocator::kIsGarbageCollected)
+ return AsAtomicPtr(&node_)->load(std::memory_order_relaxed);
+ return node_;
+ }
+
+ NodeType* node_ = nullptr;
+
+ template <typename ValueArg, typename AllocatorArg>
+ friend class ListHashSetNode;
+};
+
// ListHashSetNode has this base class to hold the members because the MSVC
// compiler otherwise gets into circular template dependencies when trying to do
// sizeof on a node.
-template <typename ValueArg>
+template <typename ValueArg, typename Allocator>
class ListHashSetNodeBase {
DISALLOW_NEW();
@@ -285,8 +337,8 @@ class ListHashSetNodeBase {
public:
ValueArg value_;
- ListHashSetNodeBase* prev_ = nullptr;
- ListHashSetNodeBase* next_ = nullptr;
+ ListHashSetNodeBasePointer<ValueArg, Allocator> prev_;
+ ListHashSetNodeBasePointer<ValueArg, Allocator> next_;
#if DCHECK_IS_ON()
bool is_allocated_ = true;
#endif
@@ -297,7 +349,7 @@ template <typename ValueArg, size_t inlineCapacity>
struct ListHashSetAllocator : public PartitionAllocator {
typedef PartitionAllocator TableAllocator;
typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node;
- typedef ListHashSetNodeBase<ValueArg> NodeBase;
+ typedef ListHashSetNodeBase<ValueArg, ListHashSetAllocator> NodeBase;
class AllocatorProvider {
DISALLOW_NEW();
@@ -382,7 +434,7 @@ struct ListHashSetAllocator : public PartitionAllocator {
bool InPool(Node* node) { return node >= Pool() && node < PastPool(); }
template <typename VisitorDispatcher>
- static void TraceValue(VisitorDispatcher, Node*) {}
+ static void TraceValue(VisitorDispatcher, const Node*) {}
private:
Node* Pool() { return reinterpret_cast_ptr<Node*>(pool_); }
@@ -402,19 +454,19 @@ struct ListHashSetAllocator : public PartitionAllocator {
};
template <typename ValueArg, typename AllocatorArg>
-class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
+class ListHashSetNode : public ListHashSetNodeBase<ValueArg, AllocatorArg> {
public:
typedef AllocatorArg NodeAllocator;
typedef ValueArg Value;
template <typename U>
ListHashSetNode(U&& value)
- : ListHashSetNodeBase<ValueArg>(std::forward<U>(value)) {}
+ : ListHashSetNodeBase<ValueArg, AllocatorArg>(std::forward<U>(value)) {}
void* operator new(size_t, NodeAllocator* allocator) {
- static_assert(
- sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>),
- "please add any fields to the base");
+ static_assert(sizeof(ListHashSetNode) ==
+ sizeof(ListHashSetNodeBase<ValueArg, AllocatorArg>),
+ "please add any fields to the base");
return allocator->AllocateNode();
}
@@ -452,7 +504,16 @@ class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
}
template <typename VisitorDispatcher, typename A = NodeAllocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher visitor) {
+ std::enable_if_t<A::kIsGarbageCollected> Trace(
+ VisitorDispatcher visitor) const {
+ if (visitor->ConcurrentTracingBailOut(
+ {this, [](blink::Visitor* visitor, const void* object) {
+ reinterpret_cast<const ListHashSetNode<ValueArg, AllocatorArg>*>(
+ object)
+ ->Trace(visitor);
+ }}))
+ return;
+
// The conservative stack scan can find nodes that have been removed
// from the set and destructed. We don't need to trace these, and it
// would be wrong to do so, because the class will not expect the trace
@@ -460,18 +521,20 @@ class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
// node from the ListHashSet while an iterator is positioned at that
// node, so there should be no valid pointers from the stack to a
// destructed node.
- if (WasAlreadyDestructed())
+ if (WasAlreadyDestructedSafe())
return;
NodeAllocator::TraceValue(visitor, this);
- visitor->Trace(Next());
- visitor->Trace(Prev());
+ visitor->Trace(
+ reinterpret_cast<const ListHashSetNode*>(this->next_.GetSafe()));
+ visitor->Trace(
+ reinterpret_cast<const ListHashSetNode*>(this->prev_.GetSafe()));
}
ListHashSetNode* Next() const {
- return reinterpret_cast<ListHashSetNode*>(this->next_);
+ return reinterpret_cast<ListHashSetNode*>(this->next_.Get());
}
ListHashSetNode* Prev() const {
- return reinterpret_cast<ListHashSetNode*>(this->prev_);
+ return reinterpret_cast<ListHashSetNode*>(this->prev_.Get());
}
// Don't add fields here, the ListHashSetNodeBase and this should have the
@@ -483,6 +546,12 @@ class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
template <typename HashArg>
friend struct ListHashSetNodeHashFunctions;
+
+ private:
+ bool WasAlreadyDestructedSafe() const {
+ DCHECK(NodeAllocator::kIsGarbageCollected);
+ return this->prev_.GetSafe() == UnlinkedNodePointer();
+ }
};
template <typename HashArg>
@@ -544,7 +613,7 @@ class ListHashSetIterator {
operator const_iterator() const { return iterator_; }
template <typename VisitorDispatcher>
- void Trace(VisitorDispatcher visitor) {
+ void Trace(VisitorDispatcher visitor) const {
iterator_.Trace(visitor);
}
@@ -606,7 +675,7 @@ class ListHashSetConstIterator {
}
template <typename VisitorDispatcher>
- void Trace(VisitorDispatcher visitor) {
+ void Trace(VisitorDispatcher visitor) const {
visitor->Trace(*set_);
visitor->Trace(position_);
}
@@ -666,7 +735,7 @@ class ListHashSetReverseIterator {
operator const_reverse_iterator() const { return iterator_; }
template <typename VisitorDispatcher>
- void Trace(VisitorDispatcher visitor) {
+ void Trace(VisitorDispatcher visitor) const {
iterator_.trace(visitor);
}
@@ -728,7 +797,7 @@ class ListHashSetConstReverseIterator {
}
template <typename VisitorDispatcher>
- void Trace(VisitorDispatcher visitor) {
+ void Trace(VisitorDispatcher visitor) const {
visitor->Trace(*set_);
visitor->Trace(position_);
}
@@ -756,7 +825,9 @@ struct ListHashSetTranslator {
}
template <typename T, typename U, typename V>
static void Translate(T*& location, U&& key, const V& allocator) {
- location = new (const_cast<V*>(&allocator)) T(std::forward<U>(key));
+ AsAtomicPtr(&location)->store(new (const_cast<V*>(&allocator))
+ T(std::forward<U>(key)),
+ std::memory_order_relaxed);
}
};
@@ -939,14 +1010,6 @@ ListHashSet<T, inlineCapacity, U, V>::insert(IncomingValueType&& value) {
template <typename T, size_t inlineCapacity, typename U, typename V>
template <typename IncomingValueType>
-typename ListHashSet<T, inlineCapacity, U, V>::iterator
-ListHashSet<T, inlineCapacity, U, V>::AddReturnIterator(
- IncomingValueType&& value) {
- return MakeIterator(insert(std::forward<IncomingValueType>(value)).node_);
-}
-
-template <typename T, size_t inlineCapacity, typename U, typename V>
-template <typename IncomingValueType>
typename ListHashSet<T, inlineCapacity, U, V>::AddResult
ListHashSet<T, inlineCapacity, U, V>::AppendOrMoveToLast(
IncomingValueType&& value) {
@@ -1125,8 +1188,17 @@ void ListHashSet<T, inlineCapacity, U, V>::DeleteAllNodes() {
}
template <typename T, size_t inlineCapacity, typename U, typename V>
-template <typename VisitorDispatcher>
-void ListHashSet<T, inlineCapacity, U, V>::Trace(VisitorDispatcher visitor) {
+template <typename VisitorDispatcher, typename A>
+std::enable_if_t<A::kIsGarbageCollected>
+ListHashSet<T, inlineCapacity, U, V>::Trace(VisitorDispatcher visitor) const {
+ if (visitor->ConcurrentTracingBailOut(
+ {this, [](blink::Visitor* visitor, const void* object) {
+ reinterpret_cast<const ListHashSet<T, inlineCapacity, U, V>*>(
+ object)
+ ->Trace(visitor);
+ }}))
+ return;
+
static_assert(!IsWeak<T>::value,
"HeapListHashSet does not support weakness, consider using "
"HeapLinkedHashSet instead.");
diff --git a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
index cd1be0089b9..f9cb5f8270c 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
@@ -41,12 +41,17 @@ namespace {
template <typename Set>
class ListOrLinkedHashSetTest : public testing::Test {};
-using SetTypes =
- testing::Types<ListHashSet<int>, ListHashSet<int, 1>, LinkedHashSet<int>>;
+using SetTypes = testing::Types<ListHashSet<int>,
+ ListHashSet<int, 1>,
+ LinkedHashSet<int>,
+ NewLinkedHashSet<int>>;
TYPED_TEST_SUITE(ListOrLinkedHashSetTest, SetTypes);
TYPED_TEST(ListOrLinkedHashSetTest, RemoveFirst) {
using Set = TypeParam;
+ // TODO(bartekn): Make the test work. Fails due to empty value.
+ if (std::is_same<Set, NewLinkedHashSet<int>>::value)
+ return;
Set list;
list.insert(-1);
list.insert(0);
@@ -197,6 +202,9 @@ TYPED_TEST(ListOrLinkedHashSetTest, PrependOrMoveToLastWithDuplicates) {
TYPED_TEST(ListOrLinkedHashSetTest, Find) {
using Set = TypeParam;
+ // TODO(bartekn): Make the test work. Fails due to empty value.
+ if (std::is_same<Set, NewLinkedHashSet<int>>::value)
+ return;
Set set;
set.insert(-1);
set.insert(0);
@@ -228,6 +236,9 @@ TYPED_TEST(ListOrLinkedHashSetTest, Find) {
TYPED_TEST(ListOrLinkedHashSetTest, InsertBefore) {
using Set = TypeParam;
+ // TODO(bartekn): Make the test work. Fails due to empty value.
+ if (std::is_same<Set, NewLinkedHashSet<int>>::value)
+ return;
bool can_modify_while_iterating =
!std::is_same<Set, LinkedHashSet<int>>::value;
Set set;
@@ -273,54 +284,6 @@ TYPED_TEST(ListOrLinkedHashSetTest, InsertBefore) {
EXPECT_EQ(7u, set.size());
}
-TYPED_TEST(ListOrLinkedHashSetTest, AddReturnIterator) {
- using Set = TypeParam;
- bool can_modify_while_iterating =
- !std::is_same<Set, LinkedHashSet<int>>::value;
- Set set;
- set.insert(-1);
- set.insert(0);
- set.insert(1);
- set.insert(2);
-
- typename Set::iterator it = set.AddReturnIterator(3);
- EXPECT_EQ(3, *it);
- --it;
- EXPECT_EQ(2, *it);
- EXPECT_EQ(5u, set.size());
- --it;
- EXPECT_EQ(1, *it);
- --it;
- EXPECT_EQ(0, *it);
- it = set.AddReturnIterator(4);
- if (can_modify_while_iterating) {
- set.erase(3);
- set.erase(2);
- set.erase(1);
- set.erase(0);
- set.erase(-1);
- EXPECT_EQ(1u, set.size());
- }
- EXPECT_EQ(4, *it);
- ++it;
- EXPECT_EQ(it, set.end());
- --it;
- EXPECT_EQ(4, *it);
- if (can_modify_while_iterating) {
- set.InsertBefore(it, -1);
- set.InsertBefore(it, 0);
- set.InsertBefore(it, 1);
- set.InsertBefore(it, 2);
- set.InsertBefore(it, 3);
- }
- EXPECT_EQ(6u, set.size());
- it = set.AddReturnIterator(5);
- EXPECT_EQ(7u, set.size());
- set.erase(it);
- EXPECT_EQ(6u, set.size());
- EXPECT_EQ(4, set.back());
-}
-
TYPED_TEST(ListOrLinkedHashSetTest, Swap) {
using Set = TypeParam;
int num = 10;
@@ -409,11 +372,17 @@ class ListOrLinkedHashSetRefPtrTest : public testing::Test {};
using RefPtrSetTypes =
testing::Types<ListHashSet<scoped_refptr<DummyRefCounted>>,
ListHashSet<scoped_refptr<DummyRefCounted>, 1>,
- LinkedHashSet<scoped_refptr<DummyRefCounted>>>;
+ LinkedHashSet<scoped_refptr<DummyRefCounted>>,
+ NewLinkedHashSet<scoped_refptr<DummyRefCounted>>>;
TYPED_TEST_SUITE(ListOrLinkedHashSetRefPtrTest, RefPtrSetTypes);
TYPED_TEST(ListOrLinkedHashSetRefPtrTest, WithRefPtr) {
using Set = TypeParam;
+ int expected = 1;
+ // NewLinkedHashSet stores each object twice.
+ if (std::is_same<Set,
+ NewLinkedHashSet<scoped_refptr<DummyRefCounted>>>::value)
+ expected = 2;
bool is_deleted = false;
DummyRefCounted::ref_invokes_count_ = 0;
scoped_refptr<DummyRefCounted> ptr =
@@ -423,24 +392,24 @@ TYPED_TEST(ListOrLinkedHashSetRefPtrTest, WithRefPtr) {
Set set;
set.insert(ptr);
// Referenced only once (to store a copy in the container).
- EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
+ EXPECT_EQ(expected, DummyRefCounted::ref_invokes_count_);
EXPECT_EQ(ptr, set.front());
- EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
+ EXPECT_EQ(expected, DummyRefCounted::ref_invokes_count_);
DummyRefCounted* raw_ptr = ptr.get();
EXPECT_TRUE(set.Contains(ptr));
EXPECT_TRUE(set.Contains(raw_ptr));
- EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
+ EXPECT_EQ(expected, DummyRefCounted::ref_invokes_count_);
ptr = nullptr;
EXPECT_FALSE(is_deleted);
- EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
+ EXPECT_EQ(expected, DummyRefCounted::ref_invokes_count_);
set.erase(raw_ptr);
EXPECT_TRUE(is_deleted);
- EXPECT_EQ(1, DummyRefCounted::ref_invokes_count_);
+ EXPECT_EQ(expected, DummyRefCounted::ref_invokes_count_);
}
TYPED_TEST(ListOrLinkedHashSetRefPtrTest, ExerciseValuePeekInType) {
@@ -460,11 +429,10 @@ TYPED_TEST(ListOrLinkedHashSetRefPtrTest, ExerciseValuePeekInType) {
const Set& const_set(set);
const_set.find(ptr);
EXPECT_TRUE(set.Contains(ptr));
- typename Set::iterator it = set.AddReturnIterator(ptr);
+ set.insert(ptr);
set.AppendOrMoveToLast(ptr);
set.PrependOrMoveToFirst(ptr);
set.InsertBefore(ptr, ptr);
- set.InsertBefore(it, ptr);
EXPECT_EQ(1u, set.size());
set.insert(ptr2);
ptr2 = nullptr;
@@ -516,6 +484,7 @@ struct ComplexityTranslator {
template <typename Set>
class ListOrLinkedHashSetTranslatorTest : public testing::Test {};
+// TODO(bartekn): Add NewLinkedHashSet once it supports custom hash function.
using TranslatorSetTypes =
testing::Types<ListHashSet<Complicated, 256, ComplicatedHashFunctions>,
ListHashSet<Complicated, 1, ComplicatedHashFunctions>,
@@ -625,7 +594,8 @@ class ListOrLinkedHashSetCountCopyTest : public testing::Test {};
using CountCopySetTypes = testing::Types<ListHashSet<CountCopy>,
ListHashSet<CountCopy, 1>,
- LinkedHashSet<CountCopy>>;
+ LinkedHashSet<CountCopy>,
+ NewLinkedHashSet<CountCopy>>;
TYPED_TEST_SUITE(ListOrLinkedHashSetCountCopyTest, CountCopySetTypes);
TYPED_TEST(ListOrLinkedHashSetCountCopyTest,
@@ -655,6 +625,7 @@ TYPED_TEST(ListOrLinkedHashSetCountCopyTest, MoveAssignmentShouldNotMakeACopy) {
template <typename Set>
class ListOrLinkedHashSetMoveOnlyTest : public testing::Test {};
+// TODO(bartekn): Add NewLinkedHashSet once it supports move-only type.
using MoveOnlySetTypes = testing::Types<ListHashSet<MoveOnlyHashValue>,
ListHashSet<MoveOnlyHashValue, 1>,
LinkedHashSet<MoveOnlyHashValue>>;
@@ -685,14 +656,6 @@ TYPED_TEST(ListOrLinkedHashSetMoveOnlyTest, MoveOnlyValue) {
EXPECT_TRUE(iter == set.end());
// ListHashSet and LinkedHashSet have several flavors of add().
- iter = set.AddReturnIterator(MoveOnlyHashValue(2, 2));
- EXPECT_EQ(2, iter->Value());
- EXPECT_EQ(2, iter->Id());
-
- iter = set.AddReturnIterator(MoveOnlyHashValue(2, 222));
- EXPECT_EQ(2, iter->Value());
- EXPECT_EQ(2, iter->Id());
-
{
AddResult add_result = set.AppendOrMoveToLast(MoveOnlyHashValue(3, 3));
EXPECT_TRUE(add_result.is_new_entry);
@@ -758,6 +721,7 @@ struct DefaultHash<InvalidZeroValue> {
template <typename Set>
class ListOrLinkedHashSetInvalidZeroTest : public testing::Test {};
+// TODO(bartekn): Add NewLinkedHashSet once it supports custom hash traits.
using InvalidZeroValueSetTypes =
testing::Types<ListHashSet<InvalidZeroValue>,
ListHashSet<InvalidZeroValue, 1>,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/lru_cache.h b/chromium/third_party/blink/renderer/platform/wtf/lru_cache.h
new file mode 100644
index 00000000000..c2d27f0e430
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/lru_cache.h
@@ -0,0 +1,148 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_LRU_CACHE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_LRU_CACHE_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
+#include "third_party/blink/renderer/platform/wtf/doubly_linked_list.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
+
+namespace WTF {
+
+// LruCache is a simple least-recently-used cache based on HashMap and
+// DoublyLinkedList. Useful in situations where caching by using a HashMap is
+// desirable but needs to be limited in size to not grow out of proportions.
+// LruCache uses a HashMap to store cache entries, and uses a DoublyLinkedList
+// in parallel to keep track of the age of entries. Accessing an entry using
+// Get() refreshes its age, Put() places a new entry into the HashMap with
+// youngest age as well. The least recently used entry of the list is pruned
+// when a Put() call would otherwise exceed the max_size limit.
+//
+// Example:
+// const size_t kMaxSize = 2;
+// LruCache<uint16_t, String> my_cache(kMaxSize);
+// my_cache.Put(13, "first string");
+// my_cache.Put(42, "second string");
+// my_cache.Put(256, "third string");
+// my_cache.Get(13) // -> nullptr, has been removed due to kMaxSize == 2.
+// my_cache.Get(42) // -> String* "second string"
+// my_cache.Get(256) // -> String* "third_string"
+//
+// See lru_cache_test.cc for more examples.
+template <typename KeyArg,
+ typename MappedArg,
+ typename HashArg = typename DefaultHash<KeyArg>::Hash,
+ typename KeyTraitsArg = HashTraits<KeyArg>>
+class LruCache {
+ USING_FAST_MALLOC(LruCache);
+
+ private:
+ class MappedListNodeWithKey final
+ : public DoublyLinkedListNode<MappedListNodeWithKey> {
+ USING_FAST_MALLOC(MappedListNodeWithKey);
+
+ public:
+ friend class DoublyLinkedListNode<MappedListNodeWithKey>;
+
+ MappedListNodeWithKey(const KeyArg& key, MappedArg&& mapped_arg)
+ : key_(key), mapped_value_(std::move(mapped_arg)) {}
+
+ MappedArg* Value() { return &mapped_value_; }
+
+ void SetValue(MappedArg&& mapped_arg) {
+ mapped_value_ = std::move(mapped_arg);
+ }
+
+ const KeyArg& Key() const { return key_; }
+
+ private:
+ KeyArg key_;
+ MappedArg mapped_value_;
+ MappedListNodeWithKey* prev_{nullptr};
+ MappedListNodeWithKey* next_{nullptr};
+ };
+
+ using MappedListNode = std::unique_ptr<MappedListNodeWithKey>;
+
+ using HashMapType = HashMap<KeyArg, MappedListNode, HashArg, KeyTraitsArg>;
+
+ public:
+ LruCache(size_t max_size) : max_size_(max_size) {
+ static_assert(!IsGarbageCollectedType<KeyArg>::value ||
+ !IsGarbageCollectedType<MappedArg>::value,
+ "Cannot use LruCache<> with garbage collected types.");
+ CHECK_GT(max_size_, 0u);
+ }
+
+ // Retrieve cache entry under |key| if it exists and refresh its age.
+ // Returns: pointer to cache entry or nullptr if no entry is found for that
+ // key.
+ MappedArg* Get(const KeyArg& key) {
+ if (map_.IsEmpty())
+ return nullptr;
+
+ typename HashMapType::iterator find_result = map_.find(key);
+ if (find_result == map_.end())
+ return nullptr;
+
+ // Move result to beginning of list.
+ MappedListNodeWithKey* node = find_result->value.get();
+ ordering_.Remove(node);
+ ordering_.Push(node);
+ return find_result->value->Value();
+ }
+
+ // Place entry in cache as new / youngest. Multiple calls to Put() with an
+ // identical key but differing MappedArg will override the stored value and
+ // refresh the age.
+ void Put(const KeyArg& key, MappedArg&& arg) {
+ {
+ typename HashMapType::iterator find_result = map_.find(key);
+ if (find_result != map_.end()) {
+ find_result->value->SetValue(std::move(arg));
+ ordering_.Remove(find_result->value.get());
+ ordering_.Push(find_result->value.get());
+ } else {
+ auto list_node =
+ std::make_unique<MappedListNodeWithKey>(key, std::move(arg));
+ typename HashMapType::AddResult add_result =
+ map_.insert(key, std::move(list_node));
+ DCHECK(add_result.is_new_entry);
+ ordering_.Push(add_result.stored_value->value.get());
+ }
+ }
+
+ if (map_.size() > max_size_) {
+ RemoveLeastRecentlyUsed();
+ }
+ }
+
+ // Clear the cache, remove all elements.
+ void Clear() {
+ map_.clear();
+ ordering_.Clear();
+ }
+
+ size_t size() { return map_.size(); }
+
+ private:
+ void RemoveLeastRecentlyUsed() {
+ MappedListNodeWithKey* tail = ordering_.Tail();
+ ordering_.Remove(tail);
+ map_.erase(tail->Key());
+ }
+
+ HashMapType map_;
+ DoublyLinkedList<MappedListNodeWithKey> ordering_;
+ size_t max_size_;
+};
+
+} // namespace WTF
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_LRU_CACHE_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/lru_cache_test.cc b/chromium/third_party/blink/renderer/platform/wtf/lru_cache_test.cc
new file mode 100644
index 00000000000..914b15db53f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/lru_cache_test.cc
@@ -0,0 +1,110 @@
+// 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 "third_party/blink/renderer/platform/wtf/lru_cache.h"
+
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace WTF {
+
+TEST(LruCacheTest, TestEmpty) {
+ LruCache<int, int> test_cache(1);
+ EXPECT_EQ(test_cache.Get(0), nullptr);
+}
+
+TEST(LruCacheTest, TestInstantiation) {
+ const int kMaxSize = 10;
+ const int kOffset = 1000;
+ LruCache<int, int> test_cache(kMaxSize);
+ EXPECT_EQ(test_cache.size(), 0u);
+ for (size_t i = 1; i < kMaxSize * 10; ++i) {
+ test_cache.Put(i, kOffset + i);
+ }
+ EXPECT_EQ(test_cache.size(), kMaxSize * 1u);
+ EXPECT_EQ(*test_cache.Get(kMaxSize * 10 - 1), kOffset + (kMaxSize * 10 - 1));
+ EXPECT_EQ(*test_cache.Get(kMaxSize * 10 - 2), kOffset + (kMaxSize * 10 - 2));
+ EXPECT_EQ(test_cache.Get(89), nullptr);
+ EXPECT_EQ(test_cache.Get(1), nullptr);
+ test_cache.Clear();
+ EXPECT_EQ(test_cache.size(), 0u);
+}
+
+TEST(LruCacheTest, TestString) {
+ const size_t kMaxSize = 4;
+ const char* test_strings[] = {"1_testing", "2_LruCache", "3_using",
+ "4_several", "5_random", "6_strings"};
+ LruCache<uint16_t, String> test_cache(kMaxSize);
+ uint16_t counter = 1;
+ EXPECT_EQ(test_cache.size(), 0u);
+ for (auto* test_string : test_strings) {
+ test_cache.Put(counter, test_string);
+ counter++;
+ }
+ EXPECT_EQ(test_cache.size(), kMaxSize);
+ EXPECT_EQ(test_cache.Get(1), nullptr);
+ EXPECT_EQ(test_cache.Get(2), nullptr);
+ EXPECT_EQ(*test_cache.Get(3), String(test_strings[2]));
+ EXPECT_EQ(*test_cache.Get(4), String(test_strings[3]));
+ EXPECT_EQ(*test_cache.Get(5), String(test_strings[4]));
+ EXPECT_EQ(*test_cache.Get(6), String(test_strings[5]));
+ test_cache.Put(1, test_strings[0]);
+ EXPECT_EQ(*test_cache.Get(1), String(test_strings[0]));
+ EXPECT_EQ(test_cache.Get(3), nullptr);
+ EXPECT_EQ(*test_cache.Get(4), String(test_strings[3]));
+ EXPECT_EQ(*test_cache.Get(5), String(test_strings[4]));
+ EXPECT_EQ(*test_cache.Get(6), String(test_strings[5]));
+ test_cache.Clear();
+ EXPECT_EQ(test_cache.size(), 0u);
+}
+
+TEST(LruCacheTest, TestOverrideKey) {
+ const size_t kMaxSize = 2;
+ const char* test_strings[] = {"original_value", "override"};
+ LruCache<uint16_t, String> test_cache(kMaxSize);
+ EXPECT_EQ(test_cache.size(), 0u);
+ test_cache.Put(1, test_strings[0]);
+ test_cache.Put(1, test_strings[1]);
+ EXPECT_EQ(*test_cache.Get(1), String(test_strings[1]));
+}
+
+TEST(LruCacheTest, StringToVector) {
+ const size_t kMaxSize = 4u;
+ LruCache<String, Vector<String>> typeface_cache(kMaxSize);
+
+ struct FontFallbackExample {
+ String locale;
+ String typeface_name;
+ } example_typefaces[] = {{"en_us", "Arial"},
+ {"ko", "Malgun Gothic"},
+ {"ja", "Yu Gothic UI"},
+ {"en_us", "Times New Roman"},
+ {"en_us", "Calibri"},
+ {"km", "Leelawadee UI"},
+ {"zh-Hans", "Microsoft Yahei UI"},
+ {"bn", "Nirmala UI"}};
+ for (auto& example : example_typefaces) {
+ Vector<String>* cache_for_locale = typeface_cache.Get(example.locale);
+ if (cache_for_locale) {
+ cache_for_locale->push_back(example.typeface_name);
+ } else {
+ Vector<String> new_cache_for_locale;
+ new_cache_for_locale.push_back(example.typeface_name);
+ typeface_cache.Put(String(example.locale),
+ std::move(new_cache_for_locale));
+ }
+ }
+ Vector<String>* vector_for_latin = typeface_cache.Get("en_us");
+ EXPECT_TRUE(vector_for_latin);
+ EXPECT_EQ(vector_for_latin->size(), 3u);
+ EXPECT_EQ(typeface_cache.Get("zh-Hant"), nullptr);
+ EXPECT_EQ(typeface_cache.Get("ko"), nullptr);
+ EXPECT_EQ(typeface_cache.Get("ja"), nullptr);
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_interval.h b/chromium/third_party/blink/renderer/platform/wtf/pod_interval.h
index 93a5a345991..ef6972acf3d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_interval.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_interval.h
@@ -86,11 +86,11 @@ class PODInterval {
// UserData type is a pointer or other type which can be initialized
// with 0.
PODInterval(const T& low, const T& high)
- : low_(low), high_(high), data_(0), max_high_(high) {}
+ : low_(low), high_(high), data_(0), min_low_(low), max_high_(high) {}
// Constructor from two endpoints plus explicit user data.
PODInterval(const T& low, const T& high, const UserData data)
- : low_(low), high_(high), data_(data), max_high_(high) {}
+ : low_(low), high_(high), data_(data), min_low_(low), max_high_(high) {}
const T& Low() const { return low_; }
const T& High() const { return high_; }
@@ -119,6 +119,9 @@ class PODInterval {
Data() == other.Data());
}
+ const T& MinLow() const { return min_low_; }
+ void SetMinLow(const T& min_low) { min_low_ = min_low; }
+
const T& MaxHigh() const { return max_high_; }
void SetMaxHigh(const T& max_high) { max_high_ = max_high; }
@@ -132,6 +135,8 @@ class PODInterval {
builder.Append(ValueToString<T>::ToString(High()));
builder.Append("), data=");
builder.Append(ValueToString<UserData>::ToString(Data()));
+ builder.Append(", minLow=");
+ builder.Append(ValueToString<T>::ToString(MinLow()));
builder.Append(", maxHigh=");
builder.Append(ValueToString<T>::ToString(MaxHigh()));
builder.Append(']');
@@ -148,6 +153,7 @@ class PODInterval {
#else
UserData data_;
#endif
+ T min_low_;
T max_high_;
};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h b/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
index 79af877b225..7db780f2500 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_INTERVAL_TREE_H_
#include "base/macros.h"
+#include "base/optional.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/pod_arena.h"
#include "third_party/blink/renderer/platform/wtf/pod_interval.h"
@@ -105,14 +106,14 @@ class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData>> {
// Explicit dereference of "this" required because of
// inheritance rules in template classes.
IntervalSearchAdapterType adapter(result, interval.Low(), interval.High());
- SearchForOverlapsFrom<IntervalSearchAdapterType>(this->Root(), adapter);
+ SearchForOverlapsFrom(this->Root(), adapter);
}
template <class AdapterType>
void AllOverlapsWithAdapter(AdapterType& adapter) const {
// Explicit dereference of "this" required because of
// inheritance rules in template classes.
- SearchForOverlapsFrom<AdapterType>(this->Root(), adapter);
+ SearchForOverlapsFrom(this->Root(), adapter);
}
// Helper to create interval objects.
@@ -127,7 +128,13 @@ class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData>> {
return false;
if (!this->Root())
return true;
- return CheckInvariantsFromNode(this->Root(), nullptr);
+ return CheckInvariantsFromNode(this->Root());
+ }
+
+ // Returns the next interval point (start or end) after the given starting
+ // point (non-inclusive). If there is no such point, returns |base::nullopt|.
+ base::Optional<T> NextIntervalPoint(T start) const {
+ return NextIntervalPoint(start, this->Root());
}
private:
@@ -144,102 +151,184 @@ class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData>> {
// interval to the result vector. The intervals are sorted by
// increasing low endpoint.
template <class AdapterType>
- DISABLE_CFI_PERF void SearchForOverlapsFrom(IntervalNode* node,
- AdapterType& adapter) const {
- if (!node)
+ DISABLE_CFI_PERF static void SearchForOverlapsFrom(IntervalNode const* node,
+ AdapterType& adapter) {
+ // This is phrased this way to avoid the need for operator
+ // <= on type T.
+ if (!node || adapter.HighValue() < node->Data().MinLow() ||
+ node->Data().MaxHigh() < adapter.LowValue()) {
return;
+ }
// Because the intervals are sorted by left endpoint, inorder
// traversal produces results sorted as desired.
- // See whether we need to traverse the left subtree.
- IntervalNode* left = node->Left();
- if (left
- // This is phrased this way to avoid the need for operator
- // <= on type T.
- && !(left->Data().MaxHigh() < adapter.LowValue()))
- SearchForOverlapsFrom<AdapterType>(left, adapter);
+ // Attempt to traverse left subtree
+ SearchForOverlapsFrom(node->Left(), adapter);
// Check for overlap with current node.
adapter.CollectIfNeeded(node->Data());
- // See whether we need to traverse the right subtree.
- // This is phrased this way to avoid the need for operator <=
- // on type T.
- if (!(adapter.HighValue() < node->Data().Low()))
- SearchForOverlapsFrom<AdapterType>(node->Right(), adapter);
+ // Attempt to traverse right subtree
+ SearchForOverlapsFrom(node->Right(), adapter);
+ }
+
+ static base::Optional<T> NextIntervalPoint(T start,
+ IntervalNode const* node) {
+ // If this node doesn't exist or is entirely out of scope, just return. This
+ // prevents recursing deeper than necessary on the left.
+ if (!node || node->Data().MaxHigh() < start) {
+ return base::nullopt;
+ }
+ // Easy shortcut: If the lowest point in this subtree is in scope, just
+ // return that. This prevents recursing deeper than necessary on the right.
+ if (start < node->Data().MinLow()) {
+ return node->Data().MinLow();
+ }
+
+ auto left_candidate = NextIntervalPoint(start, node->Left());
+
+ // If the current node's low point isn't out of scope, we don't even need to
+ // look at the right branch.
+ if (start < node->Data().Low()) {
+ if (left_candidate.has_value()) {
+ return std::min(node->Data().Low(), left_candidate.value());
+ } else {
+ return node->Data().Low();
+ }
+ }
+
+ // If the current node's high point is in scope, consider that against the
+ // left branch
+ base::Optional<T> current_candidate;
+ if (start < node->Data().High()) {
+ if (left_candidate.has_value()) {
+ current_candidate =
+ std::min(node->Data().High(), left_candidate.value());
+ } else {
+ current_candidate = node->Data().High();
+ }
+ } else {
+ current_candidate = left_candidate;
+ }
+
+ // If the current (and left) nodes fail, tail-recurse on the right node
+ if (!current_candidate.has_value()) {
+ return NextIntervalPoint(start, node->Right());
+ }
+
+ // Otherwise, pick the min between the |current_candidate| and the right
+ // node
+ auto right_candidate = NextIntervalPoint(start, node->Right());
+ if (right_candidate.has_value()) {
+ return std::min(current_candidate.value(), right_candidate.value());
+ } else {
+ return current_candidate;
+ }
}
bool UpdateNode(IntervalNode* node) override {
- // Would use const T&, but need to reassign this reference in this
- // function.
- const T* cur_max = &node->Data().High();
+ T cur_max(node->Data().High());
+ T cur_min(node->Data().Low());
+
IntervalNode* left = node->Left();
if (left) {
- if (*cur_max < left->Data().MaxHigh())
- cur_max = &left->Data().MaxHigh();
+ // Left node will always have a lower MinLow than the right node, so just
+ // reassign immediately.
+ cur_min = left->Data().MinLow();
+ cur_max = std::max(cur_max, left->Data().MaxHigh());
}
+
IntervalNode* right = node->Right();
if (right) {
- if (*cur_max < right->Data().MaxHigh())
- cur_max = &right->Data().MaxHigh();
+ // Right node will always have greater min than current node or left
+ // branch, so don't bother checking it.
+ cur_max = std::max(cur_max, right->Data().MaxHigh());
}
- // This is phrased like this to avoid needing operator!= on type T.
- if (!(*cur_max == node->Data().MaxHigh())) {
- node->Data().SetMaxHigh(*cur_max);
- return true;
+
+ bool updated = false;
+ if (!(cur_min == node->Data().MinLow())) {
+ node->Data().SetMinLow(cur_min);
+ updated = true;
+ }
+ if (!(cur_max == node->Data().MaxHigh())) {
+ node->Data().SetMaxHigh(cur_max);
+ updated = true;
}
- return false;
+
+ return updated;
}
- bool CheckInvariantsFromNode(IntervalNode* node, T* current_max_value) const {
- // These assignments are only done in order to avoid requiring
- // a default constructor on type T.
- T left_max_value(node->Data().MaxHigh());
- T right_max_value(node->Data().MaxHigh());
- IntervalNode* left = node->Left();
- IntervalNode* right = node->Right();
+ static bool CheckInvariantsFromNode(IntervalNode const* node) {
+ IntervalNode const* left = node->Left();
+ IntervalNode const* right = node->Right();
+
+ T observed_min_value(node->Data().Low());
+ T observed_max_value(node->Data().High());
+
if (left) {
- if (!CheckInvariantsFromNode(left, &left_max_value))
+ // Ensure left branch is entirely valid
+ if (!CheckInvariantsFromNode(left)) {
+ return false;
+ }
+ // Ensure that this node's MinLow is equal to MinLow of the left branch
+ if (!(left->Data().MinLow() == node->Data().MinLow())) {
+ LogVerificationFailedAtNode(node);
return false;
+ }
+ // Ensure that this node's MaxHigh is at least MaxHigh of left branch
+ if (node->Data().MaxHigh() < left->Data().MaxHigh()) {
+ LogVerificationFailedAtNode(node);
+ return false;
+ }
+
+ observed_min_value = left->Data().MinLow();
+ observed_max_value = std::max(observed_max_value, left->Data().MaxHigh());
}
+
if (right) {
- if (!CheckInvariantsFromNode(right, &right_max_value))
+ // Ensure right branch is entirely valid
+ if (!CheckInvariantsFromNode(right)) {
return false;
+ }
+ // Ensure this node's MinLow is not greater than the right node's MinLow
+ if (right->Data().MinLow() < node->Data().MinLow()) {
+ LogVerificationFailedAtNode(node);
+ return false;
+ }
+ // Ensure that this node's MaxHigh is at least MaxHigh of right branch
+ if (node->Data().MaxHigh() < right->Data().MaxHigh()) {
+ LogVerificationFailedAtNode(node);
+ return false;
+ }
+
+ observed_max_value =
+ std::max(observed_max_value, right->Data().MaxHigh());
}
- if (!left && !right) {
- // Base case.
- if (current_max_value)
- *current_max_value = node->Data().High();
- return (node->Data().High() == node->Data().MaxHigh());
- }
- T local_max_value(node->Data().MaxHigh());
- if (!left || !right) {
- if (left)
- local_max_value = left_max_value;
- else
- local_max_value = right_max_value;
- } else {
- local_max_value =
- (left_max_value < right_max_value) ? right_max_value : left_max_value;
+
+ // Ensure this node's MinLow is the min we actually observed
+ if (!(observed_min_value == node->Data().MinLow())) {
+ LogVerificationFailedAtNode(node);
+ return false;
}
- if (local_max_value < node->Data().High())
- local_max_value = node->Data().High();
- if (!(local_max_value == node->Data().MaxHigh())) {
-#ifndef NDEBUG
- String local_max_value_string =
- ValueToString<T>::ToString(local_max_value);
- DLOG(ERROR) << "PODIntervalTree verification failed at node " << node
- << ": localMaxValue=" << local_max_value_string
- << " and data=" << node->Data().ToString();
-#endif
+ // Ensure that this node's MaxHigh is the max we actually observed
+ if (!(observed_max_value == node->Data().MaxHigh())) {
+ LogVerificationFailedAtNode(node);
return false;
}
- if (current_max_value)
- *current_max_value = local_max_value;
+
return true;
}
+#ifndef NDEBUG
+ static void LogVerificationFailedAtNode(IntervalNode const* node) {
+ DLOG(ERROR) << "PODIntervalTree verification failed at node " << node
+ << ": data=" << node->Data().ToString();
+ }
+#else
+ static void LogVerificationFailedAtNode(IntervalNode const*) {}
+#endif
+
DISALLOW_COPY_AND_ASSIGN(PODIntervalTree);
};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc b/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc
index ad4ffa6f016..cdf01a2b602 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc
@@ -57,11 +57,26 @@ TEST(PODIntervalTreeTest, TestInsertionAndQuery) {
PODIntervalTree<float> tree;
tree.Add(PODInterval<float>(2, 4));
ASSERT_TRUE(tree.CheckInvariants());
- Vector<PODInterval<float>> result =
+ Vector<PODInterval<float>> overlap =
tree.AllOverlaps(PODInterval<float>(1, 3));
- EXPECT_EQ(1U, result.size());
- EXPECT_EQ(2, result[0].Low());
- EXPECT_EQ(4, result[0].High());
+ EXPECT_EQ(1U, overlap.size());
+ EXPECT_EQ(2, overlap[0].Low());
+ EXPECT_EQ(4, overlap[0].High());
+
+ auto next_point = tree.NextIntervalPoint(1);
+ EXPECT_TRUE(next_point.has_value());
+ EXPECT_EQ(2, next_point.value());
+
+ next_point = tree.NextIntervalPoint(2);
+ EXPECT_TRUE(next_point.has_value());
+ EXPECT_EQ(4, next_point.value());
+
+ next_point = tree.NextIntervalPoint(3);
+ EXPECT_TRUE(next_point.has_value());
+ EXPECT_EQ(4, next_point.value());
+
+ next_point = tree.NextIntervalPoint(4);
+ EXPECT_FALSE(next_point.has_value());
}
TEST(PODIntervalTreeTest, TestQueryAgainstZeroSizeInterval) {
@@ -214,7 +229,7 @@ void TreeInsertionAndDeletionTest(int32_t seed, int tree_size) {
tree.Add(interval);
#ifdef DEBUG_INSERTION_AND_DELETION_TEST
DLOG(ERROR) << "*** Adding element "
- << ValueToString<PODInterval<int>>::string(interval);
+ << ValueToString<PODInterval<int>>::ToString(interval);
#endif
added_elements.push_back(interval);
}
@@ -224,8 +239,8 @@ void TreeInsertionAndDeletionTest(int32_t seed, int tree_size) {
int index = NextRandom(added_elements.size());
#ifdef DEBUG_INSERTION_AND_DELETION_TEST
DLOG(ERROR) << "*** Removing element "
- << ValueToString<PODInterval<int>>::string(
- addedElements[index]);
+ << ValueToString<PODInterval<int>>::ToString(
+ added_elements[index]);
#endif
ASSERT_TRUE(tree.Contains(added_elements[index]))
<< "Test failed for seed " << seed;
@@ -247,8 +262,8 @@ void TreeInsertionAndDeletionTest(int32_t seed, int tree_size) {
int index = NextRandom(removed_elements.size());
#ifdef DEBUG_INSERTION_AND_DELETION_TEST
DLOG(ERROR) << "*** Adding element "
- << ValueToString<PODInterval<int>>::string(
- removedElements[index]);
+ << ValueToString<PODInterval<int>>::ToString(
+ removed_elements[index]);
#endif
tree.Add(removed_elements[index]);
added_elements.push_back(removed_elements[index]);
@@ -257,8 +272,8 @@ void TreeInsertionAndDeletionTest(int32_t seed, int tree_size) {
int index = NextRandom(added_elements.size());
#ifdef DEBUG_INSERTION_AND_DELETION_TEST
DLOG(ERROR) << "*** Removing element "
- << ValueToString<PODInterval<int>>::string(
- addedElements[index]);
+ << ValueToString<PODInterval<int>>::ToString(
+ added_elements[index]);
#endif
ASSERT_TRUE(tree.Contains(added_elements[index]))
<< "Test failed for seed " << seed;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h b/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
index 2ba83d373e1..d4b7a8a6b9c 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
@@ -256,6 +256,7 @@ class PODRedBlackTree {
// Fetches the user data.
T& Data() { return data_; }
+ T const& Data() const { return data_; }
// Copies all user-level fields from the source node, but not
// internal fields. For example, the base implementation of this
@@ -265,13 +266,16 @@ class PODRedBlackTree {
// superclass implementation.
virtual void CopyFrom(Node* src) { data_ = src->Data(); }
- Node* Left() const { return left_; }
+ Node* Left() { return left_; }
+ Node const* Left() const { return left_; }
void SetLeft(Node* node) { left_ = node; }
- Node* Right() const { return right_; }
+ Node const* Right() const { return right_; }
+ Node* Right() { return right_; }
void SetRight(Node* node) { right_ = node; }
- Node* Parent() const { return parent_; }
+ Node const* Parent() const { return parent_; }
+ Node* Parent() { return parent_; }
void SetParent(Node* node) { parent_ = node; }
private:
diff --git a/chromium/third_party/blink/renderer/platform/wtf/sanitizers.h b/chromium/third_party/blink/renderer/platform/wtf/sanitizers.h
index 847424195f8..1916939fb30 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/sanitizers.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/sanitizers.h
@@ -11,12 +11,36 @@
#define ASAN_REGION_IS_POISONED(addr, size) \
__asan_region_is_poisoned(addr, size)
#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+class AsanUnpoisonScope {
+ public:
+ AsanUnpoisonScope(const void* addr, size_t size)
+ : addr_(addr), size_(size), was_poisoned_(false) {
+ if (!ASAN_REGION_IS_POISONED(const_cast<void*>(addr_), size_))
+ return;
+ ASAN_UNPOISON_MEMORY_REGION(addr_, size_);
+ was_poisoned_ = true;
+ }
+ ~AsanUnpoisonScope() {
+ if (was_poisoned_)
+ ASAN_POISON_MEMORY_REGION(addr_, size_);
+ }
+
+ private:
+ const void* addr_;
+ size_t size_;
+ bool was_poisoned_;
+};
#else
#define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#define ASAN_REGION_IS_POISONED(addr, size) \
((void)(addr), (void)(size), (void*)nullptr)
#define NO_SANITIZE_ADDRESS
+class AsanUnpoisonScope {
+ public:
+ AsanUnpoisonScope(const void*, size_t) {}
+ ~AsanUnpoisonScope() {}
+};
#endif
#if defined(LEAK_SANITIZER)
diff --git a/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc b/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc
index 9d3eb78f42a..cb8c3f8ad3b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/shared_buffer.cc
@@ -28,6 +28,7 @@
#include <memory>
+#include "base/numerics/safe_conversions.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/utf8.h"
@@ -171,7 +172,8 @@ SharedBuffer::Iterator SharedBuffer::end() const {
}
void SharedBuffer::MergeSegmentsIntoBuffer() {
- wtf_size_t bytes_left = size_ - buffer_.size();
+ wtf_size_t bytes_left =
+ base::checked_cast<wtf_size_t>(size_ - buffer_.size());
for (const auto& segment : segments_) {
wtf_size_t bytes_to_copy = std::min<wtf_size_t>(bytes_left, kSegmentSize);
buffer_.Append(segment.get(), bytes_to_copy);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc b/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc
index b2421649ff3..1aaaa1c60d2 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/stack_util.cc
@@ -24,12 +24,11 @@ size_t GetUnderestimatedStackSize() {
// and its size is different from the value which APIs tells us.
#if defined(ADDRESS_SANITIZER)
return 0;
-#endif
// FIXME: On Mac OSX and Linux, this method cannot estimate stack size
// correctly for the main thread.
-#if defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+#elif defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
defined(OS_FUCHSIA)
// pthread_getattr_np() can fail if the thread is not invoked by
// pthread_create() (e.g., the main thread of blink_unittests).
diff --git a/chromium/third_party/blink/renderer/platform/wtf/testing/run_all_tests.cc b/chromium/third_party/blink/renderer/platform/wtf/testing/run_all_tests.cc
index 5a8c45de8a1..4a54c7d144f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/testing/run_all_tests.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/testing/run_all_tests.cc
@@ -35,6 +35,6 @@
int main(int argc, char** argv) {
WTF::Partitions::Initialize();
- WTF::Initialize(nullptr);
+ WTF::Initialize();
return base::RunUnitTestsUsingBaseTestSuite(argc, argv);
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h
index a853cc40e4d..1af520552af 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h
@@ -160,6 +160,14 @@ class WTF_EXPORT StringBuilder {
AtomicString ToAtomicString();
String Substring(unsigned start, unsigned length) const;
+ operator StringView() const {
+ if (Is8Bit()) {
+ return StringView(Characters8(), length());
+ } else {
+ return StringView(Characters16(), length());
+ }
+ }
+
unsigned length() const { return length_; }
bool IsEmpty() const { return !length_; }
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc
index 2e992dfac85..a02a45ef137 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.cc
@@ -701,6 +701,15 @@ wtf_size_t StringImpl::HexToUIntStrict(bool* ok) {
NumberParsingOptions::kStrict, ok);
}
+uint64_t StringImpl::HexToUInt64Strict(bool* ok) {
+ if (Is8Bit()) {
+ return HexCharactersToUInt64(Characters8(), length_,
+ NumberParsingOptions::kStrict, ok);
+ }
+ return HexCharactersToUInt64(Characters16(), length_,
+ NumberParsingOptions::kStrict, ok);
+}
+
int64_t StringImpl::ToInt64(NumberParsingOptions options, bool* ok) const {
if (Is8Bit())
return CharactersToInt64(Characters8(), length_, options, ok);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h
index 4228268fcf3..2083ac0ffe3 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h
@@ -345,6 +345,7 @@ class WTF_EXPORT StringImpl {
uint64_t ToUInt64(NumberParsingOptions, bool* ok) const;
wtf_size_t HexToUIntStrict(bool* ok);
+ uint64_t HexToUInt64Strict(bool* ok);
// FIXME: Like NumberParsingOptions::kStrict, these give false for "ok" when
// there is trailing garbage. Like NumberParsingOptions::kLoose, these return
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc
index d00bd2605f6..d915df41740 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc
@@ -175,6 +175,20 @@ unsigned HexCharactersToUInt(const UChar* data,
return ToIntegralType<unsigned, UChar, 16>(data, length, options, ok);
}
+uint64_t HexCharactersToUInt64(const LChar* data,
+ size_t length,
+ NumberParsingOptions options,
+ bool* ok) {
+ return ToIntegralType<uint64_t, LChar, 16>(data, length, options, ok);
+}
+
+uint64_t HexCharactersToUInt64(const UChar* data,
+ size_t length,
+ NumberParsingOptions options,
+ bool* ok) {
+ return ToIntegralType<uint64_t, UChar, 16>(data, length, options, ok);
+}
+
int CharactersToInt(const LChar* data,
size_t length,
NumberParsingOptions options,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h
index ae9fdedebe7..f6e78041261 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.h
@@ -40,6 +40,14 @@ WTF_EXPORT unsigned HexCharactersToUInt(const UChar*,
size_t,
NumberParsingOptions,
bool* ok);
+WTF_EXPORT uint64_t HexCharactersToUInt64(const UChar*,
+ size_t,
+ NumberParsingOptions,
+ bool* ok);
+WTF_EXPORT uint64_t HexCharactersToUInt64(const LChar*,
+ size_t,
+ NumberParsingOptions,
+ bool* ok);
WTF_EXPORT unsigned CharactersToUInt(const LChar*,
size_t,
NumberParsingOptions,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h
index 3d92473d79e..06611ab2a58 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h
@@ -58,12 +58,12 @@ class WTF_EXPORT StringView {
StringView(StringImpl&, unsigned offset);
StringView(StringImpl&, unsigned offset, unsigned length);
- // From a String, implemented in String.h
+ // From a String, implemented in wtf_string.h
inline StringView(const String&, unsigned offset, unsigned length);
inline StringView(const String&, unsigned offset);
inline StringView(const String&);
- // From an AtomicString, implemented in AtomicString.h
+ // From an AtomicString, implemented in atomic_string.h
inline StringView(const AtomicString&, unsigned offset, unsigned length);
inline StringView(const AtomicString&, unsigned offset);
inline StringView(const AtomicString&);
@@ -253,6 +253,15 @@ WTF_EXPORT bool DeprecatedEqualIgnoringCaseAndNullity(const StringView&,
WTF_EXPORT bool EqualIgnoringASCIICase(const StringView&, const StringView&);
+template <size_t N>
+inline bool EqualIgnoringASCIICase(const StringView& a,
+ const char (&literal)[N]) {
+ if (a.length() != N - 1 || (N == 1 && a.IsNull()))
+ return false;
+ return a.Is8Bit() ? EqualIgnoringASCIICase(a.Characters8(), literal, N - 1)
+ : EqualIgnoringASCIICase(a.Characters16(), literal, N - 1);
+}
+
// TODO(esprehn): Can't make this an overload of WTF::equal since that makes
// calls to equal() that pass literal strings ambiguous. Figure out if we can
// replace all the callers with equalStringView and then rename it to equal().
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
index 924e1d55a99..143fd2b7813 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
@@ -460,4 +460,30 @@ TEST(StringViewTest, EqualIgnoringASCIICase) {
EXPECT_TRUE(EqualIgnoringASCIICase(StringView(""), ""));
}
+TEST(StringViewTest, DeprecatedEqualIgnoringCase) {
+ constexpr UChar kLongSAndKelvin[] = {0x017F, 0x212A, 0};
+ EXPECT_TRUE(DeprecatedEqualIgnoringCase("SK", kLongSAndKelvin));
+ EXPECT_TRUE(DeprecatedEqualIgnoringCase("sk", kLongSAndKelvin));
+
+ // Turkish-specific mappings are not applied.
+ constexpr UChar kSmallDotlessI[] = {0x0131, 0};
+ constexpr UChar kCapitalDotI[] = {0x0130, 0};
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("i", kSmallDotlessI));
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("i", kCapitalDotI));
+
+ // DeprecatedEqualIgnoringCase() has length-equality check.
+ constexpr UChar kSmallSharpS[] = {0x00DF, 0};
+ constexpr UChar kCapitalSharpS[] = {0x1E9E, 0};
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("ss", kSmallSharpS));
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("SS", kSmallSharpS));
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("ss", kCapitalSharpS));
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("SS", kCapitalSharpS));
+ constexpr UChar kLigatureFFI[] = {0xFB03, 0};
+ EXPECT_FALSE(DeprecatedEqualIgnoringCase("ffi", kLigatureFFI));
+
+ constexpr UChar kLigatureFFIAndSSSS[] = {0xFB03, 's', 's', 's', 's', 0};
+ constexpr UChar kFFIAndSharpSs[] = {'f', 'f', 'i', 0x00DF, 0x00DF, 0};
+ EXPECT_TRUE(DeprecatedEqualIgnoringCase(kLigatureFFIAndSSSS, kFFIAndSharpSs));
+}
+
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
index b6926170494..3d4f4108d57 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
@@ -82,7 +82,7 @@ class WTF_EXPORT TextCodec {
struct EncodeIntoResult {
wtf_size_t code_units_read;
- wtf_size_t bytes_written;
+ size_t bytes_written;
};
String Decode(const char* str,
@@ -108,14 +108,14 @@ class WTF_EXPORT TextCodec {
virtual EncodeIntoResult EncodeInto(const LChar*,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) {
+ size_t capacity) {
NOTREACHED();
return EncodeIntoResult{0, 0};
}
virtual EncodeIntoResult EncodeInto(const UChar*,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) {
+ size_t capacity) {
NOTREACHED();
return EncodeIntoResult{0, 0};
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
index 6874eca2d10..71fc2ac2aae 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
@@ -497,7 +497,7 @@ TextCodec::EncodeIntoResult TextCodecUTF8::EncodeIntoCommon(
const CharType* characters,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) {
+ size_t capacity) {
TextCodec::EncodeIntoResult encode_into_result{0, 0};
wtf_size_t i = 0;
@@ -544,7 +544,7 @@ TextCodec::EncodeIntoResult TextCodecUTF8::EncodeInto(
const UChar* characters,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) {
+ size_t capacity) {
return EncodeIntoCommon(characters, length, destination, capacity);
}
@@ -552,7 +552,7 @@ TextCodec::EncodeIntoResult TextCodecUTF8::EncodeInto(
const LChar* characters,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) {
+ size_t capacity) {
return EncodeIntoCommon(characters, length, destination, capacity);
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h
index 688a40439b6..65806a9beb1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.h
@@ -62,11 +62,11 @@ class TextCodecUTF8 : public TextCodec {
EncodeIntoResult EncodeInto(const UChar*,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) override;
+ size_t capacity) override;
EncodeIntoResult EncodeInto(const LChar*,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity) override;
+ size_t capacity) override;
template <typename CharType>
std::string EncodeCommon(const CharType* characters, wtf_size_t length);
@@ -74,7 +74,7 @@ class TextCodecUTF8 : public TextCodec {
EncodeIntoResult EncodeIntoCommon(const CharType* characters,
wtf_size_t length,
unsigned char* destination,
- wtf_size_t capacity);
+ size_t capacity);
template <typename CharType>
bool HandlePartialSequence(CharType*& destination,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
index 5d7213c8503..c32a41c8f00 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
@@ -295,6 +295,15 @@ unsigned String::HexToUIntStrict(bool* ok) const {
return impl_->HexToUIntStrict(ok);
}
+uint64_t String::HexToUInt64Strict(bool* ok) const {
+ if (!impl_) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+ return impl_->HexToUInt64Strict(ok);
+}
+
int64_t String::ToInt64Strict(bool* ok) const {
if (!impl_) {
if (ok)
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h
index df24384c5be..a50371b7b56 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -422,6 +422,7 @@ class WTF_EXPORT String {
int ToIntStrict(bool* ok = nullptr) const;
unsigned ToUIntStrict(bool* ok = nullptr) const;
unsigned HexToUIntStrict(bool* ok) const;
+ uint64_t HexToUInt64Strict(bool* ok) const;
int64_t ToInt64Strict(bool* ok = nullptr) const;
uint64_t ToUInt64Strict(bool* ok = nullptr) const;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading.cc b/chromium/third_party/blink/renderer/platform/wtf/threading.cc
index 828eee6c27c..d6636df7991 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading.cc
@@ -29,6 +29,10 @@ bool IsBeforeThreadCreated() {
void WillCreateThread() {
g_thread_created = true;
}
+
+void SetIsBeforeThreadCreatedForTest() {
+ g_thread_created = false;
+}
#endif
ThreadSpecific<Threading>* Threading::static_data_;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading.h b/chromium/third_party/blink/renderer/platform/wtf/threading.h
index 197bfe06e53..0a21c3fb321 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading.h
@@ -48,6 +48,7 @@ WTF_EXPORT base::PlatformThreadId CurrentThread();
#if DCHECK_IS_ON()
WTF_EXPORT bool IsBeforeThreadCreated();
WTF_EXPORT void WillCreateThread();
+WTF_EXPORT void SetIsBeforeThreadCreatedForTest();
#endif
class AtomicStringTable;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc b/chromium/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc
index 6ce2b8bb560..2393e012756 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/scoped_blocking_call_internal.h"
#include "base/threading/thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector.h b/chromium/third_party/blink/renderer/platform/wtf/vector.h
index 1b321ec9462..632d30883c9 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector.h
@@ -108,7 +108,7 @@ template <typename T>
struct VectorUnusedSlotClearer<true, T> {
STATIC_ONLY(VectorUnusedSlotClearer);
static void Clear(T* begin, T* end) {
- memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin));
+ AtomicMemzero(reinterpret_cast<void*>(begin), sizeof(T) * (end - begin));
}
#if DCHECK_IS_ON()
@@ -204,14 +204,40 @@ struct VectorMover<true, T, Allocator> {
Traits::NotifyNewElements(dst, src_end - src);
}
}
+
+ template <bool = Allocator::kIsGarbageCollected>
+ static void MoveOverlappingImpl(const T* src, const T* src_end, T* dst);
+ template <>
+ static void MoveOverlappingImpl<false>(const T* src,
+ const T* src_end,
+ T* dst) {
+ memmove(dst, src,
+ reinterpret_cast<const char*>(src_end) -
+ reinterpret_cast<const char*>(src));
+ }
+ template <>
+ static void MoveOverlappingImpl<true>(const T* src,
+ const T* src_end,
+ T* dst) {
+ if (src == dst)
+ return;
+ if (dst < src) {
+ for (; src < src_end; ++src, ++dst)
+ AtomicWriteMemcpy<sizeof(T)>(dst, src);
+ } else {
+ --src_end;
+ T* dst_end = dst + (src_end - src);
+ for (; src_end >= src; --src_end, --dst_end)
+ AtomicWriteMemcpy<sizeof(T)>(dst_end, src_end);
+ }
+ }
+
static void MoveOverlapping(const T* src,
const T* src_end,
T* dst,
bool has_inline_buffer) {
if (LIKELY(dst && src)) {
- memmove(dst, src,
- reinterpret_cast<const char*>(src_end) -
- reinterpret_cast<const char*>(src));
+ MoveOverlappingImpl(src, src_end, dst);
if (has_inline_buffer)
Traits::NotifyNewElements(dst, src_end - src);
}
@@ -407,13 +433,15 @@ class VectorBufferBase {
DCHECK_LE(new_capacity,
Allocator::template MaxElementCountInBackingStore<T>());
size_t size_to_allocate = AllocationSize(new_capacity);
- buffer_ = Allocator::template AllocateVectorBacking<T>(size_to_allocate);
+ AsAtomicPtr(&buffer_)->store(
+ Allocator::template AllocateVectorBacking<T>(size_to_allocate),
+ std::memory_order_relaxed);
capacity_ = static_cast<wtf_size_t>(size_to_allocate / sizeof(T));
}
void AllocateBuffer(wtf_size_t new_capacity) {
AllocateBufferNoBarrier(new_capacity);
- Allocator::BackingWriteBarrier(buffer_);
+ Allocator::BackingWriteBarrier(&buffer_);
}
size_t AllocationSize(size_t capacity) const {
@@ -446,7 +474,7 @@ class VectorBufferBase {
}
void MoveBufferInto(VectorBufferBase& other) {
- other.buffer_ = buffer_;
+ AsAtomicPtr(&other.buffer_)->store(buffer_, std::memory_order_relaxed);
other.capacity_ = capacity_;
}
@@ -481,6 +509,10 @@ class VectorBufferBase {
return buffer_ == reinterpret_cast<T*>(-1);
}
+ const T* BufferSafe() const {
+ return AsAtomicPtr(&buffer_)->load(std::memory_order_relaxed);
+ }
+
T* buffer_;
wtf_size_t capacity_;
wtf_size_t size_;
@@ -540,7 +572,7 @@ class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocator> {
}
void ResetBufferPointer() {
- buffer_ = nullptr;
+ AsAtomicPtr(&buffer_)->store(nullptr, std::memory_order_relaxed);
capacity_ = 0;
}
@@ -551,11 +583,11 @@ class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocator> {
OffsetRange other_hole) {
static_assert(VectorTraits<T>::kCanSwapUsingCopyOrMove,
"Cannot swap using copy or move.");
- std::swap(buffer_, other.buffer_);
+ AtomicWriteSwap(buffer_, other.buffer_);
std::swap(capacity_, other.capacity_);
std::swap(size_, other.size_);
- Allocator::BackingWriteBarrier(buffer_);
- Allocator::BackingWriteBarrier(other.buffer_);
+ Allocator::BackingWriteBarrier(&buffer_);
+ Allocator::BackingWriteBarrier(&other.buffer_);
}
using Base::AllocateBuffer;
@@ -570,14 +602,19 @@ class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocator> {
bool HasOutOfLineBuffer() const {
// When inlineCapacity is 0 we have an out of line buffer if we have a
// buffer.
- return Buffer();
+ return IsOutOfLineBuffer(Buffer());
}
T** BufferSlot() { return &buffer_; }
+ const T* const* BufferSlot() const { return &buffer_; }
protected:
+ using Base::BufferSafe;
+
using Base::size_;
+ bool IsOutOfLineBuffer(const T* buffer) const { return buffer; }
+
private:
using Base::buffer_;
using Base::capacity_;
@@ -648,7 +685,7 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
}
void ResetBufferPointer() {
- buffer_ = InlineBuffer();
+ AsAtomicPtr(&buffer_)->store(InlineBuffer(), std::memory_order_relaxed);
capacity_ = inlineCapacity;
}
@@ -694,8 +731,8 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
std::swap(buffer_, other.buffer_);
std::swap(capacity_, other.capacity_);
std::swap(size_, other.size_);
- Allocator::BackingWriteBarrier(buffer_);
- Allocator::BackingWriteBarrier(other.buffer_);
+ Allocator::BackingWriteBarrier(&buffer_);
+ Allocator::BackingWriteBarrier(&other.buffer_);
return;
}
@@ -756,7 +793,7 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
other.buffer_ = other.InlineBuffer();
std::swap(size_, other.size_);
ANNOTATE_NEW_BUFFER(other.buffer_, inlineCapacity, other.size_);
- Allocator::BackingWriteBarrier(buffer_);
+ Allocator::BackingWriteBarrier(&buffer_);
} else if (!this_source_begin &&
other_source_begin) { // Their buffer is inline, ours is not.
DCHECK_NE(Buffer(), InlineBuffer());
@@ -766,7 +803,7 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
buffer_ = InlineBuffer();
std::swap(size_, other.size_);
ANNOTATE_NEW_BUFFER(buffer_, inlineCapacity, size_);
- Allocator::BackingWriteBarrier(other.buffer_);
+ Allocator::BackingWriteBarrier(&other.buffer_);
} else { // Both buffers are inline.
DCHECK(this_source_begin);
DCHECK(other_source_begin);
@@ -850,15 +887,20 @@ class VectorBuffer : protected VectorBufferBase<T, Allocator> {
using Base::Buffer;
using Base::capacity;
- bool HasOutOfLineBuffer() const {
- return Buffer() && Buffer() != InlineBuffer();
- }
+ bool HasOutOfLineBuffer() const { return IsOutOfLineBuffer(Buffer()); }
T** BufferSlot() { return &buffer_; }
+ const T* const* BufferSlot() const { return &buffer_; }
protected:
+ using Base::BufferSafe;
+
using Base::size_;
+ bool IsOutOfLineBuffer(const T* buffer) const {
+ return buffer && buffer != InlineBuffer();
+ }
+
private:
using Base::buffer_;
using Base::capacity_;
@@ -1237,6 +1279,9 @@ class Vector
void EraseAt(wtf_size_t position);
void EraseAt(wtf_size_t position, wtf_size_t length);
iterator erase(iterator position);
+ iterator erase(iterator first, iterator last);
+ // This is to prevent compilation of deprecated calls like 'vector.erase(0)'.
+ void erase(std::nullptr_t) = delete;
// Remove the last element. Unlike remove(), (1) this function is fast, and
// (2) only iterators pointing to the last element will be invalidated. Other
@@ -1254,8 +1299,15 @@ class Vector
// or copy-initialize all the elements.
//
// Fill(value) is a synonym for Fill(value, size()).
- void Fill(const T&, wtf_size_t);
- void Fill(const T& val) { Fill(val, size()); }
+ //
+ // The implementation of Fill uses std::fill which is not yet supported for
+ // garbage collected vectors.
+ template <typename A = Allocator>
+ std::enable_if_t<!A::kIsGarbageCollected> Fill(const T&, wtf_size_t);
+ template <typename A = Allocator>
+ std::enable_if_t<!A::kIsGarbageCollected> Fill(const T& val) {
+ Fill(val, size());
+ }
// Swap two vectors quickly.
void swap(Vector& other) {
@@ -1291,7 +1343,7 @@ class Vector
}
template <typename VisitorDispatcher, typename A = Allocator>
- std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher);
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher) const;
class GCForbiddenScope {
STACK_ALLOCATED();
@@ -1306,6 +1358,7 @@ class Vector
using Base::ClearUnusedSlots;
T** GetBufferSlot() { return Base::BufferSlot(); }
+ const T* const* GetBufferSlot() const { return Base::BufferSlot(); }
private:
void ExpandCapacity(wtf_size_t new_min_capacity);
@@ -1326,14 +1379,12 @@ class Vector
void ReallocateBuffer(wtf_size_t);
- // This is to prevent compilation of deprecated calls like 'vector.erase(0)'.
- void erase(std::nullptr_t) = delete;
-
- using Base::size_;
- using Base::Buffer;
- using Base::SwapVectorBuffer;
using Base::AllocateBuffer;
using Base::AllocationSize;
+ using Base::Buffer;
+ using Base::BufferSafe;
+ using Base::size_;
+ using Base::SwapVectorBuffer;
};
//
@@ -1550,8 +1601,9 @@ wtf_size_t Vector<T, inlineCapacity, Allocator>::ReverseFind(
}
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
-void Vector<T, inlineCapacity, Allocator>::Fill(const T& val,
- wtf_size_t new_size) {
+template <typename A>
+std::enable_if_t<!A::kIsGarbageCollected>
+Vector<T, inlineCapacity, Allocator>::Fill(const T& val, wtf_size_t new_size) {
if (size() > new_size) {
Shrink(new_size);
} else if (new_size > capacity()) {
@@ -1922,6 +1974,17 @@ inline auto Vector<T, inlineCapacity, Allocator>::erase(iterator position)
}
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
+inline auto Vector<T, inlineCapacity, Allocator>::erase(iterator first,
+ iterator last)
+ -> iterator {
+ DCHECK_LE(first, last);
+ const wtf_size_t index = static_cast<wtf_size_t>(first - begin());
+ const wtf_size_t diff = std::distance(first, last);
+ EraseAt(index, diff);
+ return begin() + index;
+}
+
+template <typename T, wtf_size_t inlineCapacity, typename Allocator>
inline void Vector<T, inlineCapacity, Allocator>::EraseAt(wtf_size_t position,
wtf_size_t length) {
SECURITY_DCHECK(position <= size());
@@ -1976,29 +2039,37 @@ inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a,
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
template <typename VisitorDispatcher, typename A>
std::enable_if_t<A::kIsGarbageCollected>
-Vector<T, inlineCapacity, Allocator>::Trace(VisitorDispatcher visitor) {
+Vector<T, inlineCapacity, Allocator>::Trace(VisitorDispatcher visitor) const {
+ // Bail out for concurrent marking.
+ if (visitor->ConcurrentTracingBailOut(
+ {this, [](blink::Visitor* visitor, const void* object) {
+ reinterpret_cast<const Vector<T, inlineCapacity, Allocator>*>(
+ object)
+ ->Trace(visitor);
+ }}))
+ return;
+
static_assert(Allocator::kIsGarbageCollected,
"Garbage collector must be enabled.");
- if (this->HasOutOfLineBuffer()) {
- Allocator::TraceVectorBacking(visitor, Buffer(), Base::BufferSlot());
+ const T* buffer = BufferSafe();
+ if (Base::IsOutOfLineBuffer(buffer)) {
+ Allocator::TraceVectorBacking(visitor, buffer, Base::BufferSlot());
} else {
// We should not visit inline buffers, but we still need to register the
// slot for heap compaction. So, we pass nullptr to this method.
Allocator::TraceVectorBacking(visitor, static_cast<T*>(nullptr),
Base::BufferSlot());
- if (!Buffer())
+ if (!buffer)
return;
// Inline buffer requires tracing immediately.
- const T* buffer_begin = Buffer();
- const T* buffer_end = Buffer() + size();
+ const T* buffer_begin = buffer;
+ const T* buffer_end = buffer + size();
if (IsTraceableInCollectionTrait<VectorTraits<T>>::value) {
for (const T* buffer_entry = buffer_begin; buffer_entry != buffer_end;
buffer_entry++) {
- Allocator::template Trace<T, VectorTraits<T>>(
- visitor, *const_cast<T*>(buffer_entry));
+ Allocator::template Trace<T, VectorTraits<T>>(visitor, *buffer_entry);
}
- CheckUnusedSlots(Buffer() + size(), Buffer() + capacity());
}
}
}
@@ -2035,7 +2106,7 @@ void Vector<T, inlineCapacity, Allocator>::ReallocateBuffer(
ANNOTATE_DELETE_BUFFER(begin(), capacity(), size_);
Base::DeallocateBuffer(begin());
buffer.MoveBufferInto(*this);
- Allocator::BackingWriteBarrier(begin());
+ Allocator::BackingWriteBarrier(Base::BufferSlot());
}
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h b/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
new file mode 100644
index 00000000000..60383b8ac53
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
@@ -0,0 +1,597 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_BACKED_LINKED_LIST_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_BACKED_LINKED_LIST_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
+#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace WTF {
+
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListIterator;
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListConstIterator;
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListReverseIterator;
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListConstReverseIterator;
+
+template <typename ValueType, typename Allocator>
+class VectorBackedLinkedListNode {
+ USE_ALLOCATOR(VectorBackedLinkedListNode, Allocator);
+
+ public:
+ VectorBackedLinkedListNode() = delete;
+
+ VectorBackedLinkedListNode(wtf_size_t prev_index, wtf_size_t next_index)
+ : prev_index_(prev_index), next_index_(next_index) {}
+
+ VectorBackedLinkedListNode(wtf_size_t prev_index,
+ wtf_size_t next_index,
+ const ValueType& value)
+ : prev_index_(prev_index), next_index_(next_index), value_(value) {}
+
+ VectorBackedLinkedListNode(wtf_size_t prev_index,
+ wtf_size_t next_index,
+ ValueType&& value)
+ : prev_index_(prev_index),
+ next_index_(next_index),
+ value_(std::move(value)) {}
+
+ VectorBackedLinkedListNode(const VectorBackedLinkedListNode& other) = default;
+ VectorBackedLinkedListNode(VectorBackedLinkedListNode&& other) = default;
+ VectorBackedLinkedListNode& operator=(
+ const VectorBackedLinkedListNode& other) = default;
+ VectorBackedLinkedListNode& operator=(VectorBackedLinkedListNode&& other) =
+ default;
+
+ template <typename VisitorDispathcer, typename A = Allocator>
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispathcer visitor) {
+ visitor->Trace(value_);
+ }
+
+ // Those indices can be initialized with |kNotFound| (not with 0), since
+ // VectorBackedLinkedList won't be initialized with memset.
+ wtf_size_t prev_index_ = kNotFound;
+ wtf_size_t next_index_ = kNotFound;
+ ValueType value_ = HashTraits<ValueType>::EmptyValue();
+};
+
+template <typename ValueType, typename Allocator>
+struct VectorTraits<VectorBackedLinkedListNode<ValueType, Allocator>>
+ : VectorTraitsBase<VectorBackedLinkedListNode<ValueType, Allocator>> {
+ STATIC_ONLY(VectorTraits);
+
+ static const bool kNeedsDestruction =
+ VectorTraits<ValueType>::kNeedsDestruction;
+ // VectorBackedLinkedList can't be initialized with memset, because we use
+ // kNotFound as sentinel value.
+ static const bool kCanInitializeWithMemset = false;
+ static const bool kCanClearUnusedSlotsWithMemset =
+ VectorTraits<ValueType>::kCanClearUnusedSlotsWithMemset;
+ static const bool kCanCopyWithMemcpy =
+ VectorTraits<ValueType>::kCanCopyWithMemcpy;
+ static const bool kCanMoveWithMemcpy =
+ VectorTraits<ValueType>::kCanMoveWithMemcpy;
+
+ // Needs to be shadowing because |VectorTraitsBase::IsDeletedValue| uses call
+ // by value, which means we need to define copy constructor of
+ // |VectorBackedLinkedList|. We can remove this function if we change
+ // |VectorTraitsBase::IsDeletedValue| to use call by reference.
+ static bool IsDeletedValue(
+ const VectorBackedLinkedListNode<ValueType, Allocator>& node) {
+ NOTREACHED();
+ return false;
+ }
+};
+
+// VectorBackedLinkedList maintains a linked list through its contents such that
+// iterating it yields values in the order in which they were inserted.
+// The linked list is implementing in a vector (with links being indexes instead
+// of pointers), to simplify the move of backing during GC compaction.
+template <typename ValueType, typename Allocator = PartitionAllocator>
+class VectorBackedLinkedList {
+ USE_ALLOCATOR(VectorBackedLinkedList, Allocator);
+
+ private:
+ using Node = VectorBackedLinkedListNode<ValueType, Allocator>;
+ using VectorType = Vector<Node, 0, Allocator>;
+
+ public:
+ using Value = ValueType;
+ using iterator = VectorBackedLinkedListIterator<VectorBackedLinkedList>;
+ using const_iterator =
+ VectorBackedLinkedListConstIterator<VectorBackedLinkedList>;
+ friend class VectorBackedLinkedListConstIterator<VectorBackedLinkedList>;
+ using reverse_iterator =
+ VectorBackedLinkedListReverseIterator<VectorBackedLinkedList>;
+ using const_reverse_iterator =
+ VectorBackedLinkedListConstReverseIterator<VectorBackedLinkedList>;
+
+ VectorBackedLinkedList();
+
+ VectorBackedLinkedList(const VectorBackedLinkedList&) = default;
+ VectorBackedLinkedList(VectorBackedLinkedList&&) = default;
+ VectorBackedLinkedList& operator=(const VectorBackedLinkedList&) = default;
+ VectorBackedLinkedList& operator=(VectorBackedLinkedList&&) = default;
+
+ ~VectorBackedLinkedList() = default;
+
+ void swap(VectorBackedLinkedList&);
+
+ bool empty() const { return size_ == 0; }
+ wtf_size_t size() const { return size_; }
+
+ iterator begin() { return MakeIterator(UsedFirstIndex()); }
+ const_iterator begin() const { return MakeConstIterator(UsedFirstIndex()); }
+ const_iterator cbegin() const { return MakeConstIterator(UsedFirstIndex()); }
+ iterator end() { return MakeIterator(anchor_index_); }
+ const_iterator end() const { return MakeConstIterator(anchor_index_); }
+ const_iterator cend() const { return MakeConstIterator(anchor_index_); }
+ reverse_iterator rbegin() { return MakeReverseIterator(UsedLastIndex()); }
+ const_reverse_iterator rbegin() const {
+ return MakeConstReverseIterator(UsedLastIndex());
+ }
+ const_reverse_iterator crbegin() const {
+ return MakeConstReverseIterator(UsedLastIndex());
+ }
+ reverse_iterator rend() { return MakeReverseIterator(anchor_index_); }
+ const_reverse_iterator rend() const {
+ return MakeConstReverseIterator(anchor_index_);
+ }
+ const_reverse_iterator crend() const {
+ return MakeConstReverseIterator(anchor_index_);
+ }
+
+ Value& front();
+ const Value& front() const;
+ Value& back();
+ const Value& back() const;
+
+ template <typename IncomingValueType>
+ iterator insert(const_iterator position, IncomingValueType&& value);
+
+ template <typename IncomingValueType>
+ void push_front(IncomingValueType&& value) {
+ insert(cbegin(), std::forward<IncomingValueType>(value));
+ }
+
+ template <typename IncomingValueType>
+ void push_back(IncomingValueType&& value) {
+ insert(cend(), std::forward<IncomingValueType>(value));
+ }
+
+ // Moves |target| right before |new_position| in a linked list. This operation
+ // is executed by just updating indices of related nodes.
+ iterator MoveTo(const_iterator target, const_iterator new_position);
+
+ iterator erase(const_iterator);
+
+ void pop_front() {
+ DCHECK(!empty());
+ erase(cbegin());
+ }
+ void pop_back() {
+ DCHECK(!empty());
+ erase(--cend());
+ }
+
+ // Removes all elements in a linked list.
+ void clear() {
+ RegisterModification();
+ nodes_.clear();
+ // Reinserts anchor so that we can insert elements after this operation.
+ nodes_.push_back(Node(anchor_index_, anchor_index_));
+ free_head_index_ = anchor_index_;
+ size_ = 0;
+ }
+
+ template <typename VisitorDispatcher, typename A = Allocator>
+ std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher visitor) {
+ nodes_.Trace(visitor);
+ }
+
+#if DCHECK_IS_ON()
+ int64_t Modifications() const { return modifications_; }
+ void RegisterModification() { modifications_++; }
+ void CheckModifications(int64_t mods) const {
+ // VectorBackedLinkedList iterators get invalidated when the container is
+ // modified.
+ DCHECK_EQ(mods, modifications_);
+ }
+#else
+ ALWAYS_INLINE int64_t Modifications() const { return 0; }
+ ALWAYS_INLINE void RegisterModification() {}
+ ALWAYS_INLINE void CheckModifications() const {}
+#endif
+
+ private:
+ bool IsFreeListEmpty() const { return free_head_index_ == anchor_index_; }
+
+ wtf_size_t UsedFirstIndex() const {
+ return nodes_[anchor_index_].next_index_;
+ }
+ wtf_size_t UsedLastIndex() const { return nodes_[anchor_index_].prev_index_; }
+
+ iterator MakeIterator(wtf_size_t index) { return iterator(index, this); }
+ const_iterator MakeConstIterator(wtf_size_t index) const {
+ return const_iterator(index, this);
+ }
+ reverse_iterator MakeReverseIterator(wtf_size_t index) {
+ return reverse_iterator(index, this);
+ }
+ const_reverse_iterator MakeConstReverseIterator(wtf_size_t index) const {
+ return const_reverse_iterator(index, this);
+ }
+
+ bool IsIndexValid(wtf_size_t index) const {
+ return 0 <= index && index < nodes_.size();
+ }
+
+ bool IsAnchor(wtf_size_t index) const { return index == anchor_index_; }
+
+ void Unlink(const Node&);
+
+ VectorType nodes_;
+ static constexpr wtf_size_t anchor_index_ = 0;
+ // Anchor is not included in the free list, but it serves as the list's
+ // terminator.
+ wtf_size_t free_head_index_ = anchor_index_;
+ wtf_size_t size_ = 0;
+#if DCHECK_IS_ON()
+ int64_t modifications_ = 0;
+#endif
+
+ template <typename T, typename U>
+ friend class NewLinkedHashSet;
+};
+
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListIterator {
+ DISALLOW_NEW();
+ using ReferenceType = typename VectorBackedLinkedListType::Value&;
+ using PointerType = typename VectorBackedLinkedListType::Value*;
+ using const_iterator =
+ VectorBackedLinkedListConstIterator<VectorBackedLinkedListType>;
+
+ public:
+ ReferenceType operator*() const { return *Get(); }
+ PointerType operator->() const { return Get(); }
+
+ VectorBackedLinkedListIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+
+ VectorBackedLinkedListIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+
+ VectorBackedLinkedListIterator& operator++(int) = delete;
+ VectorBackedLinkedListIterator& operator--(int) = delete;
+
+ bool operator==(const VectorBackedLinkedListIterator& other) const {
+ return iterator_ == other.iterator_;
+ }
+
+ bool operator!=(const VectorBackedLinkedListIterator& other) const {
+ return !(*this == other);
+ }
+
+ operator const_iterator() const { return iterator_; }
+
+ private:
+ VectorBackedLinkedListIterator(wtf_size_t index,
+ VectorBackedLinkedListType* container)
+ : iterator_(index, container) {}
+
+ PointerType Get() const { return const_cast<PointerType>(iterator_.Get()); }
+ wtf_size_t GetIndex() const { return iterator_.GetIndex(); }
+
+ const_iterator iterator_;
+
+ template <typename T, typename Allocator>
+ friend class VectorBackedLinkedList;
+};
+
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListConstIterator {
+ DISALLOW_NEW();
+ using ReferenceType = const typename VectorBackedLinkedListType::Value&;
+ using PointerType = const typename VectorBackedLinkedListType::Value*;
+ using Node = typename VectorBackedLinkedListType::Node;
+
+ public:
+ PointerType Get() const {
+ DCHECK(container_->IsIndexValid(index_));
+ DCHECK(!container_->IsAnchor(index_));
+ CheckModifications();
+ const Node& node = container_->nodes_[index_];
+ return &node.value_;
+ }
+
+ ReferenceType operator*() const { return *Get(); }
+ PointerType operator->() const { return Get(); }
+
+ wtf_size_t GetIndex() const { return index_; }
+
+ VectorBackedLinkedListConstIterator& operator++() {
+ DCHECK(container_->IsIndexValid(index_));
+ CheckModifications();
+ index_ = container_->nodes_[index_].next_index_;
+ DCHECK(container_->IsIndexValid(index_));
+ return *this;
+ }
+
+ VectorBackedLinkedListConstIterator& operator--() {
+ DCHECK(container_->IsIndexValid(index_));
+ CheckModifications();
+ index_ = container_->nodes_[index_].prev_index_;
+ DCHECK(container_->IsIndexValid(index_));
+ return *this;
+ }
+
+ VectorBackedLinkedListConstIterator operator++(int) = delete;
+ VectorBackedLinkedListConstIterator operator--(int) = delete;
+
+ bool operator==(const VectorBackedLinkedListConstIterator& other) const {
+ DCHECK_EQ(container_, other.container_);
+ return index_ == other.index_ && container_ == other.container_;
+ }
+
+ bool operator!=(const VectorBackedLinkedListConstIterator& other) const {
+ return !(*this == other);
+ }
+
+ protected:
+ VectorBackedLinkedListConstIterator(
+ wtf_size_t index,
+ const VectorBackedLinkedListType* container)
+ : index_(index),
+ container_(container)
+#if DCHECK_IS_ON()
+ ,
+ container_modifications_(container->modifications_)
+#endif
+ {
+ DCHECK(container_->IsIndexValid(index_));
+ }
+
+ private:
+ wtf_size_t index_;
+ const VectorBackedLinkedListType* container_;
+#if DCHECK_IS_ON()
+ void CheckModifications() const {
+ container_->CheckModifications(container_modifications_);
+ }
+ int64_t container_modifications_;
+#else
+ void CheckModifications() const {}
+#endif
+
+ template <typename T, typename Allocator>
+ friend class VectorBackedLinkedList;
+ friend class VectorBackedLinkedListIterator<VectorBackedLinkedListType>;
+};
+
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListReverseIterator {
+ using ReferenceType = typename VectorBackedLinkedListType::Value&;
+ using PointerType = typename VectorBackedLinkedListType::Value*;
+ using const_reverse_iterator =
+ VectorBackedLinkedListConstReverseIterator<VectorBackedLinkedListType>;
+
+ public:
+ ReferenceType operator*() const { return *Get(); }
+ PointerType operator->() const { return Get(); }
+
+ VectorBackedLinkedListReverseIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+
+ VectorBackedLinkedListReverseIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+
+ VectorBackedLinkedListReverseIterator& operator++(int) = delete;
+ VectorBackedLinkedListReverseIterator& operator--(int) = delete;
+
+ bool operator==(const VectorBackedLinkedListReverseIterator& other) const {
+ return iterator_ == other.iterator_;
+ }
+
+ bool operator!=(const VectorBackedLinkedListReverseIterator& other) const {
+ return !(*this == other);
+ }
+
+ operator const_reverse_iterator() const { return iterator_; }
+
+ private:
+ VectorBackedLinkedListReverseIterator(wtf_size_t index,
+ VectorBackedLinkedListType* container)
+ : iterator_(index, container) {}
+
+ PointerType Get() const { return const_cast<PointerType>(iterator_.Get()); }
+ wtf_size_t GetIndex() const { return iterator_.GetIndex(); }
+
+ const_reverse_iterator iterator_;
+
+ template <typename T, typename Allocator>
+ friend class VectorBackedLinkedList;
+};
+
+template <typename VectorBackedLinkedListType>
+class VectorBackedLinkedListConstReverseIterator
+ : public VectorBackedLinkedListConstIterator<VectorBackedLinkedListType> {
+ using Superclass =
+ VectorBackedLinkedListConstIterator<VectorBackedLinkedListType>;
+
+ public:
+ VectorBackedLinkedListConstReverseIterator& operator++() {
+ Superclass::operator--();
+ return *this;
+ }
+
+ VectorBackedLinkedListConstReverseIterator& operator--() {
+ Superclass::operator++();
+ return *this;
+ }
+
+ VectorBackedLinkedListConstReverseIterator operator++(int) = delete;
+ VectorBackedLinkedListConstReverseIterator operator--(int) = delete;
+
+ private:
+ VectorBackedLinkedListConstReverseIterator(
+ wtf_size_t index,
+ const VectorBackedLinkedListType* container)
+ : Superclass(index, container) {}
+
+ template <typename T, typename Allocator>
+ friend class VectorBackedLinkedList;
+ friend class VectorBackedLinkedListReverseIterator<
+ VectorBackedLinkedListType>;
+};
+
+template <typename T, typename Allocator>
+VectorBackedLinkedList<T, Allocator>::VectorBackedLinkedList() {
+ // First inserts anchor, which serves as the beginning and the end of
+ // the used list.
+ nodes_.push_back(Node(anchor_index_, anchor_index_));
+}
+
+template <typename T, typename Allocator>
+inline void VectorBackedLinkedList<T, Allocator>::swap(
+ VectorBackedLinkedList& other) {
+ nodes_.swap(other.nodes_);
+ std::swap(free_head_index_, other.free_head_index_);
+ std::swap(size_, other.size_);
+#if DCHECK_IS_ON()
+ std::swap(modifications_, other.modifications_);
+#endif
+}
+
+template <typename T, typename Allocator>
+T& VectorBackedLinkedList<T, Allocator>::front() {
+ DCHECK(!empty());
+ return nodes_[UsedFirstIndex()].value_;
+}
+
+template <typename T, typename Allocator>
+const T& VectorBackedLinkedList<T, Allocator>::front() const {
+ DCHECK(!empty());
+ return nodes_[UsedFirstIndex()].value_;
+}
+
+template <typename T, typename Allocator>
+T& VectorBackedLinkedList<T, Allocator>::back() {
+ DCHECK(!empty());
+ return nodes_[UsedLastIndex()].value_;
+}
+
+template <typename T, typename Allocator>
+const T& VectorBackedLinkedList<T, Allocator>::back() const {
+ DCHECK(!empty());
+ return nodes_[UsedLastIndex()].value_;
+}
+
+template <typename T, typename Allocator>
+template <typename IncomingValueType>
+typename VectorBackedLinkedList<T, Allocator>::iterator
+VectorBackedLinkedList<T, Allocator>::insert(const_iterator position,
+ IncomingValueType&& value) {
+ RegisterModification();
+ wtf_size_t position_index = position.GetIndex();
+ wtf_size_t prev_index = nodes_[position_index].prev_index_;
+
+ wtf_size_t new_entry_index;
+ if (IsFreeListEmpty()) {
+ new_entry_index = nodes_.size();
+ nodes_.push_back(Node(prev_index, position_index,
+ std::forward<IncomingValueType>(value)));
+ } else {
+ new_entry_index = free_head_index_;
+ Node& free_head = nodes_[free_head_index_];
+ free_head_index_ = free_head.next_index_;
+ free_head = Node(prev_index, position_index,
+ std::forward<IncomingValueType>(value));
+ }
+ nodes_[prev_index].next_index_ = new_entry_index;
+ nodes_[position_index].prev_index_ = new_entry_index;
+ size_++;
+ return iterator(new_entry_index, this);
+}
+
+template <typename T, typename Allocator>
+typename VectorBackedLinkedList<T, Allocator>::iterator
+VectorBackedLinkedList<T, Allocator>::MoveTo(const_iterator target,
+ const_iterator new_position) {
+ DCHECK(target != end());
+ RegisterModification();
+
+ wtf_size_t target_index = target.GetIndex();
+ if (target == new_position)
+ return MakeIterator(target_index);
+
+ Node& target_node = nodes_[target_index];
+ wtf_size_t new_position_index = new_position.GetIndex();
+ Node& new_position_node = nodes_[new_position_index];
+ wtf_size_t prev_index = new_position_node.prev_index_;
+
+ if (prev_index == target_index)
+ return MakeIterator(target_index);
+
+ Unlink(target_node);
+
+ nodes_[prev_index].next_index_ = target_index;
+ new_position_node.prev_index_ = target_index;
+ target_node.prev_index_ = prev_index;
+ target_node.next_index_ = new_position_index;
+ return MakeIterator(target_index);
+}
+
+template <typename T, typename Allocator>
+typename VectorBackedLinkedList<T, Allocator>::iterator
+VectorBackedLinkedList<T, Allocator>::erase(const_iterator position) {
+ DCHECK(position != end());
+ RegisterModification();
+ wtf_size_t position_index = position.GetIndex();
+ Node& node = nodes_[position_index];
+ wtf_size_t next_index = node.next_index_;
+
+ Unlink(node);
+ node.value_ = HashTraits<T>::EmptyValue();
+
+ node.next_index_ = free_head_index_;
+ node.prev_index_ = kNotFound;
+ free_head_index_ = position_index;
+
+ size_--;
+ return iterator(next_index, this);
+}
+
+template <typename T, typename Allocator>
+void VectorBackedLinkedList<T, Allocator>::Unlink(const Node& node) {
+ wtf_size_t prev_index = node.prev_index_;
+ wtf_size_t next_index = node.next_index_;
+
+ Node& prev_node = nodes_[prev_index];
+ Node& next_node = nodes_[next_index];
+
+ prev_node.next_index_ = next_index;
+ next_node.prev_index_ = prev_index;
+}
+
+} // namespace WTF
+
+using WTF::VectorBackedLinkedList;
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_BACKED_LINKED_LIST_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list_test.cc b/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list_test.cc
new file mode 100644
index 00000000000..4d7b743c02b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector_backed_linked_list_test.cc
@@ -0,0 +1,508 @@
+// 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 "third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h"
+
+#include "base/memory/ptr_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_test_helper.h"
+
+namespace WTF {
+
+TEST(VectorBackedLinkedListTest, Insert) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ EXPECT_TRUE(list.empty());
+ EXPECT_TRUE(list.begin() == list.end());
+ list.insert(list.end(), 1);
+ list.insert(list.begin(), -2);
+ list.insert(list.end(), 2);
+
+ List::iterator it = list.begin();
+ EXPECT_EQ(*it, -2);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+
+ it = list.insert(++list.begin(), 0);
+ list.insert(it, -1);
+
+ EXPECT_EQ(list.front(), -2);
+ EXPECT_EQ(list.back(), 2);
+ EXPECT_EQ(list.size(), 5u);
+
+ int i = -2;
+ for (auto element : list) {
+ EXPECT_EQ(element, i);
+ i++;
+ }
+}
+
+TEST(VectorBackedLinkedList, PushFront) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ EXPECT_TRUE(list.empty());
+ list.push_front(3);
+ EXPECT_EQ(list.front(), 3);
+ list.push_front(2);
+ EXPECT_EQ(list.front(), 2);
+ list.push_front(1);
+ EXPECT_EQ(list.front(), 1);
+
+ int i = 1;
+ for (auto element : list) {
+ EXPECT_EQ(element, i);
+ i++;
+ }
+}
+
+TEST(VectorBackedLinkedList, PushBack) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ EXPECT_TRUE(list.empty());
+ list.push_back(1);
+ EXPECT_EQ(list.back(), 1);
+ list.push_back(2);
+ EXPECT_EQ(list.back(), 2);
+ list.push_back(3);
+ EXPECT_EQ(list.back(), 3);
+
+ int i = 1;
+ for (auto element : list) {
+ EXPECT_EQ(element, i);
+ i++;
+ }
+}
+
+TEST(VectorBackedLinkedList, MoveTo) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ list.push_back(1);
+ list.MoveTo(list.begin(), list.end());
+ List::iterator it = list.begin();
+ EXPECT_EQ(*it, 1);
+ list.push_back(2);
+ list.push_back(3);
+
+ List::iterator target = list.begin();
+ list.MoveTo(target, list.end()); // {2, 3, 1}
+
+ it = list.begin();
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ --it;
+
+ target = it;
+ list.MoveTo(target, list.begin()); // {3, 2, 1}
+ it = list.begin();
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 1);
+
+ target = it;
+ list.MoveTo(target, --it); // {3, 1, 2}
+ it = list.begin();
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+
+ list.MoveTo(list.begin(), list.begin());
+ it = list.begin();
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+
+ target = list.begin();
+ List::iterator position = ++list.begin();
+ list.MoveTo(target, position);
+ it = list.begin();
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+}
+
+TEST(VectorBackedLinkedList, Erase) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ List::iterator it = list.insert(list.end(), 1);
+ EXPECT_EQ(*it, 1);
+ list.push_back(2);
+ list.push_back(3);
+ list.push_back(4);
+ list.push_back(5);
+ EXPECT_EQ(list.size(), 5u);
+
+ int i = 1;
+ for (auto element : list) {
+ EXPECT_EQ(element, i);
+ i++;
+ }
+
+ List::iterator target = list.begin();
+ ++target;
+ it = list.erase(target); // list = {1, 3, 4, 5}
+ EXPECT_EQ(*it, 3);
+ EXPECT_EQ(list.size(), 4u);
+ it = list.erase(++it); // list = {1, 3, 5}
+ EXPECT_EQ(*it, 5);
+ EXPECT_EQ(list.size(), 3u);
+
+ it = list.erase(list.begin()); // list = {3, 5}
+ EXPECT_EQ(*it, 3);
+ EXPECT_EQ(list.size(), 2u);
+
+ it = list.begin();
+ EXPECT_EQ(*it, 3);
+ ++it;
+ EXPECT_EQ(*it, 5);
+ ++it;
+ EXPECT_TRUE(it == list.end());
+
+ list.push_back(6);
+ EXPECT_EQ(list.front(), 3);
+ EXPECT_EQ(list.back(), 6);
+}
+
+TEST(VectorBackedLinkedList, PopFront) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ list.push_back(1);
+ list.push_back(2);
+ list.push_back(3);
+
+ int i = 1;
+ for (auto element : list) {
+ EXPECT_EQ(element, i);
+ i++;
+ }
+
+ list.pop_front();
+ EXPECT_EQ(list.front(), 2);
+ EXPECT_EQ(list.back(), 3);
+ EXPECT_EQ(list.size(), 2u);
+
+ list.pop_front();
+ EXPECT_EQ(list.front(), 3);
+ EXPECT_EQ(list.back(), 3);
+ EXPECT_EQ(list.size(), 1u);
+
+ list.pop_front();
+ EXPECT_TRUE(list.empty());
+}
+
+TEST(VectorBackedLinkedList, PopBack) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ list.push_back(1);
+ list.push_back(2);
+ list.push_back(3);
+
+ list.pop_back();
+ EXPECT_EQ(list.front(), 1);
+ EXPECT_EQ(list.back(), 2);
+ EXPECT_EQ(list.size(), 2u);
+
+ list.pop_back();
+ EXPECT_EQ(list.front(), 1);
+ EXPECT_EQ(list.back(), 1);
+ EXPECT_EQ(list.size(), 1u);
+
+ list.pop_back();
+ EXPECT_TRUE(list.empty());
+}
+
+TEST(VectorBackedLinkedList, Clear) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ list.push_back(1);
+ list.push_back(2);
+ list.push_back(3);
+
+ EXPECT_EQ(list.size(), 3u);
+
+ list.clear();
+ EXPECT_EQ(list.size(), 0u);
+ EXPECT_TRUE(list.empty());
+
+ EXPECT_TRUE(list.begin() == list.end());
+ list.push_back(1);
+ EXPECT_EQ(list.front(), 1);
+ EXPECT_EQ(list.back(), 1);
+ EXPECT_EQ(list.size(), 1u);
+}
+
+TEST(VectorBackedLinkedList, Iterator) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ list.push_back(1);
+ list.push_back(2);
+ list.push_back(3);
+
+ List::iterator it = list.begin();
+
+ EXPECT_EQ(*it, 1);
+ ++it;
+ EXPECT_EQ(*it, 2);
+ ++it;
+ EXPECT_EQ(*it, 3);
+ *it = 4; // list: {1, 2, 4}
+ EXPECT_EQ(list.back(), 4);
+ ++it;
+ EXPECT_TRUE(it == list.end());
+ --it;
+ --it;
+ --it;
+ EXPECT_TRUE(it == list.begin());
+ EXPECT_EQ(list.front(), 1);
+ *it = 0;
+ EXPECT_EQ(list.front(), 0); // list: {0, 2, 4}
+
+ List::reverse_iterator rit = list.rbegin();
+
+ EXPECT_EQ(*rit, 4);
+ ++rit;
+ EXPECT_EQ(*rit, 2);
+ ++rit;
+ EXPECT_EQ(*rit, 0);
+ EXPECT_FALSE(rit == list.rend());
+ *rit = 1; // list: {1, 2, 4}
+ EXPECT_EQ(list.front(), 1);
+ ++rit;
+ EXPECT_TRUE(rit == list.rend());
+ --rit;
+ EXPECT_EQ(*rit, 1);
+}
+
+TEST(VectorBackedLinkedList, ConstIterator) {
+ using List = VectorBackedLinkedList<int>;
+ List list;
+
+ list.push_back(1);
+ list.push_back(2);
+ list.push_back(3);
+
+ List::const_iterator cit = list.cbegin();
+
+ EXPECT_EQ(*cit, 1);
+ ++cit;
+ EXPECT_EQ(*cit, 2);
+ ++cit;
+ EXPECT_EQ(*cit, 3);
+ ++cit;
+ EXPECT_TRUE(cit == list.cend());
+ --cit;
+ --cit;
+ --cit;
+ EXPECT_TRUE(cit == list.cbegin());
+ EXPECT_EQ(list.front(), 1);
+
+ List::const_reverse_iterator crit = list.crbegin();
+
+ EXPECT_EQ(*crit, 3);
+ ++crit;
+ EXPECT_EQ(*crit, 2);
+ ++crit;
+ EXPECT_EQ(*crit, 1);
+ ++crit;
+ EXPECT_TRUE(crit == list.crend());
+ --crit;
+ EXPECT_EQ(*crit, 1);
+}
+
+TEST(VectorBackedLinkedList, String) {
+ using List = VectorBackedLinkedList<String>;
+ List list;
+
+ EXPECT_TRUE(list.empty());
+
+ list.push_back("b");
+ list.push_front("a");
+ list.push_back("c");
+
+ EXPECT_EQ(list.front(), "a");
+ EXPECT_EQ(list.back(), "c");
+ EXPECT_EQ(list.size(), 3u);
+
+ List::iterator it = list.begin();
+ EXPECT_EQ(*it, "a");
+ ++it;
+ EXPECT_EQ(*it, "b");
+ List::iterator target = it;
+ ++it;
+ EXPECT_EQ(*it, "c");
+ ++it;
+ EXPECT_TRUE(it == list.end());
+ --it;
+ EXPECT_EQ(*it, "c");
+ --it;
+ --it;
+ EXPECT_TRUE(it == list.begin());
+
+ list.erase(target);
+ it = list.begin();
+ EXPECT_EQ(*it, "a");
+ ++it;
+ EXPECT_EQ(*it, "c");
+ ++it;
+ EXPECT_TRUE(it == list.end());
+
+ list.pop_back();
+ EXPECT_EQ(list.front(), "a");
+ EXPECT_EQ(list.back(), "a");
+ EXPECT_EQ(list.size(), 1u);
+
+ list.push_front("c");
+ it = list.begin();
+ EXPECT_EQ(*it, "c");
+ ++it;
+ EXPECT_EQ(*it, "a");
+ ++it;
+ EXPECT_TRUE(it == list.end());
+
+ list.clear();
+ EXPECT_TRUE(list.empty());
+ EXPECT_TRUE(list.begin() == list.end());
+
+ list.push_front("a");
+ EXPECT_EQ(list.size(), 1u);
+ EXPECT_EQ(list.front(), "a");
+ list.pop_back();
+ EXPECT_TRUE(list.empty());
+}
+
+TEST(VectorBackedLinkedList, UniquePtr) {
+ using List = VectorBackedLinkedList<std::unique_ptr<Dummy>>;
+ List list;
+
+ bool deleted1 = false, deleted2 = false, deleted3 = false;
+ std::unique_ptr<Dummy> ptr1 = std::make_unique<Dummy>(deleted1);
+ std::unique_ptr<Dummy> ptr2 = std::make_unique<Dummy>(deleted2);
+ std::unique_ptr<Dummy> ptr3 = std::make_unique<Dummy>(deleted3);
+
+ Dummy* raw_ptr1 = ptr1.get();
+ Dummy* raw_ptr2 = ptr2.get();
+ Dummy* raw_ptr3 = ptr3.get();
+
+ list.push_front(std::move(ptr1));
+ list.push_back(std::move(ptr3));
+ List::iterator it = list.begin();
+ ++it;
+ it = list.insert(it, std::move(ptr2));
+ EXPECT_EQ(it->get(), raw_ptr2);
+
+ EXPECT_EQ(list.size(), 3u);
+ EXPECT_EQ((list.front()).get(), raw_ptr1);
+ EXPECT_EQ((list.back()).get(), raw_ptr3);
+
+ it = list.begin();
+ EXPECT_EQ(it->get(), raw_ptr1);
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr2);
+ List::iterator target = it;
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr3);
+ ++it;
+ EXPECT_TRUE(it == list.end());
+ --it;
+ EXPECT_EQ(it->get(), raw_ptr3);
+ --it;
+ --it;
+ EXPECT_TRUE(it == list.begin());
+
+ list.erase(target);
+ EXPECT_FALSE(deleted1);
+ EXPECT_TRUE(deleted2);
+ EXPECT_FALSE(deleted3);
+ EXPECT_EQ(list.size(), 2u);
+ it = list.begin();
+ EXPECT_EQ(it->get(), raw_ptr1);
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr3);
+ ++it;
+ EXPECT_TRUE(it == list.end());
+
+ list.pop_front();
+ EXPECT_TRUE(deleted1);
+ EXPECT_TRUE(deleted2);
+ EXPECT_FALSE(deleted3);
+ EXPECT_EQ(list.size(), 1u);
+ it = list.begin();
+ EXPECT_EQ(it->get(), raw_ptr3);
+ ++it;
+ EXPECT_TRUE(it == list.end());
+
+ list.pop_back();
+ EXPECT_TRUE(deleted1);
+ EXPECT_TRUE(deleted2);
+ EXPECT_TRUE(deleted3);
+ EXPECT_TRUE(list.empty());
+
+ bool deleted4 = false, deleted5 = false, deleted6 = false;
+ std::unique_ptr<Dummy> ptr4 = std::make_unique<Dummy>(deleted4);
+ std::unique_ptr<Dummy> ptr5 = std::make_unique<Dummy>(deleted5);
+ std::unique_ptr<Dummy> ptr6 = std::make_unique<Dummy>(deleted6);
+
+ Dummy* raw_ptr4 = ptr4.get();
+ Dummy* raw_ptr5 = ptr5.get();
+ Dummy* raw_ptr6 = ptr6.get();
+
+ list.push_back(std::move(ptr4));
+ list.push_back(std::move(ptr5));
+ list.push_back(std::move(ptr6));
+
+ it = list.end();
+ --it;
+ list.MoveTo(list.begin(), it);
+ it = list.begin();
+ EXPECT_EQ(it->get(), raw_ptr5);
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr4);
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr6);
+
+ list.MoveTo(list.begin(), list.begin());
+ it = list.begin();
+ EXPECT_EQ(it->get(), raw_ptr5);
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr4);
+ ++it;
+ EXPECT_EQ(it->get(), raw_ptr6);
+
+ EXPECT_FALSE(deleted4);
+ EXPECT_FALSE(deleted5);
+ EXPECT_FALSE(deleted6);
+
+ list.clear();
+ EXPECT_TRUE(list.empty());
+ EXPECT_EQ(list.size(), 0u);
+
+ EXPECT_TRUE(deleted4);
+ EXPECT_TRUE(deleted5);
+ EXPECT_TRUE(deleted6);
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc b/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc
index 788cc2bb12d..1e5fd403ed8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc
@@ -101,22 +101,34 @@ TEST(VectorTest, EraseAtIndex) {
}
TEST(VectorTest, Erase) {
- Vector<int> int_vector({0, 1, 2, 3});
+ Vector<int> int_vector({0, 1, 2, 3, 4, 5});
- EXPECT_EQ(4u, int_vector.size());
+ EXPECT_EQ(6u, int_vector.size());
EXPECT_EQ(0, int_vector[0]);
EXPECT_EQ(1, int_vector[1]);
EXPECT_EQ(2, int_vector[2]);
EXPECT_EQ(3, int_vector[3]);
+ EXPECT_EQ(4, int_vector[4]);
+ EXPECT_EQ(5, int_vector[5]);
auto* first = int_vector.erase(int_vector.begin());
- EXPECT_EQ(3u, int_vector.size());
+ EXPECT_EQ(5u, int_vector.size());
EXPECT_EQ(1, *first);
EXPECT_EQ(int_vector.begin(), first);
- auto* last = std::lower_bound(int_vector.begin(), int_vector.end(), 3);
+ auto* last = std::lower_bound(int_vector.begin(), int_vector.end(), 5);
auto* end = int_vector.erase(last);
+ EXPECT_EQ(4u, int_vector.size());
+ EXPECT_EQ(int_vector.end(), end);
+
+ auto* item2 = std::lower_bound(int_vector.begin(), int_vector.end(), 2);
+ auto* item4 = int_vector.erase(item2, item2 + 2);
EXPECT_EQ(2u, int_vector.size());
+ EXPECT_EQ(4, *item4);
+
+ last = std::lower_bound(int_vector.begin(), int_vector.end(), 4);
+ end = int_vector.erase(last, int_vector.end());
+ EXPECT_EQ(1u, int_vector.size());
EXPECT_EQ(int_vector.end(), end);
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf.cc b/chromium/third_party/blink/renderer/platform/wtf/wtf.cc
index c98254eec1d..c928e55082b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf.cc
@@ -45,23 +45,13 @@
namespace WTF {
bool g_initialized;
-void (*g_call_on_main_thread_function)(MainThreadFunction, void*);
base::PlatformThreadId g_main_thread_identifier;
-namespace internal {
-
-void CallOnMainThread(MainThreadFunction* function, void* context) {
- (*g_call_on_main_thread_function)(function, context);
-}
-
-} // namespace internal
-
bool IsMainThread() {
return CurrentThread() == g_main_thread_identifier;
}
-void Initialize(void (*call_on_main_thread_function)(MainThreadFunction,
- void*)) {
+void Initialize() {
// WTF, and Blink in general, cannot handle being re-initialized.
// Make that explicit here.
CHECK(!g_initialized);
@@ -75,7 +65,6 @@ void Initialize(void (*call_on_main_thread_function)(MainThreadFunction,
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
internal::GetDoubleConverter();
- g_call_on_main_thread_function = call_on_main_thread_function;
internal::InitializeMainThreadStackEstimate();
AtomicString::Init();
StringStatics::Init();
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf.h b/chromium/third_party/blink/renderer/platform/wtf/wtf.h
index 5bd960aa773..418cfca41eb 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf.h
@@ -36,18 +36,13 @@
namespace WTF {
-typedef void MainThreadFunction(void*);
WTF_EXPORT extern base::PlatformThreadId g_main_thread_identifier;
// This function must be called exactly once from the main thread before using
// anything else in WTF.
-WTF_EXPORT void Initialize(void (*)(MainThreadFunction, void*));
+WTF_EXPORT void Initialize();
WTF_EXPORT bool IsMainThread();
-namespace internal {
-void CallOnMainThread(MainThreadFunction*, void* context);
-} // namespace internal
-
} // namespace WTF
using WTF::IsMainThread;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h b/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
index 8f31365dcd0..35b1e73c81f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_WTF_TEST_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_WTF_TEST_HELPER_H_
+#include <type_traits>
+
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -177,6 +179,75 @@ struct DefaultHash<CountCopy> {
using Hash = CountCopyHash;
};
+template <typename T>
+class ValueInstanceCount final {
+ public:
+ ValueInstanceCount() : counter_(nullptr), value_(T()) {}
+ explicit ValueInstanceCount(int* counter, T value = T())
+ : counter_(counter), value_(value) {
+ DCHECK(counter_);
+ *counter = 1;
+ }
+ ValueInstanceCount(const ValueInstanceCount& other)
+ : counter_(other.counter_), value_(other.value_) {
+ if (counter_)
+ ++*counter_;
+ }
+ ValueInstanceCount& operator=(const ValueInstanceCount& other) {
+ counter_ = other.counter_;
+ value_ = other.value_;
+ if (counter_)
+ ++*counter_;
+ return *this;
+ }
+ ~ValueInstanceCount() {
+ if (counter_)
+ --*counter_;
+ }
+
+ const int* Counter() const { return counter_; }
+ const T& Value() const { return value_; }
+
+ private:
+ int* counter_;
+ T value_;
+};
+
+template <typename T>
+struct ValueInstanceCountHashTraits
+ : public GenericHashTraits<ValueInstanceCount<T>> {
+ static const bool kEmptyValueIsZero = false;
+ static const bool kHasIsEmptyValueFunction = true;
+ static bool IsEmptyValue(const ValueInstanceCount<T>& value) {
+ return !value.Counter();
+ }
+ static void ConstructDeletedValue(ValueInstanceCount<T>& slot, bool) {}
+ static bool IsDeletedValue(const ValueInstanceCount<T>& value) {
+ return false;
+ }
+};
+
+template <typename T>
+struct ValueInstanceCountHash : public PtrHash<const int*> {
+ static unsigned GetHash(const ValueInstanceCount<T>& value) {
+ return PtrHash<const int>::GetHash(value.Counter());
+ }
+ static bool Equal(const ValueInstanceCount<T>& left,
+ const ValueInstanceCount<T>& right) {
+ return PtrHash<const int>::Equal(left.Counter(), right.Counter());
+ }
+ static const bool safe_to_compare_to_empty_or_deleted = true;
+};
+
+template <typename T>
+struct HashTraits<ValueInstanceCount<T>>
+ : public ValueInstanceCountHashTraits<T> {};
+
+template <typename T>
+struct DefaultHash<ValueInstanceCount<T>> {
+ using Hash = ValueInstanceCountHash<T>;
+};
+
class DummyRefCounted : public RefCounted<DummyRefCounted> {
public:
DummyRefCounted(bool& is_deleted) : is_deleted_(is_deleted) {